📄 virus.txt
字号:
加密变形病毒是虚拟机一章的重点内容,将放到相关章节中介绍。
1.2.5反跟踪/反虚拟执行病毒
反跟踪/反虚拟执行病毒和虚拟机联系密切,所以也将放到相应的章节中介绍。
1.2.6直接API调用
直接API调用是当今WIN32病毒常用的手段,它指的是病毒在运行时直接定位API函数在内存中的入口地址然后调用之的一种技术。普通程序进行API调用时,编译器会将一个API调用语句编译为几个参数压栈指令后跟一条间接调用语句(这是指Microsoft编译器,Borland编译器使用JMP
DWORD PTR [XXXXXXXXh])形式如下:
push arg1
push arg2
……
call dword ptr[XXXXXXXXh]
地址XXXXXXXXh在程序映象的导入(Import Section)段中,当程序被加载运行时,由装入器负责向里面添入API函数的地址,这就是所谓的动态链接机制。病毒由于为了避免感染一个可执行文件时在文件的导入段中构造病毒体代码中用到的API的链接信息,它选择运用自己在运行时直接定位API函数地址的代码。其实这些函数地址对于操作系统的某个版本是相对固定的,但病毒不能依赖于此。现在较为流行的做法是先定位包含API函数的动态连接库的装入基址,然后在其导出段(Export Section)中寻找到需要的API地址。后面一步几乎没有难度,只要你熟悉导出段结构即可。关键在于第一步--确定DLL装入地址。其实系统DLL装入基址对于操作系统的某个版本也是固定的,但病毒为确保其稳定性仍不能依赖这一点。目前病毒大都利用一个叫做结构化异常处理的技术来捕获病毒体引发的异常。这样一来病毒就可以在一定内存范围内搜索指定的DLL(DLL使用PE格式,头部有固定标志),而不必担心会因引发页面错误而被操作系统杀掉。
由于异常处理和后面的反虚拟执行技术密切相关,所以特将结构化异常处理简单解释如下:
共有两类异常处理:最终异常处理和每线程异常处理。
其一:最终异常处理
当你的进程中无论哪个线程发生了异常,操作系统将调用你在主线程中调用SetUnhandledExceptionFilter建立的异常处理函数。你也无须在退出时拆去你安装的处理代码,系统会为你自动清除。
PUSH OFFSET FINAL_HANDLER
CALL SetUnhandledExceptionFilter
……
CALL ExitProcess
;************************************
FINAL_HANDLER:
……
;(eax=-1 reload context and continue)
MOV EAX,1
RET ;program entry point
……
;code covered by final handler
……
;code to provide a polite exit
……
;eax=1 stops display of closure box
;eax=0 enables display of the box
其二:每线程异常处理
FS中的值是一个十六位的选择子,它指向包含线程重要信息的数据结构TIB,线程信息块。其的首双字节指向我们称为ERR的结构:
1st dword +0 pointer to next err structure
(下一个err结构的指针)
2nd dword +4 pointer to own exception handler
(当前一级的异常处理函数的地址)
所以异常处理是呈练状的,如果你自己的处理函数捕捉并处理了这个异常,那么当你的程序发生了异常时,操作系统就不会调用它缺省的处理函数了,也就不会出现一个讨厌的执行了非法操作的红叉。
下面是cih的异常段:
MyVirusStart:
push ebp
lea eax, [esp-04h*2]
xor ebx, ebx
xchg eax, fs:[ebx] ;交换现在的err结构和前一个结构的地址
; eax=前一个结构的地址
; fs:[0]=现在的err结构指针(在堆栈上)
call @0
@0:
pop ebx
lea ecx, StopToRunVirusCode-@0[ebx] ;你的异常处理函数的偏移
push ecx ;你的异常处理函数的偏移压栈
push eax ;前一个err结构的地址压栈
;构造err结构,记这时候的esp(err结构指针)为esp0
……
StopToRunVirusCode:
@1 = StopToRunVirusCode
xor ebx, ebx ;发生异常时系统在你的练前又加了一个err结构,
;所以要先找到原来的结构地址
mov eax, fs:[ebx] ; 取现在的err结构的地址eax
mov esp, [eax] ; 取下个结构地址即eps0到esp
RestoreSE: ;没有发生异常时顺利的回到这里,你这时的esp为本esp0
pop dword ptr fs:[ebx] ;弹出原来的前一个结构的地址到fs:0
pop eax ;弹出你的异常处理地址,平栈而已
1.2.7病毒隐藏
实现进程或模块隐藏应该是一个成功病毒所必须具备的特征。在WIN9X下Kernel32.dll有一个可以使进程从进程管理器进程列表中消失的导出函数RegisterServiceProcess ,但它不能使病毒逃离一些进程浏览工具的监视。但当你知道这些工具是如何来枚举进程后,你也会找到对付这些工具相应的办法。进程浏览工具在WIN9X下大都使用一个叫做ToolHelp32.dll的动态连接库中的Process32First和Process32Next两个函数来实现进程枚举的;而在WINNT/2000里也有PSAPI.DLL导出的EnumProcess可用以实现同样之功能。所以病毒就可以考虑修改这些公用函数的部分代码,使之不能返回特定进程的信息从而实现病毒的隐藏。
但事情远没有想象中那么简单,俗话说“道高一尺,魔高一丈”,此理不谬。由于现在很多逆项工程师的努力,微软力图隐藏的许多秘密已经逐步被人们所挖掘出来。当然其中就包括WINDOWS内核使用的管理进程和模块的内部数据结构和代码。比如WINNT/2000用由ntoskrnl.exe导出的内核变量PsInitialSystemProcess所指向的进程Eprocess块双向链表来描述系统中所有活动的进程。如果进程浏览工具直接在驱动程序的帮助下从系统内核空间中读出这些数据来枚举进程,那么任何病毒也无法从中逃脱。
有关Eprocess的具体结构和功能,请参看David A.Solomon和Mark E.Russinovich的《Inside Windows2000》第三版。
1.2.8病毒特殊感染法
对病毒稍微有些常识的人都知道,普通病毒是通过将自身附加到宿主尾部(如此一来,宿主的大小就会增加),并修改程序入口点来使病毒得到击活。但现在不少病毒通过使用特殊的感染技巧能够使宿主大小及宿主文件头上的入口点保持不变。
附加了病毒代码却使被感染文件大小不变听起来让人不可思议,其实它是利用了PE文件格式的特点:PE文件的每个节之间留有按簇大小对齐后的空洞,病毒体如果足够小则可以将自身分成几份并分别插入到每个节最后的空隙中,这样就不必额外增加一个节,因而文件大小保持不变。著名的CIH病毒正是运用这一技术的典型范例(它的大小只有1K左右)。
病毒在不修改文件头入口点的前提下要想获得控制权并非易事:入口点不变意味着程序是从原程序的入口代码处开始执行的,病毒必须要将原程序代码中的一处修改为导向病毒入口的跳转指令。原理就是这样,但其中还存在很多可讨论的地方,如在原程序代码的何处插入这条跳转指令。一些查毒工具扫描可执行文件头部的入口点域,如果发现它指向的地方不正常,即不在代码节而在资源节或重定位节中,则有理由怀疑文件感染了某种病毒。所以刚才讨论那种病毒界称之为EPO(入口点模糊)的技术可以很好的对付这样的扫描,同时它还是反虚拟执行的重要手段。
另外值得一提的是现在不少病毒已经支持对压缩文件的感染。如Win32.crypto病毒就可以感染ZIP,ARJ,RAR,ACE,CAB 等诸多类型的压缩文件。这些病毒的代码中含有对特定压缩文件类型解压并压缩的代码段,可以先把压缩文件中的内容解压出来,然后对合适的文件进行感染,最后再将感染后文件压缩回去并同时修改压缩文件头部的校验和。目前不少反病毒软件都支持查多种格式的压缩文件,但对有些染毒的压缩文件无法杀除。原因我想可能是怕由于某种缘故,如解压或压缩有误,校验和计算不对等,使得清除后压缩文件格式被破坏。病毒却不用对用户的文件损坏负责,所以不存在这种担心。
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -