一、前言
二、PE整體結構
三、DOS頭
四、NT頭
五、區段頭
六、導出表
七、導入表
八、資源表
九、其他表
1.概念
導入 是PE檔案(EXE)在運作時,使用到了其他PE檔案(DLL)中的函數、變量、類等這樣的行為。
導入表 存儲的是從其他PE檔案(DLL)導入過來的函數名、序号。在加載到記憶體後,還存儲這些函數的位址。
導入表結構 導入表是一個結構體數組,最後以一個結構體大小的全零元素結尾。每一個數組元素代表一個PE檔案的導入資訊。
PE檔案(EXE)通常需要多個PE檔案(DLL)的支援,是以導入表一般有多個。
2.導入表定位
前面提到的 NT頭->擴充頭->資料目錄表->第二個元素->相對虛拟位址(RVA)
還用010Editor打開百度雲盤看一下
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIwczLcVmds92czlGZvwVP9EUTDZ0aRJkSwk0LcxGbpZ2LcBDM08CXlpXazRnbvZ2LcRlMMVDT2EWNvwFdu9mZvwVP9cnW1Z0VlVnVHFma5YVZv5kMMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2LcRHelR3LcJzLctmch1mclRXY39jNyUTMxEjM4ATNyYDM4EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
從擴充頭裡的資料,我們就可以得到導入表的定位資訊RVA
再啰嗦一下RVA定位資料的使用
如果是在檔案裡用,需要用FOA
導入表FOA = 導入表RVA - 區段RVA + 區段FOA
如果是加載到記憶體裡使用,需要用VA
導入表VA = 加載基址BaseImage + 導入表RVA
實踐一下:
我們是在檔案裡操作,是以要先得到FOA
要得到FOA先要得到導入表所在.rdata區段資訊
區段資訊怎麼得到還記得嗎?
對,在區段頭表裡有相關資訊,忘了就看看前面的文章吧
導入表FOA = 導入表RVA - 區段RVA + 區段FOA = 5706C0H - 45F000H + 45D800H = 56EEC0H
3.導入表結構
typedef struct _IMAGE_IMPORT_DESCRIPTOR {
union {
DWORD Characteristics;
DWORD OriginalFirstThunk; // 指向 導入名稱表INT(ImportNameTable)的RVA
} DUMMYUNIONNAME;
DWORD TimeDateStamp;
DWORD ForwarderChain;
DWORD Name; // 指向 DLL名稱的位址 RVA
DWORD FirstThunk; // 指向 導入位址表IAT(ImportAddressTable)的RVA
} IMAGE_IMPORT_DESCRIPTOR;
typedef IMAGE_IMPORT_DESCRIPTOR UNALIGNED *PIMAGE_IMPORT_DESCRIPTOR;
導入表結構體大小為20個位元組。
有幾個子產品,就有幾個結構體,從起始位址開始,每個20位元組,遇到20個0結束。
實踐一下:
上一環節,我們找到了導入表FOA,我們來看看FOA對應的資料
圖中圈除了三個元素,每個20位元組
我們再尋找一下結束的位置,20個0
果然找到了20個0,0x56F207,應該就是導入表結束的位置。
我們在看看其他的一些資料
導入表大小=結束位置-起始位置=0x56F208-0x56EEC0=0x348=840
導入表元素個數=導入表大小/元素大小=840/20=42
也就是導入了42個DLL
4.導入名稱表、導入位址表
4.1.表内資料元素結構
導入名稱表和導入位址表結構完全相同。
INT和IAT兩張表内的元素都是4位元組大小的結構體IMAGE_THUNK_DATA
資料元素清單遇到4位元組0結束
typedef struct _IMAGE_THUNK_DATA32 {
union {
DWORD ForwarderString;
DWORD Function; // 導入函數位址
DWORD Ordinal; // 序号導入用
DWORD AddressOfData; // 函數名導入用,指向PIMAGE_IMPORT_BY_NAME
} u1;
} IMAGE_THUNK_DATA32;
typedef IMAGE_THUNK_DATA32 * PIMAGE_THUNK_DATA32;
4.2.導入名稱表、導入位址表 關系
在磁盤檔案中,OriginalFirstThunk指向的INT 與 FirstThunk指向的IAT 兩表中的資料是相同的。
加載到記憶體後,輸入位址表會由加載器把對應的PE檔案中的函數位址覆寫到這裡。
4.3.使用規則
通過結構體定義我們可以看到,結構體裡面是一個聯合體
也就是說,其實是同一個資料,看你用哪種形式使用
如果加載到記憶體中,Function函數位址啟用
如果磁盤檔案中,隻有後兩個字段起作用Ordinal、AddressOfData。當資料最高位為1時Ordinal序号起作用,當資料最高位為0時AddressOfData函數名起作用,指向結構體。
typedef struct _IMAGE_IMPORT_BY_NAME {
WORD Hint; // 如不為空,值為函數在導出表中的索引
CHAR Name[]; // 函數名的第一位元組,到0結束
} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;
實踐一下:
不按上面寫的那麼複雜的去做了,簡單的在檔案中看一下
找到導入表第一個元素,找到第一個元素内的INT位址和IAT位址
INT表FOA = 0x5715CC - 0x45F000 + 0x45D800 = 0x56FDCC
函數名FOA = 0x571634 - 0x45F000 + 0x45D800 = 0x56FE34
上一篇:【PE結構】導出表
下一篇:【PE結構】資源表