天天看點

【PE結構】4.導出表六、導出表

一、前言 二、PE整體結構 三、DOS頭 四、NT頭 五、區段頭

六、導出表

七、導入表 八、資源表 九、其他表

1.概念

導出 是指PE檔案導出的供其他PE檔案使用的函數、變量、或者類的行為。

符号 這些導出的函數、變量、類一般稱為符号。

導出表 是存儲導出的這些符号的表。通過導出表,能夠定位這些符号。

2.導出表定位

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

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

【PE結構】4.導出表六、導出表

可以看到,資料目錄表中第一個元素的結構體内有兩個資料

  • 相對虛拟位址

    相對虛拟位址隻是一個偏移值,虛拟位址才是真正定位的值。

    虛拟位址 = 程式加載基址(通常是0x400000) + 虛拟位址

    因為有檔案對齊的問題,未加載0x200對齊,加載後0x1000對齊,改位址并不能直接在檔案中找到導出表的位置。

    需要将虛拟位址,轉換成,檔案偏移。

    檔案FOA = 導出表RVA - 區段RVA + 區段FOA

    導出表應該在.edata段中,但通常這個段會合并到.rdata中。

  • 大小

    EXE檔案通常是沒有導出内容的

    大小,Size,值為0

我們換一個DLL檔案看一下

【PE結構】4.導出表六、導出表

3.導出表結構

typedef struct _IMAGE_EXPORT_DIRECTORY {
    DWORD   Characteristics;
    DWORD   TimeDateStamp;
    WORD    MajorVersion;
    WORD    MinorVersion;
    DWORD   Name;               // 目前PE檔案名
    DWORD   Base;               // 序号基數
    DWORD   NumberOfFunctions;  // 函數數量
    DWORD   NumberOfNames;      // 函數名稱數量
    DWORD   AddressOfFunctions;     // RVA 位址表
    DWORD   AddressOfNames;         // RVA 名稱表
    DWORD   AddressOfNameOrdinals;  // RVA 序号表
} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;
           

函數序号 需要通過序号基數加上序号表裡的序号才是真正的函數序号。

4.函數位址表

上面結構體中,AddressOfFunctions,該字段為導出函數位址表的**相對虛拟位址**RVA。

檔案未加載時,需要轉換為**檔案偏移**VA後才能使用。

檔案加載後,需要轉為為**虛拟位址**FOA才能使用。

找到導出函數位址表後,每條4個位元組為一條資料,共有NumberOfFunctions個。

5.函數名稱表

上面結構體中,AddressOfNames,該字段為導出函數名稱表的**相對虛拟位址**RVA。

表記憶體儲的是函數名稱的相對虛拟位址。

檔案未加載時,需要轉換為檔案偏移後才能使用。

檔案加載後,需要轉為為虛拟位址才能使用。

找到導出函數位址表後,每條4個位元組為一條資料,共有NumberOfFunctions個。每條資料為一個位址,指向函數名稱字元串。

6.函數序号表

上面結構體中,AddressOfNameOrdinals,該字段為導出函數序号表的**相對虛拟位址**RVA。

檔案未加載時,需要轉換為**檔案偏移**VA後才能使用。

檔案加載後,需要轉為為**虛拟位址**FOA才能使用。

找到導出函數序号表後,每條2個位元組為一條資料,共有NumberOfFunctions個。

7.位址表、名稱表、序号表關系

序号表 與 名稱表,兩表内容按索引值一一對應。

序号表 與 位址表,序号表内容 與 位址表索引加一的資料相對應。

位址表内容可能會比名稱表多,沒對應上的部分可能是用序号導出的函數,也可能是無效函數,位址為0。

【PE結構】4.導出表六、導出表

上一篇 :【PE結構】3.區段頭

下一篇 :【PE結構】5.導入表