天天看點

【PE結構】5.導入表

一、前言

二、PE整體結構

三、DOS頭

四、NT頭

五、區段頭

六、導出表

七、導入表

八、資源表

九、其他表

1.概念

導入 是PE檔案(EXE)在運作時,使用到了其他PE檔案(DLL)中的函數、變量、類等這樣的行為。

導入表 存儲的是從其他PE檔案(DLL)導入過來的函數名、序号。在加載到記憶體後,還存儲這些函數的位址。

導入表結構 導入表是一個結構體數組,最後以一個結構體大小的全零元素結尾。每一個數組元素代表一個PE檔案的導入資訊。

PE檔案(EXE)通常需要多個PE檔案(DLL)的支援,是以導入表一般有多個。

2.導入表定位

前面提到的 NT頭->擴充頭->資料目錄表->第二個元素->相對虛拟位址(RVA)

還用010Editor打開百度雲盤看一下

【PE結構】5.導入表

從擴充頭裡的資料,我們就可以得到導入表的定位資訊RVA

再啰嗦一下RVA定位資料的使用

如果是在檔案裡用,需要用FOA

導入表FOA = 導入表RVA - 區段RVA + 區段FOA

如果是加載到記憶體裡使用,需要用VA

導入表VA = 加載基址BaseImage + 導入表RVA

實踐一下:

我們是在檔案裡操作,是以要先得到FOA

要得到FOA先要得到導入表所在.rdata區段資訊

區段資訊怎麼得到還記得嗎?

對,在區段頭表裡有相關資訊,忘了就看看前面的文章吧

【PE結構】5.導入表

導入表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對應的資料

【PE結構】5.導入表

圖中圈除了三個元素,每個20位元組

我們再尋找一下結束的位置,20個0

【PE結構】5.導入表

果然找到了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;

           

實踐一下:

不按上面寫的那麼複雜的去做了,簡單的在檔案中看一下

【PE結構】5.導入表

找到導入表第一個元素,找到第一個元素内的INT位址和IAT位址

INT表FOA = 0x5715CC - 0x45F000 + 0x45D800 = 0x56FDCC

【PE結構】5.導入表

函數名FOA = 0x571634 - 0x45F000 + 0x45D800 = 0x56FE34

【PE結構】5.導入表

上一篇:【PE結構】導出表

下一篇:【PE結構】資源表