PE文件初识
PE(Portable Execute)文件是Windows下可执行文件的总称,wiki百科[12]将PE文件描述为“可移植的可执行文件”,是一种主要使用在32位和64位Windows操作系统上的文件格式。常见的PE文件格式主要用于DLL文件、EXE文件、SYS文件等,PE文件的判断标准不由文件扩展名决定,而是依据其独特的文件结构。
PE文件结构
PE文件中IAT表的修改是实现Windows API拦截的技术核心,由于PE文件格式复杂,涉及到的数据类型众多,故本文只对PE文件主要结构及IAT表相关部分进行简单介绍。
PE文件结构原理如图所示。
PE文件由DOS头开始,与DOS stub共同构成一个完整的DOS程序,用于兼容MS-DOS操作系统。NT头存储整个PE文件的信息,包含“PE”字样签名、PE文件头(IMAGE_FILE_HEADER)和PE可选头(IMAGE_OPTIONAL_HEADER32)三部分。
NT头包含大量的复杂结构,IAT表位于IMAGE_OPTIONAL_HEADER32的更深层次中。IMAGE_OPTIONAL_HEADER32结构包含31个域,其中DllCharacteristics用于单独标记DLL文件属性,仅对DLL文件有效,DataDirectory域是一个长度为16的数组,每个数组元素均是一个IMAGE_DATA_DIRECTORY结构体。IMAGE_DATA_DIRECTORY结构包含VirtualAddress和Size两个属性,其中VirtualAddress 记录数据结构的相对虚拟地址(RVA),Size用于描述VirtualAddress所指向的数据结构的大小。
DataDirectory数组中第二个IMAGE_DATA_DIRECTORY结构存储着“导入表”的RVA,利用这个RVA,我们就可以找到“导入表”。“导入表”本身是一个由IMAGE_IMPORT_DESCRIPTOR结构组成的数组,数组中的每个元素都包含一个PE文件引用的DLL信息。在IMAGE_IMPORT_DESCRIPTOR结构中,FirstThunk指向IMAGE_THUNK_DATA结构数组的RVA,其中PE文件载入内存后,FirstThunk指向导入地址表(IAT),即Windows API 拦截涉及到的核心数据结构。PE文件最后存放着大量的节,节表是对节的宏观统计。节的设计是为了以数据属性为标准归类数据,没有严格的限制,常见的.data节用于保存数据,.text节用于保存程序代码。
PE文件RVA寻址
IMAGE_IMPORT_DESCRIPTOR结构中的OriginalFirstThunk和FirstThunk成员均指向IMAGE_THUNK_DATA结构数组,IMAGE_THUNK_DATA是一个以联合体为成员变量的结构体。
简单来说,IMAGE_THUNK_DATA结构记录了一个指向IMAGE_IMPORT_BY_NAME结构的RVA,该结构存放了导入函数信息。OriginalFirstThunk和FirstThunk均指向包含导入函数信息的结构,二者间差异如图3所示,我们真正关心的是FirstThunk所指向的IMAGE_THUNK_DATA数组。
在PE文件装入内存之前,OriginalFirstThunk和FirstThunk指向两个内容相同的IMAGE_THUNK_DATA数组,在PE文件装入内存之后,FirstThunk所指向的IMAGE_THUNK_DATA数组内容变更为导入函数的实际地址(VA),我们称此时的IMAGE_THUNK_DATA数组为“导入地址表”,即用于拦截Windows API的IAT(Import Address Table)表。
“导入表”记录PE文件调用的所有DLL文件及外部函数信息,包括导入函数所在DLL文件名、导入函数名、导入函数地址等,IMAGE_IMPORT_DESCRIPTOR数组中元素个数即为PE文件引用DLL文件的个数。
PE文件
最新推荐文章于 2019-06-10 11:02:08 发布