1. 程式人生 > >PE文件格式中導入表和ITA表總結20180508

PE文件格式中導入表和ITA表總結20180508

med 只有一個 文件 term 說明 def 文件中 內容 nal

PE文件中重要的表有:1.導出表,2.導入表,3.IAT表,4.重定位表,5.資源表
導入表的結構體:

typedef struct _IMAGE_IMPORT_DESCRIPTOR {
union {
DWORD Characteristics; // 0 for terminating null import descriptor
DWORD OriginalFirstThunk; // RVA to original unbound IAT (PIMAGE_THUNK_DATA)
};
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;

以上結構體成員不多,而且有用的成員只有第一個共用體成員,第四個dll名稱,第五個FirstThunk(ITA表首地址)。
一一詳解如下:
1)第一個成員雖為共用體,但常用的類型是共用體中第二個成員DWORD OriginalFirstThunk,看到名稱就知道和第五
個成員變量很像,它們記錄的是THUNK_DATA表的RVA,其實以上結構體的第一個和最後一個成員的類型可以改成PIMAGE_THUNK_DATA,
但之所以沒改,我想原因是第五個成員指向的RVA也是IAT表地址,而IAT表是用於填API地址指針的,而函數指針類型各異,所以
統一用DWORD表類型,當然用LPVOID也是合理的。或者可以這麽理解,OriginalFirstThunk和FirstThunk在文件中是類型應該是
PIMAGE_THUNK_DATA,但加載到內存後就是LPVOID或者DWORD了。
再看一下PIMAGE_THUNK_DATA是什麽類型指針,

typedef struct _IMAGE_THUNK_DATA32 {
union {
PBYTE ForwarderString;
PDWORD Function;
DWORD Ordinal;
PIMAGE_IMPORT_BY_NAME AddressOfData;
} u1;
} IMAGE_THUNK_DATA32;
typedef IMAGE_THUNK_DATA32 * PIMAGE_THUNK_DATA32;

別看以上結構體好像很龐大,但其實其中的成員只有一個共用體,就相當於一個DWORD類型的大小,共用體中常用的類型是
DWORD Ordinal和PIMAGE_IMPORT_BY_NAME AddressOfData,至於到底是序號還是名稱,通過該值的最高位得到,如果最高位是1,
則表明是序號,序號保存在後兩個字節中,其實也說明序號導出只能導出65536個函數,如果最高位是0,則表明是API名稱導出,
但該值並不直接指向API名稱的地址,而是指向一個結構體,如下的一個柔性數組:

typedef struct _IMAGE_IMPORT_BY_NAME {
WORD Hint;
BYTE Name[1];
} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;

頭一個二字節的成員很少用,直接用第二個,即API名稱地址。PIMAGE_THUNK_DATA就是如上說明,OriginalFirstThunk和
FirstThunk中如果有值,則是按以上方式解析。一個dll對應的導入表中只會有一個PIMAGE_THUNK_DATA表,也就是說一般
OriginalFirstThunk和FirstThunk指向的文件中內容是一樣的,並且因為FirstThunk還是IAT表,所以和Nt頭中數據目錄的第12
指向的內容是一樣的。
那現在又有一個問題了,系統在加載PE文件時是以哪個成員指向的數據為準呢?其實是,先看OriginalFirstThunk中數據是
否在,如果不在或者是錯的值(被人手工修改),則讀FirstThunk中數據或者有可能加載不了,當OriginalFirstThunk和FirstThunk
都沒指向PIMAGE_THUNK_DATA數據時,則肯定是加載不了的,另外,當OriginalFirstThunk中指向數據正確,FirstThunk改成其它
有效數據也是可以的。指向的PIMAGE_THUNK_DATA表以零結尾,加載到0則加載下一個導入表。
2)IMAGE_IMPORT_DESCRIPTOR的第四個成員變量是dll名稱,很重要,不能改錯,不然沒法加載了,一個dll對應一個導入表。

PE文件格式中導入表和ITA表總結20180508