之前的笔记搬运
0x1 导入表结构
导入表位于PE文件中的数据目录数组下标为1的位置
1 | IMAGE_IMPORT_DESCRIPTOR STRUCT |
OriginalFirstThunk:指向IMAGE_THUNK_DATA结构数组的RVA,也被称为INT,
IMAGE_THUNK_DATA数组里每个成员是指向一个IMAGE_IMPORT_BY_NAME的结构的RVA,
IMAGE_IMPORT_BY_NAME里存放的是一个无用的WORD量和输入函数的名称, 具体见0x2与0x3
TimeDateStamp:该字段可以忽略。如果那里有绑定的话它包含时间/数据戳(time/data
stamp)。如果它是0,就没有绑定在被导入的DLL中发生。
在最近,它被设置为0xFFFFFFFF以表示绑定发生。
ForwarderChain:一般情况下我们也可以忽略该字段。在老版的绑定中,它引用API的第一个forwarder
chain(传递器链表)。
它可被设置为0xFFFFFFFF以代表没有forwarder。
Name: 指向DLL 名称的RVA, 如kernel32.dll, 用于PE加载器loadlibrary
FirstThunk: 指向IMAGE_THUNK_DATA结构数组的RVA, 其内容在程序未运行下,
和OriginalFirstThunk内容一样,
但是在程序运行后会被填充为对应函数的地址也被称为IAT
0x2 IMAGE_THUNK_DATA
1 | typedef struct _IMAGE_THUNK_DATA32 { |
ForwarderString 指向一个转向者字符串的RVA;
Function 被输入的函数的内存地址;
Ordinal 被输入的API的序数值
AddressOfData 指向IMAGE_IMPORT_BY_NAME
这4个成员是一个共用体, 在不同情况下代表不同的数据
IMAGE_THUNK_DATA32的值表示一个输入函数,这个值最高位为1的时候,
表示函数是一个序号输出值, 低31位会被看做API的导出序号, 当最高位为0时,
这时候这个值是一个指向IMAGE_IMPORT_BY_NAME结构的RVA
0x3 IMAGE_IMPORT_BY_NAME
1 | typedef struct _IMAGE_IMPORT_BY_NAME { |
Hint: 无用的WORD量
Name[1]: 指向一个输入函数字符串的指针, NULL结尾
0x4 系统加载导入表的过程
1 | 1) 首先检查当前导入表FirstThunk这个字段指向的内容是否为空 |
总结:
1.导入表其实是一个IMAGE_IMPORT_DESCRIPTOR的数组,每个导入的DLL对应一个IMAGE_IMPORT_DESCRIPTOR。
2.IMAGE_IMPORT_DESCRIPTOR包含两个IMAGE_THUNK_DATA数组,数组中的每一项对应一个导入函数。
3.加载前OriginalFirstThunk与FirstThunk的数组都指向名字信息,加载后FirstThunk数组指向实际的函数地址。