计算机病毒史:安全防御的极限博弈

从特征码到沙箱技术,一场关于不确定性的底层攻防

slashslashdev·

计算机病毒史:安全防御的极限博弈

1983 年 11 月,美国南加州大学的一间机房里,研究生 Fred Cohen 在一台 VAX-11/750 计算机上完成了一次后来被认为具有里程碑意义的实验。

他编写了一段代码,并将其嵌入一个普通程序中,使这段代码能够借助宿主程序运行,在执行过程中复制自身,并感染其他程序。实验开始不到八小时,这段程序便获得了整台计算机的控制权。

Cohen 的导师 Leonard Adleman(RSA 算法共同发明者之一)注意到了这种程序与生物病毒之间的相似之处,于是借用了生物学中的概念,将其命名为“计算机病毒”(computer virus)。

不过,真正让 Cohen 的研究进入计算机科学史的,并不是这段实验代码本身,而是他随后提出的一个理论问题:

是否存在一种算法,可以准确判断任意一个程序是否具有病毒性质?

答案是否定的。

这种“不可能”并不是因为当时的计算能力不足,也不是工程实现尚未成熟,而是来自计算理论本身的限制。

Cohen 的证明采用了经典的反证法。

假设存在一个能够识别所有病毒的完美检测程序,那么就可以构造出另一个程序,让它根据检测程序的判断结果采取相反行动。这样一来,无论检测程序给出什么结论,最终都会产生逻辑矛盾。

在数学意义上,不存在一个能够对所有程序行为做出正确判断的万能检测算法。

这个问题与图灵(Alan Turing)提出的停机问题属于同一类理论困境:有些问题并不是暂时无法解决,而是在数学层面不存在通用解法。

这个结论,成为计算机安全领域一个特殊的起点。

计算机安全从诞生之初就知道自己无法达到完美,却依然发展成了一个庞大的技术产业。

几十年来,无数安全研究人员和工程师围绕病毒检测、代码分析和防御体系展开研究,与不断变化的恶意程序持续竞争。

既然不存在覆盖所有程序的完美检测方法,安全行业所做的事情,便是在理论划定的边界之内,不断提高发现和控制风险的能力。

这也成为此后计算机安全技术演进的一条核心线索:恶意程序不断寻找新的隐藏方式,检测技术不断探索新的识别方法,两者在持续博弈中推动整个行业向前发展。

一、病毒诞生之前

在计算机病毒真正出现之前,自我复制程序的概念已经存在于理论研究之中。

病毒并不是某位程序员突然产生的奇思妙想,而是建立在计算机科学早期对于“机器是否能够复制自身”这一问题的长期探索之上。

1949 年,冯·诺依曼(John von Neumann)在关于“自我复制自动机”的系列讲座中提出了一个问题:

一台机器是否能够制造出另一台与自己完全相同的机器?

他的答案是肯定的。

冯·诺依曼指出,自我复制系统的关键在于:用于复制的信息必须同时承担两种角色。

它既要作为“指令”被执行,用来指导新结构的构造;又要作为“数据”被复制,并传递给新的副本。

这一思想后来成为理解自我复制系统的重要理论基础。

不过,从理论模型到真正运行在计算机上的程序,中间仍然经历了二十多年的发展。

1971 年,一个名为 Creeper 的实验程序出现在 ARPANET 上。

它能够在网络中的计算机之间自行传播,并在感染后的机器上留下这样一句提示:

“I’m the Creeper, catch me if you can!”

(我是 Creeper,有本事来抓我。)

Creeper 并不是为了破坏系统而设计,它更像是一次关于网络程序传播能力的实验。

但很快,人们开发出了另一个程序来寻找并删除它——Reaper。

从今天来看,这场对抗还远没有达到后来恶意软件与安全软件之间的复杂程度。

Creeper 没有明显的破坏行为,Reaper 也只是一个实验性的清除工具。

但它们第一次展现了计算机安全领域最基本的模式:

一种能够传播的程序出现后,人们便开始研究如何发现它、分析它,并最终清除它。

到了 1983 年,Fred Cohen 对计算机病毒进行了正式定义,并通过理论证明指出了病毒检测所面临的边界。

