使用16進制編輯器,在PE文件種定位到導入表的過程。
1. 前64字節MZ文件頭,最後的4個字節是PE文件頭的位置。
2. 找到PE文件頭。
3. PE文件頭第24字節偏移處是可選頭。
4. 可選頭0x70偏移處是IMAGE_DATA_DIRECTORY數組
5. 該數組長64字節,第二個元素爲導入表的IMAGE_DATA_DIRECTORY
6. 導入表的IMAGE_DATA_DIRECTORY的前32位是導入表的RVA
7. 查節表確定導入表在哪個節,然後利用節表獲得導入表的文件偏移
8. 定位到導入表
9. 導入表爲一個IMAGE_IMPORT_DESCRIPTOR數組,每個被導入的文件對應一項,定義如下:
typedef struct _IMAGE_IMPORT_DESCRIPTOR {
DWORD OriginalFirstThunk;
DWORD TimeDateStamp;
DWORD ForwarderChain;
DWORD Name;
DWORD FirstThunk;
}IMAGE_IMPORT_DESCRIPTOR, *PIMAGE_IMPORT_DESCRIPTOR;
成員含義如下:
OriginalFirstThunk
它指向first thunk,IMAGE_THUNK_DATA,該thunk擁有Hint和Function name的地址。
TimeDateStamp
如果那裏有綁定的話它包含時間/數據戳(time/data stamp)。如果它是0,就沒有綁定在被導入的DLL中發生。在最近,它被設置爲0xFFFFFFFF以表示綁定發生。
ForwarderChain
在老版的綁定中,它引用API的第一個forwarder chain(傳遞器鏈表)。它可被設置爲0xFFFFFFFF以代表沒有forwarder。
Name
它表示DLL 名稱的相對虛地址(譯註:相對一個用null作爲結束符的ASCII字符串的一個RVA,該字符串是該導入DLL文件的名稱,如:KERNEL32.DLL)。
FirstThunk
它包含由IMAGE_THUNK_DATA定義的 first thunk數組的虛地址,通過loader用函數虛地址初始化thunk。在Orignal First Thunk缺席下,它指向first thunk:Hints和The Function names的thunks。
10. 從Name成員可以得到被導入文件名的RVA,利用節表可以獲得文件偏移,可以看到被導入文件的名稱。
11. 從OriginalFirstThunk可以得到IMAGE_THUNK_DATA結構數組的RVA,利用節表得到其文件偏移。IMAGE_THUNK_DATA結構定義爲:
typedef struct _IMAGE_THUNK_DATA32 {
PIMAGE_IMPORT_BY_NAME AddressOfData;
} IMAGE_THUNK_DATA32;
12. 從中得到IMAGE_IMPORT_BY_NAME結構的RVA,利用節表得到文件偏移。IMAGE_IMPORT_BY_NAME結構定義爲:
typedef struct _IMAGE_IMPORT_BY_NAME {
WORD Hint;
BYTE Name[1];
}IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;
成員含義如下:
Hint
指示本函數在其所駐留DLL的引出表中的索引號。該域被PE裝載器用來在DLL的引出表裏快速查詢函數。該值不是必須的,一些連接器將此值設爲0。
Name1
含有引入函數的函數名。函數名是一個ASCIIZ字符串。注意這裏雖然將Name1的大小定義成字節,其實它是可變尺寸域,只不過我們沒有更好方法來表示結構中的可變尺 寸域。