ღ Miranda

PE头结构分析

PE文件是Win32的原生文件格式.每一个Win32可执行文件都遵循PE文件格式.对PE文件格式的了解可以加深你对Win32系统的深入理解。

基本结构

PE头由许多结构体构成,大致顺序为:DOS头,DOS存根,NT头,.text节区头,.data节区头,.rsrc节区头,这些结构体都定义在winnt.h这个头文件中。

DOS头

DOS头为了保留PE文件对DOS的兼容性,拓展已经有的DOS EXE头,结构体名为_IMAGE_DOS_HEADER:

WORD大小为2个字节,LONG大小为4个字节,所以_IMAGE_DOS_HEADER结构体的大小为64个字节,关注第一个和最后一个字段,e_magicDOS签名,值为MZ,用16进制编辑器打开文件就能看到开头为4D 5A,由于Intel以逆序存储数据,所以就对应ASCII5A4D,也就是MZe_lfanew字段指示了NT头的偏移,由于文件偏移为00000000-FFFFFFFF,所以e_lfanew的长度为4个字节。


DOS存根

DOS存根是可选项,大小不固定,由代码和数据混合而成,不是一个结构体,这是MS-DOS兼容模式,在DOS下运行就会执行这部分的代码,以notepad.exe为例,在DOS下的汇编代码如下:

就相当于一个程序里包含了另一个程序。


NT头

_IMAGE_NT_HEADERS这个结构体里包含了三个成员,Signature这个是签名,值为50 45 00 004550,就是PE这个字符串,另外两个分别为文件头_IMAGE_FILE_HEADER和可选头_IMAGE_OPTIONAL_HEADENT结构体总大小为F8。

文件头

_IMAGE_FILE_HEADER结构体:

NumberOfSections定义了节区的个数,SizeOfOptionalHeader指定了_IMAGE_OPTIONAL_HEADER结构体的长度,其实这个结构体的大小是确定的,但WindowsPE装载器要查看这个值,只是在32位和64位下这个结构体大小不同。

可选头

_IMAGE_OPTIONAL_HEADER结构体:

_IMAGE_OPTIONAL_HEADER32时,Magic码为10B,为_IMAGE_OPTIONAL_HEADER64时,Magic码为20B,AddressOfEntryPoint指定了EP的相对地址,ImageBase为文件加载到内存时优先载入的地址,SizeOfHeaders指出了整个PE头的大小,DataDirectory这个成员是一个IMAGE_DATA_DIRECTORY的结构体数组,数组大小也在winnt.h中定义:

IMAGE_DATA_DIRECTORY结构体:

定义了大小和相对地址。


节区头

节区头由.text节区头,.data节区头,.rsrc节区头组成,结构体定义如下:

注意这里的union关键字表示两个变量用同一块内存空间,VirtualSize是内存中节区大小,VirtualAddress是内存中节区起始地址,是相对地址,SizeOfRawData是文件中节区大小,PointerToRawData是文件中节区起始地址,头部基本就是这些结构,下面讲一下节区里的两个特殊的结构。


IAT

IAT就是导入地址表,记录了程序使用了哪些库的那些函数,每一被导入的库都有一_IMAGE_IMPORT_DESCRIPTOR结构体保存,注意大小为20字节,这个结构体的位置信息储存在可选头结构体的DataDirectory[1],可由相对地址算出文件偏移,位置在三个节区内,一般在.text内。

OriginalFirstThunk这个结构体成员为INT(import name table)FirstThunk这个结构体成员就是IAT(import address table),这两个结构体中的值在一些情况下是相同的。

找到这个结构体的位置,按照结构体可以找到Name(库名称)的地址,INT(import name table)的地址,跟随进去就能找到各个函数名称。


EAT

EAT使应用程序能够准确找到函数的起始地址,只有库文件才有EAT,与IAT类似,由_IMAGE_EXPORT_DIRECTORY保存导出信息,而且PE文件中只有一个这样的结构体,函数的名字和地址都为一个数组:

查看DataDirectory[0]就可以得到_IMAGE_EXPORT_DIRECTORY的相对地址和大小,就能算出文件偏移,找到结构体位置,然后根据指针位置就能找到名称数组和地址数组,数组各索引对应的地址就是名称和地址对应的地址。

  1. 匿名说道:

    周安 打赏不能啊 :surprised: :surprised: :surprised:

发表评论

电子邮件地址不会被公开。