- 一个进程是由一组PE文件构成的。
- PE文件提供哪些功能:导出表。
- PE文件需要依赖哪些模块以及依赖这些模块中的哪些函数:导入表。
导入表结构
typedef struct _IMAGE_IMPORT_DESCRIPTOR {
union {
DWORD Characteristics;
DWORD OriginalFirstThunk; //RVA指向IMAGE_THUNK_DATA结构数组
} DUMMYUNIONNAME;
DWORD TimeDateStamp; //时间戳
DWORD ForwarderChain;
DWORD Name; //RVA,指向DLL名字,该名字以0x00结尾
DWORD FirstThunk; //RVA,指向IMAGE_THUNK_DATA结构数组
} IMAGE_IMPORT_DESCRIPTOR;
typedef struct _IMAGE_THUNK_DATA32 {
union {
DWORD ForwarderString; // PBYTE
DWORD Function; // PDWORD
DWORD Ordinal; // 序号
DWORD AddressOfData; // 指向 IMAGE_IMPORT_BY_NAME
} u1;
} IMAGE_THUNK_DATA32;
typedef struct _IMAGE_IMPORT_BY_NAME {
WORD Hint; //可能为空,由编译器决定,如果不为空就是函数在导出表中的索引
CHAR Name[1]; //函数名称,以0结尾
} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;
定位导入表
- 扩展PE头中的最后一个结构体成员它的第二个成员就是导入表。
- 依赖一个模块就有一个导入表,依赖十个模块就有十个导入表。
如何判断有多少个导入表?
通过连续的20个为00的字节来确定导入表结束。
确定需要导入的函数
INT:导入名称表
IAT:导入地址表