小甲魚PE詳解之IMAGE_OPTIONAL_HEADER32 結構定義即各個屬性的作用(PE詳解03)

typedef 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    IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
       // 數據目錄表
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;


事實上,這個結構中的大部分字段都不重要,大家可以從註釋中理解它們的含義,小甲魚將比較重要的字段在下邊跟大家詳細講解。另外,這玩意千萬不要去背啊,我們要把絕大多數的時間拿來改變,而不是記住。不用做筆記,把這篇文章轉載到您的博客就行(最好註明:小甲魚是帥哥)吼 吼 ^_^


●  AddressOfEntryPoint字段

指出文件被執行時的入口地址,這是一個RVA地址(RVA的含義在下一節中詳細介紹)。如果在一個可執行文件上附加了一段代碼並想讓這段代碼首先被執行,那麼只需要將這個入口地址指向附加的代碼就可以了。


●  ImageBase字段

指出文件的優先裝入地址。也就是說當文件被執行時,如果可能的話,Windows優先將文件裝入到由ImageBase字段指定的地址中,只有指定的地址已經被**模塊使用時,文件才被裝入到**地址中。鏈接器產生可執行文件的時候對應這個地址來生成機器碼,所以當文件被裝入這個地址時不需要進行重定位操作,裝入的速度最快,如果文件被裝載到**地址的話,將不得不進行重定位操作,這樣就要慢一點。


對於EXE文件來說,由於每個文件總是使用獨立的虛擬地址空間,優先裝入地址不可能被**模塊佔據,所以EXE總是能夠按照這個地址裝入,這也意味着EXE文件不再需要重定位信息。對於DLL文件來說,由於多個DLL文件全部使用宿主EXE文件的地址空間,不能保證優先裝入地址沒有被**的DLL使用,所以DLL文件中必須包含重定位信息以防萬一。因此,在前面介紹的 IMAGE_FILE_HEADER 結構的 Characteristics 字段中,DLL 文件對應的 IMAGE_FILE_RELOCS_STRIPPED 位總是爲0,而EXE文件的這個標誌位總是爲1。

在鏈接的時候,可以通過對link.exe指定/base:address選項來自定義優先裝入地址,如果不指定這個選項的話,一般EXE文件的默認優先裝入地址被定爲00400000h,而DLL文件的默認優先裝入地址被定爲10000000h。


●  SectionAlignment 字段和 FileAlignment字段

SectionAlignment字段指定了節被裝入內存後的對齊單位。也就是說,每個節被裝入的地址必定是本字段指定數值的整數倍。而FileAlignment字段指定了節存儲在磁盤文件中時的對齊單位。


●  Subsystem字段

指定使用界面的子系統,它的取值如表17.3所示。這個字段決定了系統如何爲程序建立初始的界面,鏈接時的/subsystem:**選項指定的就是這個字段的值,在前面章節的編程中我們早已知道:如果將子系統指定爲Windows CUI,那麼系統會自動爲程序建立一個控制檯窗口,而指定爲Windows GUI的話,窗口必須由程序自己建立。


界面子系統的取值和含義

取   值

Windows.inc中的預定義值

含   義

0

IMAGE_SUBSYSTEM_UNKNOWN

未知的子系統

1

IMAGE_SUBSYSTEM_NATIVE

不需要子系統(如驅動程序)

2

IMAGE_SUBSYSTEM_WINDOWS_GUI

Windows圖形界面

3

IMAGE_SUBSYSTEM_WINDOWS_CUI

Windows控制檯界面

5

IMAGE_SUBSYSTEM_OS2_CUI

OS2控制檯界面

7

IMAGE_SUBSYSTEM_POSIX_CUI

POSIX控制檯界面

8

IMAGE_SUBSYSTEM_NATIVE_WINDOWS

不需要子系統

9

IMAGE_SUBSYSTEM_WINDOWS_CE_GUI

Windows CE圖形界面


●  DataDirectory字段

這個字段可以說是最重要的字段之一,它由16個相同的IMAGE_DATA_DIRECTORY結構組成,雖然PE文件中的數據是按照裝入內存後的頁屬性歸類而被放在不同的節中的,但是這些處於各個節中的數據按照用途可以被分爲導出表、導入表、資源、重定位表等數據塊,這16個IMAGE_DATA_DIRECTORY結構就是用來定義多種不同用途的數據塊的(如表17.4所示)。IMAGE_DATA_DIRECTORY結構的定義很簡單,它僅僅指出了某種數據塊的位置和長度。

IMAGE_DATA_DIRECTORY STRUCT

 VirtualAddress DWORD ? ;數據的起始RVA

 isize DWORD ? ;數據塊的長度

IMAGE_DATA_DIRECTORY ENDS

數據目錄列表的含義

索   引

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

對應的數據塊

0

IMAGE_DIRECTORY_ENTRY_EXPORT

導出表

1

IMAGE_DIRECTORY_ENTRY_IMPORT

導入表

2

IMAGE_DIRECTORY_ENTRY_RESOURCE

資源

3

IMAGE_DIRECTORY_ENTRY_EXCEPTION

異常(具體資料不詳)

4

IMAGE_DIRECTORY_ENTRY_SECURITY

安全(具體資料不詳)

5

IMAGE_DIRECTORY_ENTRY_BASERELOC

重定位表

6

IMAGE_DIRECTORY_ENTRY_DEBUG

調試信息

7

IMAGE_DIRECTORY_ENTRY_ARCHITECTURE

版權信息

8

IMAGE_DIRECTORY_ENTRY_GLOBALPTR

具體資料不詳

9

IMAGE_DIRECTORY_ENTRY_TLS

Thread Local Storage

10

IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG

具體資料不詳

11

IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT

具體資料不詳

12

IMAGE_DIRECTORY_ENTRY_IAT

導入函數地址表

13

IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT

具體資料不詳

14

IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR

具體資料不詳

15

未使用

 


在PE文件中尋找特定的數據時就是從這些IMAGE_DATA_DIRECTORY結構開始的,比如要存取資源,那麼必須從第3個IMAGE_DATA_DIRECTORY結構(索引爲2)中得到資源數據塊的大小和位置;同理,如果要查看PE文件導入了哪些DLL文件的哪些API函數,那就必須首先從第2個IMAGE_DATA_DIRECTORY結構得到導入表的位置和大小。

發佈了19 篇原創文章 · 獲贊 14 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章