跳转至

Basic info

基础概念

下表描述了贯穿于本文中的一些概念:

名称 描述
地址 是 “虚拟地址” 而不是“物理地址”。**为什么不是“物理地址”呢?**因为数据在内存的位置经常在变,这样可以节省内存开支、避开错误的内存位置等的优势。同时用户并不需要知道具体的“真实地址”,因为系统自己会为程序准备好内存空间的(只要内存足够大)
镜像文件 包含以 EXE 文件为代表的 “可执行文件”、以DLL文件为代表的“动态链接库”。为什么用“镜像”?这是因为他们常常被直接“复制”到内存,有“镜像”的某种意思。
RVA 英文全称 Relatively Virtual Address。偏移(又称“相对虚拟地址”)。相对镜像基址的偏移。
节 节 是 PE 文件中 代码 或 数据 的基本单元。原则上讲,节只分为 “代码节” 和 “数据节” 。
VA 英文全称 Virtual Address。基址

​ PE( Portable Execute)文件是Windows下可执行文件的总称,常见的有 DLL,EXE,OCX,SYS 等。它是微软在 UNIX 平台的 COFF(通用对象文件格式)基础上制作而成。最初设计用来提高程序在不同操作系统上的移植性,但实际上这种文件格式仅用在 Windows 系列操作系统下。PE文件是指 32 位可执行文件,也称为PE32。64位的可执行文件称为 PE+ 或 PE32+,是PE(PE32)的一种扩展形式(请注意不是PE64)。

事实上,一个文件是否是 PE 文件与其扩展名无关,PE文件可以是任何扩展名。那 Windows 是怎么区分可执行文件和非可执行文件的呢?我们调用 LoadLibrary 传递了一个文件名,系统是如何判断这个文件是一个合法的动态库呢?这就涉及到PE文件结构了。

img

PE文件的结构一般来说如下图所示:从起始位置开始依次是 DOS头,NT头,节表 以及 ***具体的*节。

img

PE文件结构

图 1:

img

图 2:

img

图 3:

img

PE 文件的执行顺序

  1. 当一个 PE 文件 被执行时,PE 装载器 首先检查 DOS header 里的 PE header 的偏移量。如果找到,则直接跳转到 PE header 的位置。
  2. 当 PE装载器 跳转到 PE header 后,第二步要做的就是检查 PE header 是否有效。如果该 PE header 有效,就跳转到 PE header 的尾部。
  3. 紧跟 PE header 尾部的是节表。PE装载器执行完第二步后开始读取节表中的节段信息,并采用文件映射( 在执行一个PE文件的时候,Windows并不在一开始就将整个文件读入内存,而是采用与内存映射的机制,也就是说,Windows装载器在装载的时候仅仅建立好虚拟地址和PE文件之间的映射关系,只有真正执行到某个内存页中的指令或者访问某一页中的数据时,这个页面才会被从磁盘提交到物理内存,这种机制使文件装入的速度和文件大小没有太大的关系 )的方法将这些节段映射到内存,同时附上节表里指定节段的读写属性。
  4. PE文件映射入内存后,PE装载器将继续处理PE文件中类似 import table (输入表)的逻辑部分。

这四个步骤便是PE文件的执行顺序,具体细节读者可以参考相关文档。(以上四个步骤摘自《黑客破解精通》)