2020.05.25-2020.05.24

PE文件格式

可执行文件的格式是操作系统本身执行机制的反映。
PE(Portable Executable File Format 可移植的执行体)
头文件winnt.h中的image format给出了pe文件的内容,可以找到所有pe文件的数据结构定义、枚举类型、常量定义等
exe和dll文件使用完全相同的pe格式,唯一的区别就是用一个字段标识出这个文件是exe还是dll
64位Windows只是对pe格式进行了一些简单的修饰,新的格式为pe32+,没有新的结构加入,只是把32位字段扩展成64位
tCceGn.png

PE的基本概念

pe文件的内容分为不同区块,区块中包含代码或数据,各个区块按页边界对齐。区块大小没有限制,是一个连续的结构。每个块在内存中都有自己的属性如是否包含代码、是否可读写等
pe文件不是作为单一内存映射文件被载入内存。pe装载器遍历pe文件并决定文件的哪部分被映射。磁盘文件一旦被载入内存,磁盘上的数据结构布局和内存中的数据结构布局就是一致的,但数据之间的的相对位置可能会改变

基地址

PE文件通过加载器载入内存后,内存中的版本称为模块。映射文件的起始地址(基地址)称为模块句柄,可以通过模块句柄访问内存中的其他数据结构。
tCcm2q.png
内存中的模块代表进程将这个可执行文件所需要的代码、数据、输入表、输出表及其他有用的数据结构所使用的内存都放在一个连续的内存块中。PE文件的剩余部分可以被读入,但可能无法被映射。例如在将调试信息放到文件尾部时,PE的一个字段会告诉系统不能映射的数据将被放置在文件的尾部。在32位Windows种可以直接调用GetModuleHandle取得指向dll的指针,通过该指针访问DLL Mdodle。
基地址的值是由pe文件本身设定的

虚拟地址(Virtual Address)

相对虚拟地址(RVA)

相对于pe文件载入地址的偏移位置,其实就是一个偏移量。
假设一个文件从400000h处载入,代码区块开始于401000h处,代码区块的RVA计算方法:

1
目标地址401000-载入地址400000h=RVA1000h

同样,

1
虚拟地址VA=基地址ImageBase+相对虚拟地址RVA

文件偏移地址(物理地址)

pe文件的某个数据位置相对于文件头的偏移量
用十六进制工具打开文件时显示的地址就是文件偏移地址