解析導入表就需要先認識下面這三個結構體
//導入表結構體
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:源代碼下載