|
|
楼主 |
发表于 2009-5-16 00:06:14
|
显示全部楼层
消息来自- 北京
第三章 COM病毒的清除
一 实现原理
COM文件是DOS的一种二进制代码的可执行文件,COM文件结构比较简单,加载过程十分迅速.整个程序只有一个段.因此全部代码长度必须小于64K,其入口代码地址是CS:100H. DOS装入COM文件时,先在内存建立一个长度为100H的程序前缀段(PSP,由DOS建立,是DOS用户程序和命令行之间的接口),然后将整个文件装载于PSP上端,不进行重定位操作,接着将四个段地址寄存器DS(Data Segment),CS(Code Segment),SS(Stack Segment),ES(Extra Segment)初始化为程序前缀段(PSP)的段地址,最后将程序的控制权交于CS:100H处.如表1所示.
表1: COM文件的装入执行
地址
内容
XXXX:0000
PSP
← CS,DS,ES,SS
XXXX:0100
程序代码
← IP
数据
堆栈
← SP
寄生于COM文件的病毒,大部分是采用保存文件头若干字节,并将第一条指令改为”JMP 病毒入口”,以确保病毒最先执行,也有部分病毒附加在文件首部,病毒执行完后恢复寄生程序原先的状态,并用JMP FAR等指令使程序再次回到CS:100H处,以确保寄生程序与PSP的一致.
可见,病毒执行完后,必将会恢复并运行原文件,以便传播,当其将原文件参数全部恢复后,会将控制权交于CS:100H处.因此,判别COM文件的真正入口的标准是:最后一次在CS:100H处执行的程序段(CS=当前PSP段地址,IP=100H).
于是,可以设想出这样一种跟踪器,每执行一条指令,便判断上述条件是否满足,如果满足,则此时CS:100H处的代码便是原文件的影像,由于COM文件只有一个段,因此此时内存的影像既是磁盘文件的内容.将CS:100H处的代码写回原文件,此病毒即被消除了,如果知道病毒的长度,还可将文件尾的无用代码去掉,这样病毒就物理上消除了.
二 实现方案
设想的跟踪器的实现是核心问题,也是主要的难点.事实上单步陷阱中断(INT 1)完全符合跟踪器的条件,但由于目前的计算机病毒广泛采取破坏单步断点的技术,因此这种跟踪器在具体实现上还有一定难度.
目前有一种比较方便的替代方法,即DOS的EXEC(INT 21H的功能4BH,加载执行)功能,此功能有一个有趣的现象,即执行完加载程序后,它会将所有寄存器恢复到执行前的状态,并且它不清除内存,此方法易于实现,操作简便,但对所处理的文件有一定的要求及限制.
具体实现是,先保存中断向量表,然后在分配一块内存,调用DOS的EXEC功能执行被感染的COM文件.执行结束后,重写中断向量表以清除内存中的病毒,然后将内存偏移100H上的代码写入文件,文件长度为原文件长度,最后,在知晓病毒长度的情况下去掉文件尾的病毒代码,清除工作结束.
这种技术可以对付任何一种文件型病毒,但对??COM文件却有一定的要求:即文件在执行过程中不可以修改代码段的内容,未被加密或压缩的文件一般均可满足此条件.
四 使用调试器DEBUG.COM的EXEC功能
更简单的方法是用DEBUG来实现,先用L命令装入一个文件,再用G命令运行,EXEC功能结束后,返回寄存器与运行前完全一样,此时用W命令存盘,这时病毒便被清除了.(全过程只用了三条命令)
第四章 EXE病毒的清除
一 实现原理
EXE文件是DOS系统最为常见且灵活的可执行文件,其应璀¨十分广泛.但EXE文件的结构要比COM文件复杂得多.EXE文件由文件头(Header)和装入模块(Load Module)两大部分组成.文件头由格式化区(Format Area)和重定位表(Relocation Table)组成.装入模块为程序代码部分,从位移量100H字节开始.DOS系统在调用EXE文件时,先在内存块底部建立一个程序前缀段(PSP),再将装入模块读入内存指定区域(PSP上方),DS和ES初始化为PSP段地址,CS,IP,SS,SP由文件头格式化区确定,并通过重定位参数调整.然后根据重定位项修改代码数据,最后将程序的控制权由CS:IP传递给目标程序. (如表2所示)
表2: EXE文件的装入执行
地址
内容
XXXX:0000
PSP
← DS,ES
XXXX:0100
数据
程序代码
← CS:IP
堆栈
← SS:SP
对于EXE文件而言,计算机病毒主要是附着于宿主文件的尾部,由于它必须首先获得程序的控制权,因此它必须对文件头进行修改.一般来说,只要恢复了正确的文件头,便可达到杀毒的目的.
EXE文件被加载时,系统根据EXE文件头的CS:IP参数确定第一条执行语句,因此病毒只需将CS:IP地址指针修改,便可首先执行,事实上,大多数病毒仅仅只修改了文件头,而未修改原文件内容.这便为完整地恢复原程序代码提供了条件.
从上面的分析可知,感染病毒的EXE文件尾部形成明显的层次,CS:IP指向病毒体,不管病毒采取什么样的措施,它最终必定会在内存中恢复宿主程序所有的真实参数,并且用一条长跳转指令返回原程序.这时,我们便可直接提取出正确的CS:IP和SS:SP参数指针,用它修改文件头后,再将外层病毒代码去掉,这便彻底地恢复了原EXE文件.
问题在于如何找到EXE文件的正确入口.判断EXE文件的真正入口是十分复杂的,但对于基于DOS系统的病毒来说,其编写语种基本上是汇编语言,因此便具有一些独特的特点.经过大量分析看出,一般情况下,当EXE病毒执行到真正的文件开头时,其CS和DS均要改变,并且DS内容必定是PSP段地址,SS:SP指针被初始化,对于不修改重定位表的病毒来说,CS:IP指针应处于重定位区域内.
于是,可以再设想出这样一种跟踪器,每执行一条指令,便判断上述条件是否满足,如果满足,则此时CS:IP处的代码便是原文件的影像,根据CPU各个寄存器的内容便可正确地恢复EXE文件头,以达到杀毒的目的.
二 实现方案
同COM文件杀毒一样,这种理论上的跟踪器实际上是很难奏效的.因此,我们又要求助于我们的老朋友--EXEX功能.
MS DOS的功能4B有两个重要的子功能:4B00为装入并执行,4B01为装入不执行(未公开的文档功能),4B00用于执行所有的可执行程序,4B01则用于DEBUG调试器中的装入功能.(关于4B01功能的具体参数见附录1).
由于问题的关键在于如何找到原程序的第一条指令,也就是说在执行到原程序的第一条指令时发生中断,因此我们可以人为地将第一条指令改为中断指令.为了完成这种功能,只需用4B01功能来仿真4B00功能.
具体是这样做的,当系统调用加载执行功能4B00时,先用功能4B01加载,并初试化所有参数,这时内存的影像应如表3所示.
表3: EXE 染毒程序内存影像
地址
内容
原程序代码区
CS:IP→
病毒代码区
假定病毒的第一条指令处于病毒代码的最前端,原程序的内存影像应为PSP:100~CS:IP(病毒的第一条指令),将这部分区域全部用ASCII码CD填充.这样,原程序的每一条指令都变成了中断指令INT CD(不用INT 3断点中断是因为大部分病毒都具有破坏单步断点中断的功能),也就是说,无论从原程序的任何地址开始运行,所执行的第一条指令都是INT CD.这样,一旦病毒代码执行完毕,打算用长跳转指令返回原程序执行时,都会触发软中断INT CD,而通过INT CD的中断服务程序便可取得EXE文件头真正的初始化CS:IP和SS:SP指针.
另外值得注意的是,修改后的INT 21必须是可递归的,因为有些病毒(如新世纪病毒)是通过第二次加载原程序来返回的,因此,内存填充要进行两次.4B01也被调用了两次.
此方法的效率和准确度要远远高于用DEBUG等工具逐步跟踪分析的手工杀毒法.可以为各种染上已知或未知病毒的文件去除病毒外壳.与RCOPY等去壳程序不同的是,这种方法对EXE程序的恢复是全真的恢复,它并不改变原EXE文件的任何内容.它所恢复的EXE程序代码应与原EXE程序代码完全一样.另外,此法由于采用了剥壳还原法,因此还可以用来清除交叉感染的病毒,方法是从外到内逐层脱壳,最后彻底恢复最内层的宿主文件.
第五章 结论
本文所论述的这种清除病毒的方法的实现原理是非常独特的.当然,文中所给出的实现方案并不能清除所有的计算机病毒,但它却给出了一种思想,即抛弃以前那种一个杀毒算法只能杀一个病毒,而是一个算法可以杀一类病毒.根据这种思想,笔者已用C语言和汇编语言编写出这个通用杀病毒程序,并且用大量的病毒对它进行了测试,效果良好.当然,病毒是五花八门的,因此一个统一的病毒对抗软件应接受广泛的考验.其具体的功效还需要多方面的验证,笔者也仅仅希望这种思想能够在反病毒领域发挥出积极的作用. |
|