[PE結構分析] 5.IMAGE_OPTIONAL_HEADER
結構體源代碼如下:
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]; // 數據目錄表 ***(必須了解,重點)*** winNT發布到win10,IMAGE_NUMBEROF_DIRECTORY_ENTRIES一直都是16 } IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
AddressOfEntryPoint ***(必須了解)***
程序開始執行的地址,這是一個RVA(相對虛擬地址)。對於exe文件,這裏是啟動代碼;對於dll文件,這裏是libMain()的地址。如果在一個可執行文件上附加了一段代碼並想讓這段代碼首先被執行,那麽只需要將這個入口地址指向附加的代碼就可以了。在脫殼時第一件事就是找入口點,指的就是這個值。
ImageBase ***(必須了解)***
PE文件的優先裝入地址。也就是說,當文件被執行時,如果可能的話(當前地址沒有被使用),Windows優先將文件裝入到由ImageBase字段指定的地址中。
對於EXE文件來說,由於每個文件總是使用獨立的虛擬地址空間,優先裝入地址不可能被**模塊占據,所以EXE總是能夠按照這個地址裝入。
這也意味著EXE文件不再需要重定位信息。
對於DLL文件來說,由於多個DLL文件全部使用宿主EXE文件的地址空間,不能保證優先裝入地址沒有被**的DLL使用,所以DLL文件中必須包含重定位信息以防萬一。
因此,在前面介紹的 IMAGE_FILE_HEADER 結構的 Characteristics 字段中,DLL 文件對應的 IMAGE_FILE_RELOCS_STRIPPED 位總是為0,而EXE文件的這個標誌位總是為1。
如果沒有指定的話,dll文件默認為0x10000000;exe文件默認為0x00400000,但是在Windows CE平臺上是0x00010000。此值必須是64K bytes的倍數!
SectionAlignment ***(必須了解)***
內存中區塊的對齊單位。區塊總是對齊到這個值的整數倍。此字段必須大於或等於 FileAlignment ,默認值是系統頁面的大小。32位cpu通常值為 0x1000(十六進制),即4096,即4KB。64位cpu通常為 8kB
FileAlignment ***(必須了解)***
pe文件中區塊的對齊單位,以bytes(字節)為單位。此值必須是2的次方倍,但是必須在512和64K區間之間(閉區間[521, 64*1024=65536]),如果SectionAlignment小於系統頁面的大小,那麽SectionAlignment的大小就和FileAlignment相同。pe文件中默認值為 521 字節(0.5KB) 即 0x200(十六進制)。
Subsystem ***(必須了解)***
pe文件的用戶界面使用的子系統類型。定義如下:
#define IMAGE_SUBSYSTEM_UNKNOWN 0 // 未知子系統 #define IMAGE_SUBSYSTEM_NATIVE 1 // 不需要子系統(如驅動程序) #define IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Windows GUI 子系統 #define IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Windows 控制臺子系統 #define IMAGE_SUBSYSTEM_OS2_CUI 5 // OS/2 控制臺子系統 #define IMAGE_SUBSYSTEM_POSIX_CUI 7 // Posix 控制臺子系統 #define IMAGE_SUBSYSTEM_NATIVE_WINDOWS 8 // 鏡像是原生 Win9x 驅動程序 #define IMAGE_SUBSYSTEM_WINDOWS_CE_GUI 9 // Windows CE 圖形界面
例如,Visual Studio 2015中編譯程序時可以在圖形界面設置鏈接選項:
更多請查看:
微軟官方文檔:https://msdn.microsoft.com/en-us/library/windows/desktop/ms680339(v=vs.85).aspx
DataDirectory ***(必須了解,重要)***
這個字段可以說是最重要的字段之一,它由16個相同的IMAGE_DATA_DIRECTORY結構組成。其結構如下:
typedef struct _IMAGE_DATA_DIRECTORY {
DWORD VirtualAddress; // 相對虛擬地址
DWORD Size; // 數據塊的大小
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
也就是定義了某塊的位置和大小。
雖然PE文件中的數據是按照裝入內存後的頁屬性歸類而被放在不同的節中的,但是這些處於各個節中的數據按照用途可以被分為導出表、導入表、資源、重定位表等數據塊,這16個IMAGE_DATA_DIRECTORY結構就是用來定義多種不同用途的數據塊的(如下表所示)。IMAGE_DATA_DIRECTORY結構的定義很簡單,它僅僅指出了某種數據塊的位置和長度。
#define IMAGE_DIRECTORY_ENTRY_EXPORT 0 // Export Directory #define IMAGE_DIRECTORY_ENTRY_IMPORT 1 // Import Directory #define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 // Resource Directory #define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 // Exception Directory #define IMAGE_DIRECTORY_ENTRY_SECURITY 4 // Security Directory #define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 // Base Relocation Table #define IMAGE_DIRECTORY_ENTRY_DEBUG 6 // Debug Directory // IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 // (X86 usage) #define IMAGE_DIRECTORY_ENTRY_ARCHITECTURE 7 // Architecture Specific Data #define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 // RVA of GP #define IMAGE_DIRECTORY_ENTRY_TLS 9 // TLS Directory #define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 // Load Configuration Directory #define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11 // Bound Import Directory in headers #define IMAGE_DIRECTORY_ENTRY_IAT 12 // Import Address Table #define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13 // Delay Load Import Descriptors #define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14 // COM Runtime descriptor
給出說明:
Offset (PE/PE32+) |
Size |
Field |
Description |
96/112 |
8 |
Export Table |
The export table address and size. For more information see section 6.3, “The .edata Section (Image Only).” |
104/120 |
8 |
Import Table |
The import table address and size. For more information, see section 6.4, “The .idata Section.” |
112/128 |
8 |
Resource Table |
The resource table address and size. For more information, see section 6.9, “The .rsrc Section.” |
120/136 |
8 |
Exception Table |
The exception table address and size. For more information, see section 6.5, “The .pdata Section.” |
128/144 |
8 |
Certificate Table |
The attribute certificate table address and size. For more information, see section 5.7, “The Attribute Certificate Table (Image Only).” |
136/152 |
8 |
Base Relocation Table |
The base relocation table address and size. For more information, see section 6.6, "The .reloc Section (Image Only)." |
144/160 |
8 |
Debug |
The debug data starting address and size. For more information, see section 6.1, “The .debug Section.” |
152/168 |
8 |
Architecture |
Reserved, must be 0 |
160/176 |
8 |
Global Ptr |
The RVA of the value to be stored in the global pointer register. The size member of this structure must be set to zero. |
168/184 |
8 |
TLS Table |
The thread local storage (TLS) table address and size. For more information, see section 6.7, “The .tls Section.” |
176/192 |
8 |
Load Config Table |
The load configuration table address and size. For more information, see section 6.8, “The Load Configuration Structure (Image Only).” |
184/200 |
8 |
Bound Import |
The bound import table address and size. |
192/208 |
8 |
IAT |
The import address table address and size. For more information, see section 6.4.4, “Import Address Table.” |
200/216 |
8 |
Delay Import Descriptor |
The delay import descriptor address and size. For more information, see section 5.8, “Delay-Load Import Tables (Image Only).” |
208/224 |
8 |
CLR Runtime Header |
The CLR runtime header address and size. For more information, see section 6.10, “The .cormeta Section (Object Only).” |
216/232 |
8 |
Reserved, must be zero |
具體資料見:www.microsoft.com/whdc/system/platform/firmware/PECOFF.mspx 中的pecoff.docx文檔
[PE結構分析] 5.IMAGE_OPTIONAL_HEADER