【PE文件】导入表
导入表位置
IMAGE_NT_HEADERS.IMAGE_OPTIONAL_HEADER32.IMAGE_DATA_DIRECTORY_ARRAY[1].VirtualAddress
导入表结构
导入表以一个 IMAGE_IMPORT_DESCRIPTOR(IID)数组开始。每个导入的DLL都对应一个IID结构体。最后以一个全0的IID结构体结束。
1 struct _IMAGE_IMPORT_DESCRIPTOR 2 { 3 0x00 union 4 { 5 0x00 DWORD Characteristics; 6 0x00 PIMAGE_THUNK_DATA OriginalFirstThunk; //RVA:INT(导入名称表) 7 } u; 8 0x04 DWORD TimeDateStamp; 9 0x08 DWORD ForwarderChain; 10 0x0c DWORD Name; //RVA:DLL 名称 11 0x10 PIMAGE_THUNK_DATA FirstThunk; //RVA:IAT(导入地址表) 12 };
INT和IAT指向一个相同类型的 IMAGE_THUNK_DATA(ITD)结构体数组,该数组以一个全0结构体结尾。该结构体与导入函数相对应,有多少个ITD结构体就有多少个函数被导入。
1 struct _IMAGE_THUNK_DATA 2 { 3 union 4 { 5 0x00 LPBYTE ForwarderString; 6 0x00 PDWORD Function; 7 0x00 DWORD Ordinal; //函数序号 8 0x00 PIMAGE_IMPORT_BY_NAME AddressOfData; //RVA:IMAGE_IMPORT_BY_NAME 9 } u1; 10 };
当IMAGE_THUNK_DATA 结构体:最高位为1时,表示函数以序号导入,此时低31位被看成函数序号使用。
当IMAGE_THUNK_DATA 结构体:最高位为0时,表示函数以名称导入,此时AddressOfData是一个指向 IMAGE_IMPORT_BY_NAME 结构体的Rva。
1 struct _IMAGE_IMPORT_BY_NAME 2 { 3 0x00 WORD Hint; //2字节 4 0x02 BYTE Name[1]; //n字节 函数名称字符串 5 };
PE文件加载前:INT和IAT指向的IMAGE_THUNK_DATA 结构体存储着相同内容(导入函数的名称或序号)
PE文件加载后:IAT指向导入函数的实际调动地址。