解析导入表就需要先认识下面这三个结构体
//导入表结构体
typedef struct _IMAGE_IMPORT_DESCRIPTOR {
union {
DWORD Characteristics;
//主要这个,包含指向INT的RVA
DWORD OriginalFirstThunk;
};
//时间标识
DWORD TimeDateStamp;
//与转发有关
DWORD ForwarderChain;
//这就是DLL文件名
DWORD Name;
//IAT的RVA
DWORD FirstThunk;
} IMAGE_IMPORT_DESCRIPTOR, *PIMAGE_IMPORT_DESCRIPTOR;
//
typedef struct _IMAGE_THUNK_DATA32 {
union {
//转发器有关
DWORD ForwarderString;
//IAT有关
DWORD Function;
//当前结构高位为1是有关
DWORD Ordinal;
//不是上面三个的时候这个就发挥作用
//指向输入名称表
DWORD AddressOfData;
} u1;
} IMAGE_THUNK_DATA32,*PIMAGE_THUNK_DATA32;
//输入名称表
typedef struct _IMAGE_IMPORT_BY_NAME {
//导入的函数序号
WORD Hint;
//导入的函数名称
CHAR Name[1];
} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;
IMAGE_IMPORT_DESCRIPTOR(导入表)仅仅是一个引导者,引导系统找到那两个保存有真正导入信息的结构体,也就是IMAGE_THUNK_DATA和IMAGE_IMPORT_BY_NAME。
实现代码:
BOOL PEAnalyseSpace::PEAnalyse::ShowImport()
{
//执行是否成功
BOOL bRet = FALSE;
//导入表指针
PIMAGE_IMPORT_DESCRIPTOR pImport = NULL;
//指针
PIMAGE_THUNK_DATA pThunk = NULL;
//导入名称表指针
PIMAGE_IMPORT_BY_NAME pName = NULL;
//字符串指针
PCHAR pszName = NULL;
do
{
//没有解析
if (m_lpBase == NULL)
{
break;
}
//没有导入导入表,这个是不可能的
if (m_pNt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size == NULL)
{
break;
}
//获取导入表
pImport = (PIMAGE_IMPORT_DESCRIPTOR)
(RVAtoOffset(m_pNt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
+ (DWORD)m_lpBase);
//循环遍历
while (pImport->Name)
{
//获取导入地址表
pThunk = (PIMAGE_THUNK_DATA)
(RVAtoOffset(pImport->OriginalFirstThunk) + (DWORD)m_lpBase);
//获取模块名字
pszName = (PCHAR)(RVAtoOffset(pImport->Name) + (DWORD)m_lpBase);
cout << "Module Name Is: "
<< pszName
<< endl;
//循环遍历地址
while (pThunk->u1.AddressOfData)
{
//判断是序号导入还是名称导入
//序号
if (IMAGE_SNAP_BY_ORDINAL32(pThunk->u1.AddressOfData))
{
cout << "Index Import -> ID: "
<< hex
<< (pThunk->u1.Ordinal & 0xffff)
<< endl;
}
else//名称导入
{
//获取导入名称
pName = (PIMAGE_IMPORT_BY_NAME)
(RVAtoOffset(pThunk->u1.AddressOfData)
+ (DWORD)m_lpBase);
cout << "Name Import -> ID: "
<< hex
<< pName->Hint
<< "\tName: "
<< pName->Name
<< endl;
}
pThunk++;
}
cout << endl;
pImport++;
}
bRet = TRUE;
} while (FALSE);
return bRet;
}
实际效果:
Github:源代码下载