第三章 PE头文件
本章是全书重点,所以要好好理解,概念比较多,但是非常重要。
PE头文件记录了PE文件中所有的数据的组织方式,它类似于一本书的目录,通过目录我们可以快速定位到某个具体的章节;通过PE文件头部分对某些数据结构的描述,我们也可以定位到那些不在头文件部的信息,比如导入表数据、导出表数据、资源表数据等。
3.1 PE的数据组织方式
这一节说了很多,举了两个例子,分别是图书馆存书1和图书馆存书2,细节我不介绍了,是基本的数据结构应用,没有难点。最后说PE数据组织方式类似于存书2的例子。那么说下存书2的例子:
为了方便图书馆更好的管理书籍(为了方便查找),我们可以定义两个数据结构,一个是BookStore,另一个是Book。(书中都是用汇编写的,我用C++翻译一下吧,方便看)。
BOOKSTORE
BOOK
找书的时候,我们可以通过BookStore遍历书库位置中的所有书找到存储指定的书的信息的变量的地址(某个Book地址),然后我们在根据这个地址找到Book结构,然后再根据这个结构去找到这本书。
对应的结构图
PE文件结构基本采用了类似的阻止方式。
3.2 与PE有关的基本概念
在详细了解PE文件结构之前,先学习几个基本概念。
3.2.1 地址
PE中设计的地址有四类,它们分别是:
1.虚拟内存地址(VA)
2.相对虚拟内存地址(RVA)
3.文件偏移地址(FOA)
4.特殊地址
要想了解这些概念,需要先简单了解一下32位环境下Windows对内存的管理,以及分页机制的原理。(这个地方请自行百度补脑)。
1.虚拟内存地址
用户的PE文件被操作系统加载进内存后,PE对应的进程支配了自己独立的4GB虚拟空间。在这个空间中定位的地址称为虚拟内存地址(Virtual Address,VA),所以虚拟内存地址的范围是00000000h~ffffffffh。在PE中,进程本身的VA被解释为:VA=进程的基地址+相对偏移内存地址。
2.相对虚拟内存地址
一个进程被操作系统加载到虚拟内存空间后,其相关的动态链接库也会被加载。这些同时加载到进程地址空间的文件被称为模块。每个模块在加载时都会有一个基址,也就是预先告操作系统:它会占用4GB空间的哪个部分(即从哪里开始存储该模块)。不同模块的基地址一般不一样,如果两个模块的基地址相同,就由操作系统决定这两个模块在虚拟空间中的具体位置。
相对虚拟内存地址(Reverse Virtual Address ,RVA)是相对于基地址的偏移,即