但此时,计算机病毒仍然停留在研究领域。

真正让这一理论概念进入现实世界的,是个人计算机的普及。

随着 IBM PC 等个人电脑进入家庭和企业,软件开始通过软盘等介质广泛传播。

程序复制变得越来越容易,而早期软件生态中缺乏安全机制的问题也逐渐暴露出来。

在这样的环境下,病毒第一次成为普通计算机用户必须面对的问题。

这个历史性的转折点,来自巴基斯坦拉合尔的一家小型电脑店,以及一款由两兄弟编写的程序——Brain。

二、第一个广泛传播的 PC 病毒,与早期查杀方法

1986 年,巴基斯坦的 Amjad 和 Basit 两兄弟编写出了 Brain 程序。

它通常被认为是第一个广泛传播的 IBM PC 病毒,标志着计算机病毒第一次真正进入普通用户的视野。

Brain 的诞生动机并非出于破坏或牟利。

两兄弟经营着一家销售医疗软件的公司,但当地盗版现象严重。为了追踪软件未经授权的传播情况,他们编写了 Brain,希望借此了解究竟有多少人在使用盗版软件。

出于这种目的,Brain 并没有设计强烈的破坏性。

它感染软盘的引导扇区,将磁盘卷标修改为“©Brain”,但不会删除用户文件,也不会刻意破坏数据。病毒代码中甚至保留了作者的真实姓名、公司地址和联系电话,并附上一段“如果感染,请联系我们”的信息。

两兄弟最初或许没有意识到,这个原本为解决本地版权问题设计的小程序,会随着软盘的物理流通传播到世界各地。

随着越来越多用户受到影响,他们很快便接到了来自不同国家的大量投诉电话。

Brain 之所以能够大范围传播,与它选择的感染位置密切相关。

在早期个人计算机中,系统启动时,BIOS 会首先读取存储设备的第一个扇区,也就是引导扇区(boot sector),并将其中的内容加载到内存中执行。

整个过程发生在操作系统启动之前。

因此,控制引导扇区,就意味着程序能够在操作系统加载之前获得执行机会。

Brain 正是利用了这一机制。

它将自身代码写入软盘引导扇区,替换原本的启动信息。随后,它利用 TSR(Terminate and Stay Resident,终止并驻留)机制,让自身继续留存在内存中,并拦截磁盘访问请求。

当用户插入新的软盘时,Brain 就能够在用户没有察觉的情况下完成复制。

这种不直接攻击操作系统,而是将自身嵌入系统启动流程中的设计,成为早期病毒的重要思路。

Brain 的另一个重要特点,是采用了早期的隐形技术(stealth)。

当检测程序读取感染区域时,Brain 会拦截这一操作,并返回事先保存的原始内容,让检查者看到一个看似正常的结果。

它并没有阻止检查,而是控制了检查结果。

这种隐藏真实状态的设计,后来成为许多隐形病毒的重要技术基础。

Brain 出现之后,计算机病毒开始快速增加,相应的检测和清除工具也逐渐出现。

1987 年前后,德国程序员 Bernd Fix 成功分析并清除了 Vienna 病毒;随后,后来发展为 ESET 的斯洛伐克团队、德国 G Data 等安全厂商也相继推出了相关产品。

这一时期,杀毒技术仍处于早期阶段。

安全人员通常是在发现新病毒后,分析其代码,再编写对应的专用清除工具。

随着病毒数量不断增长,如何让针对单个病毒的临时方案发展为普通用户也能使用的通用检测工具,成为新的挑战。

推动这一转变的人之一是 John McAfee。

他的主要贡献并不在于提出全新的检测算法,而在于推动了杀毒技术的产品化和商业化。

他将针对单个病毒的检测能力整合到统一的软件中,并通过共享软件(Shareware)模式推广产品。

病毒检测自此不再只是安全研究人员的实验工具,而开始成为日常计算环境中的基础软件。

早期杀毒软件的核心逻辑,是建立病毒特征库。

当分析人员发现一种新病毒后,会从中提取一段具有代表性的字节序列,并保存为检测规则。

扫描程序检查文件时,如果匹配到这些特征码(signature),就认为文件可能已经感染。

