天天看點

PE檔案,導入表定位

使用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的大小定義成位元組,其實它是可變尺寸域,隻不過我們沒有更好方法來表示結構中的可變尺 寸域。