PE文件是Protable Executable File Format(可移至的执行体),是目前Windows平台上的主流可执行文件格式。
PE可以简单理解为一个结构,这个结构用来告诉Windows加载器如何去加载这个文件。PE会告诉它其资源、导入表等信息。而这些信息对应在PE文件的不同成员变量。暂时理解PE文件,通过其几个主要的结构来学习。
先给张有总结性的网上大量流传的PE文件格式图:
我觉得,还有必要加深理解几个和地址有关的定义:基地址、相对虚拟地址、文件偏移地址。
基地址吧,PE文件被加载进入内存后,其映射文件的起始位置就是基地址,其实我们的模块句柄也是这个值。用VC的默认选项编译的EXE基地址为00400000h,DLL基地址为10000000h。
相对虚拟地址,其作用吧,简单点说,避免在PE文件中有确定的内存地址。既是相对于文件载入点的大小吧,目标地址 - 装入地址 = RVA。内存的虚拟地址 = 基地址 + RVA。
文件偏移地址,既是物理地址吧,从0开始计数,用UE等打开看到的地址就是这个。
然后开始学PE文件的格式了。差点忘了说,这些结构名有些许出入,大多是32位和64位的差异。可以到我们的系统盘(C:\Program Files\Microsoft SDKs\Windows\v6.0A\Include里面的winnt.h头文件)的里面找找看。
首先是被称为DOS头部的结构,这个,其实现在没太大价值的感觉。只用知道在3ch位置,记录着PE文件头的文件偏移地址(用4个Bytes)即可。由于Intel是小端规则,所以需要留意“B0000000”代表“000000B0”地址。
然后就是我们的PE文件头了,IMAGE_NT_HEADER由三部分组成,上面也看到了。
Signature字段记录着“PE00”。用UE打开可以很明显看到。
IMAGE_FILE_HEADER结构的话,成为映射文件头结构吧。需要留意的可能是文件属性字段吧,普通的EXE文件的话则为010fh,DLL文件的话则为0210h。
IMAGE_OPTIONAL_HEADER结构,是对上面的一个补充。具体结构也上图吧。
以此类推,可以看出,上图大概可以帮我们理解PE文件格式了。然后输入表、输出表、块、基地址重定位等,都需要在此基础上理解了才能学好。所以,先消化这些。