PE文件格式中导入表和ITA表总结20180508

PE文件中重要的表有:1.导出表,2.导入表,3.IAT表,4.重定位表,5.资源表
导入表的结构体:

typedef struct _IMAGE_IMPORT_DESCRIPTOR {
union {
DWORD Characteristics; // 0 for terminating null import descriptor
DWORD OriginalFirstThunk; // RVA to original unbound IAT (PIMAGE_THUNK_DATA)
};
DWORD TimeDateStamp; // 0 if not bound,
// -1 if bound, and real date\time stamp
// in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND)
// O.W. date/time stamp of DLL bound to (Old BIND)

DWORD ForwarderChain; // -1 if no forwarders
DWORD Name;
DWORD FirstThunk; // RVA to IAT (if bound this IAT has actual addresses)
} IMAGE_IMPORT_DESCRIPTOR;
typedef IMAGE_IMPORT_DESCRIPTOR UNALIGNED *PIMAGE_IMPORT_DESCRIPTOR;

以上结构体成员不多,而且有用的成员只有第一个共用体成员,第四个dll名称,第五个FirstThunk(ITA表首地址)。
一一详解如下:
1)第一个成员虽为共用体,但常用的类型是共用体中第二个成员DWORD OriginalFirstThunk,看到名称就知道和第五
个成员变量很像,它们记录的是THUNK_DATA表的RVA,其实以上结构体的第一个和最后一个成员的类型可以改成PIMAGE_THUNK_DATA,
但之所以没改,我想原因是第五个成员指向的RVA也是IAT表地址,而IAT表是用于填API地址指针的,而函数指针类型各异,所以
统一用DWORD表类型,当然用LPVOID也是合理的。或者可以这么理解,OriginalFirstThunk和FirstThunk在文件中是类型应该是
PIMAGE_THUNK_DATA,但加载到内存后就是LPVOID或者DWORD了。
再看一下PIMAGE_THUNK_DATA是什么类型指针,

typedef struct _IMAGE_THUNK_DATA32 {
union {
PBYTE ForwarderString;
PDWORD Function;
DWORD Ordinal;
PIMAGE_IMPORT_BY_NAME AddressOfData;
} u1;
} IMAGE_THUNK_DATA32;
typedef IMAGE_THUNK_DATA32 * PIMAGE_THUNK_DATA32;

别看以上结构体好像很庞大,但其实其中的成员只有一个共用体,就相当于一个DWORD类型的大小,共用体中常用的类型是
DWORD Ordinal和PIMAGE_IMPORT_BY_NAME AddressOfData,至于到底是序号还是名称,通过该值的最高位得到,如果最高位是1,
则表明是序号,序号保存在后两个字节中,其实也说明序号导出只能导出65536个函数,如果最高位是0,则表明是API名称导出,
但该值并不直接指向API名称的地址,而是指向一个结构体,如下的一个柔性数组:

typedef struct _IMAGE_IMPORT_BY_NAME {
WORD Hint;
BYTE Name[1];
} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;

头一个二字节的成员很少用,直接用第二个,即API名称地址。PIMAGE_THUNK_DATA就是如上说明,OriginalFirstThunk和
FirstThunk中如果有值,则是按以上方式解析。一个dll对应的导入表中只会有一个PIMAGE_THUNK_DATA表,也就是说一般
OriginalFirstThunk和FirstThunk指向的文件中内容是一样的,并且因为FirstThunk还是IAT表,所以和Nt头中数据目录的第12
指向的内容是一样的。
那现在又有一个问题了,系统在加载PE文件时是以哪个成员指向的数据为准呢?其实是,先看OriginalFirstThunk中数据是
否在,如果不在或者是错的值(被人手工修改),则读FirstThunk中数据或者有可能加载不了,当OriginalFirstThunk和FirstThunk
都没指向PIMAGE_THUNK_DATA数据时,则肯定是加载不了的,另外,当OriginalFirstThunk中指向数据正确,FirstThunk改成其它
有效数据也是可以的。指向的PIMAGE_THUNK_DATA表以零结尾,加载到0则加载下一个导入表。
2)IMAGE_IMPORT_DESCRIPTOR的第四个成员变量是dll名称,很重要,不能改错,不然没法加载了,一个dll对应一个导入表。

猜你喜欢

转载自www.cnblogs.com/DennyChen/p/9008267.html