1966年前后,Robert Morris Sr.,这位后来的美国国家安全局(National Security Agency,NSA)首席科学家,决定跟他的两个朋友Victor Vyssotsky和Dennis Ritchie共同开发一个新的游戏环境,他们编写了游戏代码并将其命名为达尔文(Darwin)。(Morris Sr.的儿子Morris Jr.,是计算机病毒史上第一位声名狼藉的蠕虫作者。我们将会在本书的后面讨论他在计算机病毒历史上的所作所为。)
Darwin的最初版本是在贝尔实验室为PDP-1(程序数据处理机)设计的。不久之后,Darwin演变成了磁芯大战(Core War),这是一个至今仍然有许多程序员和数学家(当然还有“黑客”)玩的电脑游戏。
注释我在这里使用“黑客”这一术语原始的、正面的意思。我同样认为所有好的病毒研究者都是传统意义上的“黑客”。我把自己也当作一名黑客,不过与那些入侵别人计算机的恶意黑客是有根本区别的。
这个游戏被称做磁芯大战(Core War)是因为游戏的目标是通过覆盖对手的程序而将其“杀”掉。最初的游戏是在两个用一种被称作Redcode的汇编语言编写的程序之间展开的。Redcode程序是在一种被称作“内存阵列Redcode模拟器”(MARS)的模拟机器(例如“虚拟机”)内存(即core,当时采用磁芯core作为计算机的内存储器)中执行的。对战程序之间的“战斗”,称作磁芯大战。
最初的Redcode指令集由10条简单的指令组成,这些指令可以把内存中某地址的信息转移到其他位置,为编写各种微妙的对战程序提供了很大的灵活性。从1984年5月开始,Dewdney在《Scientific American》(科学美国人)[13,14]上发表了数篇关于“电脑娱乐”的文章,来讨论磁芯大战。图1-7是一个正在执行的被称作PMARSV的磁芯大战游戏的截屏,PMARSV是由AlbertMa,Na'ndor Sieben,Stefan Strack和Mintardjo Wangsaw共同开发的。观看一个个小的磁芯大战“战士”在MARS的环境里互相“打斗”是相当有趣的。 | [tr][/tr] 在每年的程序对战比赛中,总会有一些“战士”成为“山头”的国王(King of the Hill,KotH),这就是那些能够胜过其对手的Redcode程序。
一个名为MICE的对战程序赢得了首届的比赛,它的作者Chip Wendell获得的奖品是一块早期的CDC 6600计算机上的内存板[14]。
最简单的Redcode程序仅仅由一条MOV指令组成:MOV 0,1(按照传统的语法)。这个程序被称作IMP,它把内存中相对地址为0处的内容(也就是MOV这条指令本身)转移到相对地址为1的内存处,也就是这条指令的下一个地址。当这条指令被复制到了这个新的地址后,控制也交给了这个地址,于是这一指令又一次被执行,又将其自己复制到更高一位的地址上去,如此反复。这一切的发生都是很自然的,因为每条指令执行后,指令指针总会自动加一,于是系统自然的依次执行高一位地址处的指令。
基本的磁芯(core,指内存)中包括两个对战程序和8000个用来存放指令的单元,游戏新的修改版本可以同时允许有多个对战程序。对战程序的起始大小是有明确限制的,通常是100条指令。每个程序可以反复执行的次数是有限的,默认情况下是80 000次。
最初的Redcode版本包含了10条指令,后来的版本包含了更多的指令。例如,清单1-1中列出了1994年的修订版本中使用的14条指令。 | [tr][/tr]
| [tr][/tr]
| [tr][/tr] Dwarf使用了一种称作炸弹的策略。最初的几行是注释,指出这一对战程序的名字,并且遵从Redcode的1994年的标准。Dwarf通过向其对手程序的执行路径上“投掷”DAT炸弹,以试图破坏对手的程序。由于MARS虚拟机中所有进程如果试图执行DAT语句时将被终止,因此当Dwarf击中对手后,Dwarf就可能赢了。
MOV是用来将信息移动到MARS单元中去的指令。(IMP对战程序可以很清楚地解释这一点。)一条Redcode指令的一般格式是:操作码 A,B。因此指令MOV.AB #0,@-2将指向作为源地址的Dwarf程序代码中的DAT语句。
A域指向DAT语句,每条指令的所占的空间都等于1,在内存地址0处是DAT #0,#0。因此,MOV指令将会将DAT指令复制到B指向的内存地址处。而B现在指向哪里呢?
B指向它里面的DAT.F #0,#0语句。通常,这意味着炸弹将会放置在这个语句的上面,但是@符号把它后面的操作数变成一个间接的指针。也就是说,@符号表示使用B域指向地址处的内容作为一个新的指针(指向目的地址)。在这种情况下,地址B处的内容好像是指向地址0(地址0,也就是存放DAT.F指令的地方)。
然而,在MOV之前要先执行一个ADD指令。当ADD #4,$-1执行后,DAT中的偏移地址(也就是ADD指令相对偏移地址为-1处。—译者注)会每次增加4—第一次从0变成4,第二次从4变成8,如此反复。
这就是为什么当MOV指令复制DAT炸弹时,炸弹(Data指令。—译者注)会被放置到DAT语句后面的第4行处(见清单1-3)。 | [tr][/tr] JMP.A$-2指令将程序的执行转移到相对偏移地址-2处,也就是回到ADD指令,从而使Dwarf程序“永无休止”的运行下去。Dwarf不断地向内存中每4个地址投放一个炸弹,直到指针“绕”内存一圈。(当到达了投放DAT炸弹的最高可能达到的地址后,地址将会“绕”回来,又从0地址重新开始。例如,如果地址的最大值是10,那么10+1意味着0,而10+4意味着3。)
以后,Dwarf开始在它投放过炸弹的地方重新投放炸弹,直到程序反复执行80 000次,或者其他的对战程序将Dwarf覆盖。不过,其他的对战程序可以很轻易的杀掉Dwarf,因为Dwarf总是停留在一个不变的位置上—以便不被自己的“火力”所击中,但这样却将自己暴露给其他的攻击程序。
在磁芯大战中通常包含以下几种策略:扫描、复制、投放炸弹、IMP螺旋(spiral)(使用MARS的SPL指令来实现)。另外还有一个更有意思的炸弹变种叫做吸血鬼(vampire)。Dewdney程序还证明,一个程序可以通过截获对手程序的执行流,从而“偷走”对手程序的“灵魂”,这需要向对方的内存中投掷JMP(跳转)指令炸弹,这种程序被称做吸血鬼。通过投放跳转指令炸弹,可以将敌人的程序控制“抢”过来,从而指向一个新的、预先定义好的位置,通常会让被“抢”的对战程序开始执行无用的代码。无用的代码可以扰乱敌人程序的执行思路,从而使吸血鬼程序占得先机。
我强烈建议大家去玩这种无害的、非常有趣的游戏,而不是去编写计算机病毒。实际上,如果你对蠕虫感兴趣,那么可以开发一个新版本的磁芯大战,这个版本的磁芯大战可以将位于不同网络的对战程序联结到一起,允许一个对战程序从某个战场跳到其他的战场去,在别的机器上跟新的敌人进行对战。游戏的联网特性允许出现像蠕虫一样的对战程序。
|