PE文件格式詳解(二)


0x00 前言

   上一篇講到了PE文件頭的中IMAGE_FILE_HEADER結構的第二個結構,今天從IMAGE_FILE_HEADER中第三個結構sizeOfOptionalHeader講起。這個字段的結構名也叫做IMAGE_OPTIONAL_HEDAER講起。

0x01  IMAGE_OPTIONAL_HEADER概述

  其實這個結構是IMAGE_FILE_HEADER結構的補充。這兩個結構合起來才能對整個PE文件頭進行描述。這個結構異常復雜,但真正我們用得到的其實不多,下面來看看它的各個字段情況,如下圖(左邊的16位字符表示相對於文件頭的偏移量):

ypedef struct _IMAGE_OPTIONAL_HEADER 
{
    //
    // Standard fields.  
    //
+18h    WORD    Magic;         // 標志字, ROM 映像(0107h),普通可執行文件(010Bh)
+1Ah    BYTE      MajorLinkerVersion;     // 鏈接程序的主版本號
+1Bh    BYTE      MinorLinkerVersion;     // 鏈接程序的次版本號
+1Ch    DWORD   SizeOfCode;     // 所有含代碼的節的總大小
+20h    DWORD   SizeOfInitializedData;    // 所有含已初始化數據的節的總大小
+24h    DWORD   SizeOfUninitializedData; // 所有含未初始化數據的節的大小
+28h    DWORD   AddressOfEntryPoint;    // 程序執行入口RVA
+2Ch    DWORD   BaseOfCode;      // 代碼的區塊的起始RVA
+30h    DWORD   BaseOfData;      // 數據的區塊的起始RVA
    //
    // NT additional fields.    以下是屬於NT結構增加的領域。
    //
+34h    DWORD   ImageBase;      // 程序的首選裝載地址
+38h    DWORD   SectionAlignment;      // 內存中的區塊的對齊大
+3Ch    DWORD   FileAlignment;      // 文件中的區塊的對齊大小
+40h    WORD    MajorOperatingSystemVersion;  // 要求操作系統最低版本號的主版本號
+42h    WORD    MinorOperatingSystemVersion;  // 要求操作系統最低版本號的副版本號
+44h    WORD    MajorImageVersion;       // 可運行於操作系統的主版本號
+46h    WORD    MinorImageVersion;       // 可運行於操作系統的次版本號
+48h    WORD    MajorSubsystemVersion;  // 要求最低子系統版本的主版本號
+4Ah    WORD    MinorSubsystemVersion;  // 要求最低子系統版本的次版本號
+4Ch    DWORD   Win32VersionValue;       // 莫須有字段,不被病毒利用的話一般為0
+50h    DWORD   SizeOfImage;       // 映像裝入內存后的總尺寸
+54h    DWORD   SizeOfHeaders;       // 所有頭 + 區塊表的尺寸大小
+58h    DWORD   CheckSum;       // 映像的校檢和
+5Ch    WORD    Subsystem;       // 可執行文件期望的子系統
+5Eh    WORD    DllCharacteristics;       // DllMain()函數何時被調用,默認為 0
+60h    DWORD   SizeOfStackReserve;       // 初始化時的棧大小
+64h    DWORD   SizeOfStackCommit;       // 初始化時實際提交的棧大小
+68h    DWORD   SizeOfHeapReserve;        // 初始化時保留的堆大小
+6Ch    DWORD   SizeOfHeapCommit;        // 初始化時實際提交的堆大小
+70h    DWORD   LoaderFlags;        // 與調試有關,默認為 0 
+74h    DWORD   NumberOfRvaAndSizes;  // 下邊數據目錄的項數,這個字段自Windows NT 發布以來        // 一直是16
+78h    DWORD   DataDirctory[16];
       // 數據目錄表
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;

這里總共31個字段但是常用的其實就是我用紅色字體標明的。

前面我們已經知道了PE文件頭在40h的位置,則上面的偏移量推斷IMAGE_OPTIONAL_HEADER字段的首個字段在40h+18h=58h的地方,我們還是用hexwrokshop打開那個PE文件。Ctrl+G打開轉移窗口,輸入58則找到了第一個字段位置,如下圖:

  對於這31個字段我們今天最為關心的是最后一個字段DataDirctory[16]我們一眼就能看出這是一個數組,其中的每個元素都是由一個叫做IMAGE_DATA_DIRECTORY的結構組成。這個叫做IMAGE_DATA_DIRACTORY的結構如下:

                                               IMAGE_DATA_DIRACTORY    STRUC

                                               VritualAddress    DWORD    //數據塊的起始RVA

                                              Size             DWORD   //數據塊的長度

                                               IMAGE_DATA_DIRACTORY    RENS

下面是DataDirctory[16]即數據目錄表的各個成員

 

   

索引值在Windows.inc中的預定義值

對應的數據塊

偏移量

0

IMAGE_DIRECTORY_ENTRY_EXPORT

導出表

78h

1

IMAGE_DIRECTORY_ENTRY_IMPORT

導入表

80h

2

IMAGE_DIRECTORY_ENTRY_RESOURCE

資源

88h

3

IMAGE_DIRECTORY_ENTRY_EXCEPTION

異常(具體資料不詳)

90h

4

IMAGE_DIRECTORY_ENTRY_SECURITY

安全(具體資料不詳)

98h

5

IMAGE_DIRECTORY_ENTRY_BASERELOC

重定位表

A0h

6

IMAGE_DIRECTORY_ENTRY_DEBUG

調試信息

A8h

7

IMAGE_DIRECTORY_ENTRY_ARCHITECTURE

版權信息

B0h

8

IMAGE_DIRECTORY_ENTRY_GLOBALPTR

具體資料不詳

B8h

9

IMAGE_DIRECTORY_ENTRY_TLS

Thread Local Storage

C0h

10

IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG

具體資料不詳

C8h

11

IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT

具體資料不詳

D0h

12

IMAGE_DIRECTORY_ENTRY_IAT

導入函數地址表

D8h

13

IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT

具體資料不詳

E0h

14

IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR

具體資料不詳

      E8h

15

未使用

 

保留

 

  這張表的16個成員中第一個成員IMAGE_DIRECTORY_ENTRY_EXPORT(導出表)和第二個成員IMAGE_DIRECTORY_ENTRY_EXPORT(導入表)非常重要。下面我們用另一個PE文件來查看信息。由於前面的PE.exe沒有輸出表,所以換一個Dumped.DLL這個有輸出表的來查看結構。步驟如下:

1.Hexwrokshop打開文件,首先找到PE文件頭位置,一般都是在載入起始位+3ch處,如下圖所示。

 圖中被選中的黑色處100h,故可知PE文件頭在100h處,用快捷鍵跳ctrl+G跳轉到該處上圖標黑部分即PE文件頭位置。

2.找到了PE文件頭的位置,接下來我們來找DataDirctory[16]各個成員位置。第一個成員輸出表位於PE文件頭+78h位置即100h+78h=178h處,如下圖:

由於每個結構都占8個字節,所以可以知道輸出表的其實位置在4000h處,大小為45h

輸入表的位置位100h+80h=180h處,如下圖:

 

由上圖可知輸入表的起始位置在3000h處,大小為52h

3.其實除了這么查找,還有一種更為簡單的方式。

我們要用到另一個工具LordPE

步驟如下:

1)打開lordPE,點擊PE編輯器即可查看PE文件頭的許多信息,如下圖:

 

2)再點擊目錄按鈕即可查看數據目錄表的相關信息。如下圖:

 

由上圖我們直接就能看到輸出表RVA4000h大小為45h,輸入表的RVA3000h,大小為52h。這和我們計算的查找的結果一致。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM