计算机病毒分析与对抗————2、PE文件

1、PE文件定义

PE即(Portable Executable,可移植的执行体),它是Win32可执行文件的标准格式。

2、PE文件结构

总共五部分:DOS头、PE文件头、节表、节,调试信息。

Dos头:

由MZ文件头以及DOS插桩程序构成,其实际上就是一个在DOS环境下显示“Thisprogram can not be run in DOS  mode”或“This program must be run  under Win32”之类信息的小程序。
MZ文件以“4D5A”开头。在DOS插桩程序的最后会给出PE文件头的起始位置。


PE文件头:

PE文件头由 PE文件标准、映像头文件、可选映像头文件构成

PE文件标准————“PE\0\0”————“50\45\00\00”标志着PE文件头的开始。

映像头文件


其中NumberOfSection、SizeOfOptionHeader对于计算机病毒来说是非常重要的,知道SizeOfOptionHeader后就可以知道节表的开始位置。病毒通过刚才得到的节表的开始位置和节的个数就可以确定最后一个节表的末尾地址(每个节是28H个字节),这样在添加新节时,我们就可以找到新节表应该所在的位置。

计算机病毒如何得知一个文件是不是PE文件?
首先看该文件的前两个字节是不是4D5A,如果不是,则说明该文件不是PE文件,如果是,那么我们可以在DOS头中的找到字串的偏移位置(e_ifanew.然后查看该偏移位置的前4个字节是否是50\45\00\00,如果不是,说明不是PE文件,如果是,则说明是PE文件。

可选映像头文件:位于映像头文件,这是一个可选的结构。



节表:
节表紧跟在PE文件头之后,该PE文件有多少个节则对应有几个节表,节表其实就是对相应节的描述,包括描述节的名字,实际大小,在文件中的位置,映射到内存后再内存中的位置,节的属性(可读可写可执行等)。每个节表占用28H字节,即40Byte。
EXE一般都有几个字,最常见的是代码节,数据节和引入函数节,而DLL一般会有引出函数节。

常见的节:
代码节、已初始化的数据节、未初始化的数据节、引入函数节、引出函数节、资源节

节的属性:

节的属性代表了该节所在内存区块的权限,其中每一位都代表了一种权限或属性的开启或关闭。


例如:800000000H就表示这段内存是可写的    400000000H就表示这段内存是可读的

代码节的属性一般为:600000020H————可执行、可读和“节中包含代码”

数据节的属性一般为:C00000040H————可读、可写、“包含已初始化数据”

PE装载器工作流程:

  • 获取文件节的数目(NumberOfSection)
  • 定位节表(SizeOfHeaders)
  • 获得该节在磁盘上的存储位置以及大小
  • 把该节映射进内存(VirtualAddress  ImageBase)
  • 设置节的属性

节:

节紧跟在节表之后,一般PE文件都会有几个“节”。PE文件又很多种“节”下面简单介绍几种:

代码节:

代码节一般命名为.text或.code,该节含有程序的可执行代码。每个PE文件都会有代码节。

已初始化的数据节:

这个节一般取名为.data或DATA,该节中放的是在编译时刻就已经确定的数据。比如Hello world中的字符串“Hello World”.

未初始化的数据节:

这个节的名称一般叫.bbs,这个节中放有未初始化的全局变量和静态变量,比如:static intk

资源节:

资源节一般名为.rsrc。这个节存放图标、对话框等程序要用到的资源。资源节是树型结构的,它有一个主目录,主目录下面又有子目录。

重定位节:

重定位节存放了一个重定位表。若装载器无法把程序装到程序编译时默认的基地址时,就需要这个重定位表来做一些调整。

引入函数节:

这个节一般名为idata(rdata),它包含有从其他DLL(例如Kernel32.dll\user32.dll等)中引入的函数。该节的开始是一个成员为IMAGE_IMPORT_DESCRIPTOR结构的数组。这个数组的长度不定,但它的最后一项全是0,可以依次来判断数组的结束。该数组中成员结构的个数取决于程序要使用的DLL文件的数量,每个结构对应一个DLL文件。例如,如果一个PE文件从5个不同的DLL文件中引入了函数,那么该数组就存在5IMAGE_IMPORT_DESCRIPTOR结构成员。

IMAGE_IMPORT_DESCRIPTOR结构如下:



IAT可以直接获取该API的地址。





引入函数节也可以被病毒用来直接获取API函数地址,譬如,直接修改或添加所需函数的IMAGE_IMPORT_DESCRIPTOR结构后,当程序调入内存时便会将所需函数的地址写入到IAT表中供病毒获取,对于病毒来说,获取了LoadLibraryGetProcAddress函数之后,基本上就可以获取所有其他的API函数了。


引出函数节

引出函数节对病毒来说也是非常重要的。我们知道,病毒在感染其他文件时,是不能直接调用API函数的,因为计算机病毒往其他HOST程序中所写的只是病毒代码节的部分。而不能保证HOST程序中一定有病毒所调用的API函数,这样我们就需要自己获取API函数的地址!有一种暴力搜索就是从kernel32模块中获取API函数的地址,这种方法充分利用了引出函数节中的数据。

引出函数节一般名为.edata,这是本文件向其他程序提供调用的函数列表。这个节一般用在DLL中,EXE文件也可以有这个节,但通常很少使用。


猜你喜欢

转载自blog.csdn.net/fly_hps/article/details/80065787