在 20 世纪 80 年代末,这套方法非常有效。

人类第一次拥有了能够自动、大规模识别计算机病毒的手段。

但这套机制完全依赖于病毒固有的静态特征。

病毒作者很快意识到,只要改变自身代码中的部分字节序列,就可能让依靠固定特征的检测方法失效。

这一思路,开启了随后十余年间计算机病毒与杀毒技术之间最激烈的一轮技术博弈。

三、十年攻防:加密、多态与变形

特征码检测的普及,让病毒与杀毒技术在 20 世纪 80 年代末到 90 年代中期进入快速迭代阶段。

双方围绕信息隐藏、代码混淆和行为识别展开持续竞争,技术演进大致经历了三个阶段:加密、多态和变形。

第一阶段:加密病毒

最早出现的突破方式,是对病毒主体进行加密。

一个加密病毒通常由两部分组成:一小段负责解密的代码,以及被加密隐藏的病毒主体。

平时,病毒主体只是无法直接读取的密文,传统扫描器无法通过特征匹配识别它;只有病毒开始运行后,解密代码才会将主体恢复为可执行状态。

20 世纪 80 年代末出现的 Cascade 病毒,就是这一阶段的代表之一。

这种设计最初成功绕过了特征码检测,但缺陷也很快暴露。

病毒主体可以隐藏,但解密代码本身必须保持明文可执行,否则病毒无法完成自身运行。

于是,安全人员调整了检测策略:不再寻找被加密的病毒主体,而是关注负责解密的那段程序。

Cascade 正是在这一点上被突破。

虽然它会根据被感染文件的大小生成不同的密钥,但解密代码的逻辑始终保持稳定。只要识别出这段固定的解密程序,杀毒软件依然能够判断病毒的存在。

第二阶段:多态病毒

既然固定的解密代码会暴露身份,多态病毒(polymorphic virus)便出现了。

多态病毒在传播过程中会动态改变代码结构。

它自身包含一个变形引擎(mutation engine),能够在每次感染新文件时重新生成不同形式的解密代码。

它可能使用不同的加密密钥,改变指令排列方式,或者插入无意义的代码干扰分析。

结果是,即使两个文件感染的是同一种病毒,它们在二进制层面也可能完全不同,传统特征码依赖的稳定特征逐渐消失。

1990 年,Mark Washburn 开发的 1260 病毒(又名 Chameleon)证明,如果病毒能够动态改变自身结构,依赖静态代码片段的检测方法将面临巨大挑战。

面对多态病毒,安全研究人员不得不改变方向:

既然无法可靠识别病毒的外观,那就观察它运行时的行为。

这推动了模拟执行和沙箱技术的发展。

杀毒引擎会在隔离的虚拟环境中运行可疑程序。当多态病毒执行解密过程,并尝试恢复主体代码时,其真实行为便可能暴露出来。

但新的问题随之出现:

病毒必须在分析环境中表现出真实意图。

如果病毒能够察觉自己正在被观察,并选择隐藏行为呢?

第三阶段:变形病毒

变形病毒(metamorphic virus)采取了更加彻底的方式。

它不再隐藏一个固定的病毒主体,而是直接重写自身的整个代码结构。

每次传播时,变形病毒都会生成一个新的版本。

它可以调整指令顺序,替换等价操作,插入大量冗余代码,再通过跳转指令恢复原有逻辑。

最终,不同副本之间可能不存在固定的代码形式,但执行的却是同一种功能。

Simile 病毒就是这一阶段的典型代表。

它包含约一万四千行汇编代码,其中约九成代码用于实现变形机制,而不是执行攻击行为。

它的大部分复杂度,都被用于不断改变自身外观,以隐藏真实逻辑。

面对没有固定形态的对手,检测技术不得不跳出静态比对的框架,将关注点转移到程序的具体行为上。

这推动了启发式分析(heuristic analysis)与行为监控的发展。

启发式分析不再依赖固定字节,而是通过扫描可疑的代码结构和指令组合,判断程序是否具有潜在风险。

行为监控则进一步延伸到动态运行阶段,通过内核钩子等技术观察程序是否尝试修改引导扇区、注入系统进程,或频繁调用敏感系统接口。

