导入表
具体参考
导入表在PE文件中就类似一个数组,存放的是这个PE文件加载时动态链接库(DLL)和函数的入口地址,具体结构如下:
typedef struct _IMAGE_IMPORT_DESCRIPTOR {
union {
DWORD Characteristics; // 0 for terminating null import descriptor
DWORD OriginalFirstThunk; // RVA to original unbound IAT (PIMAGE_THUNK_DATA)
} DUMMYUNIONNAME;
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;
重点的字段有:
- Characteristics:如果这个表是数组的最后一个则为0,否则OriginalFirstThunk保存一个入口点地址,指向一个IMAGE_THUNK_DATA数组
- TimeDateStamp:导入模块的时间戳,映像绑定前为0
- Name:是一个入口点地址,指向的是该导入模块的名字
- FirstThunk:指向一个IMAGE_THUNK_DATA数组
通过C++来获取PE文件导入表结构以及动态链接库的解析函数:
//打印导入表
void ImportTable(char * buffer)
{
//Dos
PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)buffer;
//PE
PIMAGE_NT_HEADERS pNt = (PIMAGE_NT_HEADERS)(pDos->e_lfanew + buffer);
//定位导入表
PIMAGE_DATA_DIRECTORY pImportDir = (PIMAGE_DATA_DIRECTORY)(pNt->OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_IMPORT);
//填充结构
PIMAGE_IMPORT_DESCRIPTOR pImport = (PIMAGE_IMPORT_DESCRIPTOR)(RvaToOffset(pImportDir->VirtualAddress, buffer) + buffer);
//通过循环来获取各个导入的DLL的文件,导入表类似数组
while (pImport->Name != NULL)
{
//完成导入表的解析
//由于再结构中指向的名字(name)是一个地址,所以还需要计算
char *szDllName = (char *)(RvaToOffset(pImport->Name, buffer) + buffer