PE32+ 是 Windows OS 使用的可执行文件格式.
64位 Windows OS 中进程的虚拟内存为16TB,其中低位的8TB供用户模式使用.高位的8TB供内核模式使用.
IMAGE_NT_HEADERS
IMAGE_FILE_HEADER
x86 PE32 固定为 014C. x64 PE32+ 中则为 8664 ( IA-64 中为0200 ).
IMAGE_OPTIONAL_HEADER
1#. Magic
PE32 中为 010B , PE32+ 中为 20B
2#. BaseOfData
PE32 中用作指示数据节的起始地址( RVA ), 而PE32+ 中删除了.
3#. ImageBase
有双字( Dword ) 变为 ULONGLONG (8字节).
4#. 堆&栈
与 堆(heah) 和 栈(stack) 有关的数据类型都变为 ULONGLONG 类型.
IMAGE_THUNK_DATA
先以32位为例:
这个结构体其实就是 INT 和 IAT 所指向的结构体.
网上有:
第一种说法: Ordinal 的值用作判断 union 中哪个域发挥作用.若 Ordinal 值为0,则此时只有 AddressOfData (指向 Import_by_name )有效, 即为 INT .若 Ordinal 最高位为1,则为 IAT.
这种说法纯属离谱,Ordinal 和 AddressOfData 都占四字节,不可能出现上述情况。
第二种说法是: 按照 IMAGE_THUNK_DATA 的最高位来判断. 如果最高位为1 ,则是 IAT,否则为 INT .
在 xp sp3 中的 notepad.exe 中看一下:
再看一下 INT :
可以发现 INT 中,最高位都是 0 ; 而 IAT 中,最高位都不是1 (最高位为1,则值最小为: 0x80000000 ),并且 IAT 中是函数地址.
当然,首先要明确一点,确实 IAT 和 INT 中对应的值都是一样的,此时满足最高位为0,指向 INT .
在 Win 7 32位下,看一下 notepad.exe 的 IAT 信息:
INT 信息:
如图,最高字节的值有 77, 6F , 73 , 72 , 75 , 3F ,以及 80.
同时注意到一点, 前面提到:普通 Dll 的 ImageBase 为 0x10000000,即最高字节值为1. 当最高位为1时,此时为 0x80000000 , 而 00000000 - 7FFFFFFF 是用户空间,其它则是系统空间.因此最高位为1时,在用户模式下是不能表示函数地址的.
通过以上这些,可以做如下总结:
1#. 在 IAT 中, 只有两种值, ①表示函数地址 ②与 INT 相同,即指向 Import_by_name 结构体.
2#. 在 INT 中, 存在两种值, ①指向 Import_by_name 结构体 ② 最高位为1,表示这个函数是由导出序号导入的函数.
因此当 IMAGE_THUNK_DATA 的最高位为1时,此时一定表示函数的导入序号.其它情况则分情况判定.
IMAGE_TLS_Directory
ULONGLONG 都是改变了的字段,并且持有的都是 VA 值.