这种方法不要求安全软件提前认识每一种病毒,而是试图判断一个程序的行为模式是否符合恶意程序的特征。

持续的循环

病毒改变隐藏方式,检测技术便调整识别方法。

当检测技术开始关注行为,病毒又开始检测运行环境,尝试隐藏自身行为。

计算机病毒与杀毒技术的发展,并不是一条通往最终胜利的直线。

每一次防御技术升级都会提升检测能力,但始终无法产生一种能够覆盖所有可能程序的完美方案。

这也印证了 Fred Cohen 在理论层面指出的问题:

工程可以不断进步,但完美检测永远不存在。

四、理论的边界与工程的实践

随着病毒技术越来越难以分析,有人开始怀疑,Fred Cohen 提出的“不可判定问题”是否正在现实中被验证。

答案是否定的。

这里有一个经常被混淆的边界:多态和变形病毒虽然大幅提高了静态分析的难度,但这属于工程上的复杂性问题,而不是理论上的不可行。

只要病毒运行起来,沙箱和动态分析仍然有机会捕获它。

“检测成本高昂”和“理论上无法检测”,是两个完全不同的问题。

Cohen 证明的是数学和逻辑意义上的极限:不存在一种万能算法,能够对任意程序是否具有病毒性质做出始终正确的预判。

而现实中的杀毒软件面对的,是有限范围内、不断变化的实际威胁。

安全研究人员并不需要解决“所有可能存在的病毒”这一命题,而是在现实约束下,尽可能提高防御成功的概率。

特征码可以快速识别已知威胁,启发式分析能够发现未知风险,沙箱可以观察程序运行行为,而现代机器学习和威胁情报则尝试从海量样本中总结规律。

这些方法都不是完美方案,但它们足以在现实世界中显著降低安全风险。

理论上的不可判定,并没有阻止工程上的持续进步。

有趣的是,在几乎同一时期,地球另一端的中国计算机研究者,也开始面对类似的技术问题,并展开了具有本土特色的早期探索。

五、中国的同期探索

中国的计算机病毒史,常常在后来的大众记忆中被简化为一场商业竞争——瑞星、江民、金山等厂商在市场中展开竞争,随后又受到互联网免费安全模式的冲击。

但如果抛开商业竞争的视角,中国早期安全研究者面对的技术命题,与世界其他地区几乎一致。

他们同样需要回答几个核心问题:

如何判断一个程序是否具有病毒特征?

如何在未知威胁出现之前发现风险?

当病毒不断改变自身结构时,检测技术又该如何应对?

专家系统的探索

1992 年 8 月,一篇题为《计算机病毒判定专家系统原理与设计》的论文发表在中文核心期刊《计算机研究与发展》上,作者署名为“雷军,武汉大学计算机系”。

这篇论文讨论的问题,与当时全球安全领域正在探索的方向高度接近:

如果无法依靠固定特征识别所有病毒,是否可以利用规则和经验建立一种更智能的判断方式?

论文尝试设计一个计算机病毒判定专家系统。

该系统通过规则库保存安全专家对于病毒行为的经验,再结合已知病毒档案,对未知程序进行分析和判断。

这种思路与传统特征码检测存在明显区别。

特征码关注的是:

“这个程序是否包含某段已知病毒代码?”

而专家系统试图回答:

“这个程序的行为是否符合病毒的一般规律?”

放到今天来看,这更像是一次从“识别已知样本”走向“推断未知风险”的早期探索。

它面对的问题,仍然属于 Cohen 理论边界之内的工程尝试:通过经验、规则和分析方法,尽可能提高判断未知程序的能力。

识别病毒家族:KV 系列的实践

如果说雷军的论文探索的是理论方向,那么江民公司的王江民,则是在实际产品中尝试解决另一个问题:

如何让检测技术在不断变化的病毒环境中保持有效。

王江民开发的 KV 系列杀毒软件,是 1990 年代中国个人电脑安全领域的重要产品。

与当时许多依赖单一特征码的检测方式相比,KV 系列在技术演进上的一个重要实践,是尝试从病毒样本中提炼更加普遍的规律。

这一点,在“上海系列”病毒与 KV300 的攻防中表现得十分明显。

