|
病毒专区 | 安全 | 1113 次查看 | |
|---|---|---|---|
|
|||
本文假定你对dos下的病毒和386PM有一定的了解。 1、感染任何一个病毒都需要有寄主,把病毒代码加入寄主程序中 (伴侣病毒除外)。 以下说明如何将病毒代码嵌入PE文件中,有关PE文件的结构请看以前的文章。 PE文件的典型结构:MZ Header DOS STUB CODE PE HEADER OPTIONAL HEADER SECTION TABLE SECTION 1 SECTION 2 ... IMPORT TABLE EXPORT TABLE 和DOS的可执行文件类似,PE的代码映象分为几个SECTION,在文件中会对齐页边界(4K)。一般来说,文件会加载在400000h开始的空间,而第一个SECTION在401000h处,同时入口地址也是401000h。由高级语言编写的程序,每个SECTIO-N的长度不可能刚好是4K的倍数,因此在SECTION的末尾将会存在一段未用的空间 , 大小可由Section的PHYSICAL SIZE-VIRTUALSIZE得到,在文件中起始位置可由 PHYSICAL OFFSET得到,这段空间可以用来存放病毒代码。此外一般来说,MZ Header+DOS STUD+PEHEADER+OPTIONAL HEADER+SECTION TABLE不过1K左右,而SECTION 1由4K开始,空出来的地方足够存放一个设计精良的病毒。CIH就是将代码存放在这些空闲空间里。 2、分配驻留所需内存 对于驻留形的病毒,分配驻留所需内存是必需的。在DOS下使用由于所有的 应用程序都映射在相同的线性地址空间里,使用一般的内存分配调用就足够了。而在WIN32下,每个应用程序都有自己的线性地址空间,必须使用特殊的函数分配2GB以上的系统地址。典型的如:VXD服务_PageAllocate,和kernel32的 VxDCALL _PageReserve。_PageAllocate请参看win98ddk中的说明,VxDCall _PageReserve 请参看HPS源码中的注释。 3、截留FILE I/O操作 驻留型的病毒通过截留FILE I/O来激活,可以通过使用VXD服务 IFSMgr_Install-FileSystemAPIHook(如CIH)或截留VxDCall中的DOS Services callback(如HPS)。 在Win32下编写病毒不是一件困难的事。值得注意的有几件事: 一、Win32下的系统功能调用不是通过中断实现,而是由DLL中导出。 (直接使用VxD服务除外)。直接在病毒中得到API入口不是一件容易的事,可以通过以下这个变通的方法。 在同一个版本的Windows下,同一个核心函数的入口总是固定的(指由Kernel32,gdi32,user32导出的函数)。因此可以用以下的方法得到函数入口:
在Intialize Code得到要用的函数入口并将它填入病毒中,在病毒运行时可以直接使用了。 二:主要是要截留文件I/O操作。 Windows下截留文件I/O操作有几种方法,在病毒中使用的主要有两种。 1、使用VxDCallIFSMgr_InstallFileSystemHook 2、截留Kernel32.dll中导出的第一个函数VxDCall对DOS INT 21的呼叫(EAX=2A0010)。 VxDCall的代码如下: mov eax,dword ptr [esp+04] pop dword ptr [esp] call fword ptr cs:[xxxxxxxx] ^^^^^^^^只要将这个地址指向的地址改为自己的过程入口,就捕获了所有的VxDCall。 进入这个过程时: eax=service number,如果是DOS INT 21将是2A0010 esp[2c]d调用Int 21时eax的值 ~~~~ 算漏了个pushad,应该是10h esp[30] 调用int 21时ecx的值 ~~~~14h 其他寄存器为调用时所需的值。(段寄存器无用) 以后的就和在DOS下写病毒没什么差别了。 在WINDOWS下写病毒,如何得到API的入口是一件麻烦的事. 可以直接使用的API都在DLL中,而VXDCALL要在RING0时才能使 用,DOS的INT 21服务也不能直接调用. 得到DLL中的API入口有两种方法: 1.加载时得到,建立一个 IMPORT TABLE,在加载时WINDOWS会根据IMPORT TABLE定位API的 入口地址.这是一般应用程序的使用的方法,但不大适合病毒. 2.运行时得到,使用GetModuleHandle和GetProcAddress得到API的入口,但前提时要知道GetModuleHandle和GetProcAddress的 入口地址.:< 这是明显也是不可能的.除了将GetModuleHandle和GetProcAddress的代码复制到我们的病毒中,只有使用暴力在 2GB的空间内找出API的入口了. 首先说明一下WINDOWS的内存映射,由00000000开始有一段是 无效地址(我忘了到底到多少了),用来捕获应用程序错误的指针. 跟着一直到0x7FFFFFFF为应用程序的空间.0X80000000以后为系统 的空间,DLL和VXD都映射在这里.我们要作的就是从这2GB的空间内找到Krnl32.dll. 一般来说,Windows下的程序都是对齐在64k的边界.首先是MZ 文件头,跟着是由MZ HEADER中的信息可以得到PE HEADER的入口. 由这个标记就可以找出所有的DLL.由PE HEADER可以得到DLL的 EXPORT TABLE的入口,其中而NAME PTR TABLE的第一项为DLL的名 称,由此可以找出Krnl32.dll,并从ADDRESS TABLE中得到任何一个 API的入口. 值得注意的是,在这2GB中并不是所有而地址都是有效的,在 一般的程序中可以通过IsXXXXXPtr来判断地址是否有效,但在病毒 中不行.只能Hook Exception,忽略访问无效的地址导致的Exception. Windows中的Exception Chain的结构如下: fs:[0] dword exception发生时esp的新值,该值指向一个如下 的结构 [esp] dword fs:[0]的新值 [esp+4] dword exception handler的入口 [esp+8] dword exception handler使用的数据首地址 [esp+12] dword -1详细的汇编代码可以用C写一段__try...__except的代码,然后 转译成汇编. 只要我们的exception handler直接跳转到病毒中寻找Krnl32.dll 的代码,就可以不引起GP Error而访问任何的地址了. 范例可以参看HPS的源码,PE HEADER,EXPORT TABLE请参看PE FORMAT. 1、在Windows下载入的DLL在不同的process中映射到同一个地址。 2、在DLL中导出的函数在export table中记录相对DLL Image Base 的偏移,改变这个偏移使用GetProcAddress得到的地址就会改变。 (想象一下,把CreateProcess地址指向自己的DLL中的函数,或者截获GetDlgItemText来记录Password) 3、在Kernel32.DLL中Section Table在0x300以前就结束了,而真正的代码由0x1000处开始,其间有3K的未用空间,可以用来存放我们的代码。 Kernel32.DLL的Image Base可以由GetModuleHandleA得到。 4、在任何版本的Windows中,3个基本的DLL总是被加载(Kernel32.DLL,User32.DLL,GDI32.DLL),而且对于同一个版本的Windows,它们的Image Base,和导出函数的地址总是固定的。可以将得到的地址直接用于病毒使用。 |
|||