当时,有匿名作者陆续编写针对 KV300 的挑衅性病毒。

“上海 1 号”出现后,很快被 KV300 查杀。随后,作者修改病毒发作信息,推出“上海 2 号”,将提示内容改成与 KV300 相关的挑衅文字,但依然被识别清除。

到了“上海 3 号”,作者进一步改变表面特征,直接将发作信息改成了王江民姓名的拼音:“Wangjiangmin”。

如果按照传统特征码思路,病毒每改变一次表面特征,安全软件就需要增加一个对应的静态规则。

但王江民采取了另一种方法。

他没有继续追踪每一个具体版本,而是分析这些病毒之间共有的底层结构,并编写了一组针对这一类病毒的“广谱代码”。

此后,无论病毒作者如何修改表面的字符信息,都难以绕过这种基于共同结构的检测方式。

这里的“广谱代码”,体现了特征码技术的一次重要演进。

传统特征码更像精确匹配,而广谱检测会利用通配、掩码等方式,寻找一类病毒共有的结构特征。

检测目标也从:

“这个病毒具体是什么样?”

变成:

“这一类病毒无论如何变化,都无法摆脱哪些共同特征?”

这与后来安全领域从单一样本检测走向病毒家族识别的方向高度一致。

硬件层的冲击:CIH 病毒

1998 年出现的 CIH 病毒,展示了恶意软件如何进一步突破当时防御体系的边界。

CIH 与早期主要破坏文件或修改数据的病毒不同,CIH 在技术设计上深入到了系统底层,其中两个特点尤其受到安全界关注。

第一个特点,是它采用了“空洞感染(cavity infection)”技术。

传统病毒感染 Windows 可执行文件时,通常会将自身代码附加到文件末尾,导致文件体积明显增加,容易被用户或安全软件察觉。

而 CIH 利用了 Windows PE 文件格式的结构特点,将约 1KB 左右的病毒代码拆分成多个碎片,隐藏在 PE 文件不同节区之间由于对齐产生的空余空间中。

这些空间通常被称为“空洞”。

这种设计使被感染文件的大小几乎不会发生变化,从而绕过了一些依赖文件体积变化判断感染情况的检测方式。

第二个特点,也是 CIH 最具破坏性的设计,是它能够修改主板 Flash BIOS 中的固件内容。

在部分采用特定芯片组(如 Intel 430TX),且没有启用 BIOS 写保护的计算机上,CIH 会向 BIOS 存储区域写入破坏性数据。

由于最底层的引导程序遭到破坏,计算机开机时甚至可能无法完成自检流程(POST)。

从用户角度看,这种情况已经非常接近硬件损坏。

1999 年 4 月 26 日,CIH 大规模爆发后,全球大量计算机受到影响。其中部分机器因 BIOS 损坏无法正常启动,需要通过重新刷写固件恢复。

据作者后来透露,编写该病毒的动机之一,是为了挑战当时被过度宣传的杀毒软件能力。

CIH 的出现推动安全攻防进一步向系统底层发展。

从巴基斯坦的 Brain,到中国的 KV 系列,再到 CIH 对硬件层面的冲击,技术路线虽然不同,但最终都指向了同一个现实:

在一个无法达到绝对安全的世界里,防御体系必须持续适应新的攻击方式。

结语:与不确定性共处

计算机安全技术的演进,是一场漫长的长跑。

它始于冯·诺依曼纸面上的自我复制自动机,随后变成隐藏在软盘扇区里的真实代码。

当防御者用静态特征码筑起防线时,病毒用多态和变形突破限制,进而迫使整个安全产业转向基于行为分析的动态防御。

这场对抗注定没有终局。

早在 1983 年,Fred Cohen 就用数学划定了一条名为“不可能”的边界。

但过去几十年的网络安全发展证明,无法达到完美,并不意味着无法前进。

工程师们在这条边界之内不断探索,将一个理论上不可解的问题,转化为现实世界中可以评估、可以控制的风险。

杀毒技术的发展史,本质上就是人类在数字世界中,逐渐学会与不确定性共处的过程。

MalwareCybersecurityComputer History
🧑‍💻

开发者周报

关注技术的新变化