天天看點

PE檔案格式總結基本介紹1.DOS Header 和 DOS stub2.NT headers3.Section headers4.Sections其他

PE檔案格式總結

  • 基本介紹
  • 1.DOS Header 和 DOS stub
  • 2.NT headers
    • 2.1File header
    • 2.2 Optional header
  • 3.Section headers
  • 4.Sections
  • 其他

時間:202106

基本介紹

PE檔案主要由 檔案頭 和 區段(Section) 構成(如圖所示),檔案頭記錄相關資訊,而區段則存放相關資料。相連代表資料在檔案中存儲緊接上一部分。

PE檔案格式總結基本介紹1.DOS Header 和 DOS stub2.NT headers3.Section headers4.Sections其他

檔案頭部分包括:

(1) DOS Header

(2) DOS Stub

(3) NT Headers

(4) Section Headers

運作時PE檔案由PE加載器加載到記憶體,檔案頭部分将會被加載到 記憶體基址(Image Base) 。但程式運作時一般會加載多個子產品,如果都固定 Image Base 可能會導緻記憶體使用沖突,是以PE檔案會設定一個首選 Image Base,但實際的 Image Base 由 PE 加載器決定。是以,PE 檔案中一般不使用絕對的記憶體位址,而采用相對于 Image Base 偏移的位址,稱為 相對記憶體位址(Relative Virtual Address, RVA) ,其 絕對記憶體位址(Virtual Address, VA) 在加載後計算得到,關系如下:

VA = ImageBase + RVA

區段頭(Section Header) 中包括了該區段的重要資訊,主要包括:區段資料的檔案位置和大小、加載到記憶體時的 RVA 和占用記憶體大小、區段屬性。PE加載器通過讀取區段頭的資訊,将檔案中的區段資料加載到對應的記憶體位址中。檔案中的位置由相對檔案第一個位元組的偏移描述,稱為 檔案偏移位址(File Offset Address, FOA)。

1.DOS Header 和 DOS stub

DESC (Description) : 為相容 ms-dos 系統而存在,DOS stub 為 DOS 根存程式。

FOA : 0x00000000

PE檔案格式總結基本介紹1.DOS Header 和 DOS stub2.NT headers3.Section headers4.Sections其他

e_magic

DESC : 辨別符, 必須為 ”MZ”, 0x5A4D。

e_lfanew

DESC : 新檔案頭 NT headers 的 FOA 。

2.NT headers

DESC : PE 檔案頭。

FOA : IMAGE_DOS_HEADER.elfanew

PE檔案格式總結基本介紹1.DOS Header 和 DOS stub2.NT headers3.Section headers4.Sections其他

Signature

DESC : 辨別符, 必須為 ”PE”,0x00004550。

2.1File header

FOA : IMAGE_DOS_HEADER.elfanew + 0x04

PE檔案格式總結基本介紹1.DOS Header 和 DOS stub2.NT headers3.Section headers4.Sections其他

Machine

DESC : 辨別符,映像檔案适用的機器類型。

描述
0x014C x86 處理器
0x0200 Intel Itanium 處理器
0x8664 x64 處理器

TimeDateStamp

DESC : 檔案的建立時間,等于 1970/01/01 00:00:00 起經過的秒數。

SizeOfOptionalHeader

DESC : Optional Header 的大小,值可以為 224 位元組和 240 位元組,分别表示 32 位和 64 位。該值可以作為 32 位/ 64 位的判斷依據。

Characteristics

DESC : 檔案屬性。

描述
0x0001 重新定位資訊已從檔案中删除,檔案必須在其首選基址處加載,如果基位址不可用,加載器會報錯
0x0002 檔案可執行
0x0004 COFF line number 已經從檔案中删除
0x0008 COFF 符号表條目已經從檔案中删除
0x0010 棄用
0x0020 應用程式可以處理大于 2GB 的位址
0x0080 保留
0x0100 計算機支援 32 位體系架構
0x0200 調試資訊被移除并儲存在另一個檔案中
0x0400 如果此鏡像檔案在可移動媒體上,将其複制到交換檔案中并從中運作
0x0800 如果此鏡像檔案在網絡媒體上,将其複制到交換檔案中并從中運作
0x1000 此鏡像檔案是系統檔案
0x2000 此鏡像檔案是動态連結庫 (DLL)
0x4000 此檔案隻能運作于單處理器機器上
0x8000 保留
值未列出表明官方文檔缺失,之後的表格也是如此

2.2 Optional header

FOA : IMAGE_DOS_HEADER.elfanew + 0x18

PE檔案格式總結基本介紹1.DOS Header 和 DOS stub2.NT headers3.Section headers4.Sections其他
PE檔案格式總結基本介紹1.DOS Header 和 DOS stub2.NT headers3.Section headers4.Sections其他

Magic

DESC : 辨別符。

描述
0x10B 檔案為 32 位程式的可執行映像
0x20B 檔案為 64 位程式的可執行映像
0x107 檔案為 ROM 映像。

SizeOfCode

SizeOfInitializedData

SizeOfUninitializedData

DESC : 代碼段、已初始化和未初始化的資料段的位元組大小,如果存在多個段則為所有段大小之和。

每個 Section 在檔案中的資料都為已初始化的資料,可以直接加載到記憶體中。

未初始化資料應該是用于減小檔案的大小,具體是:如果檔案中 Section 某位置一直到該 Section 結束時的資料初始值均為 0x00,就可以将該部分删去,而 Section 加載到記憶體時的實際大小設定不變,加載時僅加載 Section 在檔案中有的部分,剩下的記憶體則由PE加載器填充 0x00,即由PE加載器完成初始化工作。

AddressOfEntryPoint

DESC : 程式入口點相對于 ImageBase 的偏移位址,即入口點的 RVA。

ImageBase

DESC : 映像被加載到記憶體時第一個位元組的首選基址, 值為 64KB 的倍數。Dll 預設為 0x10000000; 應用程式除了在 Windows CE 上為預設為 0x00010000,其他預設為 0x00400000。

當加載到記憶體後, PE裝載器會将其修改為實際加載的基址。

SectionAlignment

DESC : 區段加載到記憶體時的對齊位元組值,即加載到 SectionAlignment 倍數的記憶體位址處。該值必須不小于 FileAlignment,預設值為系統的頁大小 (4KB)。是以記憶體中相鄰 Section 間一般存在間隙。

FileAlignment

DESC : 區段資料在映像檔案中的對齊位元組值。該值為 512 到 64K 之間 2 的幂(含邊界值),預設值為 512 位元組。是以每個區段末一般會有填充 0x00 的部分,且未被使用。

SizeOfImage

DESC : 映像加載到記憶體後占用的總大小,值必須為 SectionAlignment 的倍數。

SizeOfHeaders

DESC : 檔案頭的大小,為以下幾個值的和,且最終向上舍入到 FileAlignment 的倍數。

a) IMAGE_DOS_HEADER.e_lfanew

b) 4位元組的辨別符

c) IMAGE_FILE_HEADER 的大小

d) 可選頭的大小

e) 所有區段頭的大小

CheckSum

DESC : 校驗和,在以下檔案加載時驗證:所有驅動程式、任何引導時加載的 DLL 和任何加載到關鍵系統程序中的 DLL。

Subsystem

DESC : 運作該映像所需要的子系統類型。

描述
未知子系統
1 無子系統要求(裝置驅動程式和本地系統程序)
2 Windows 圖形使用者界面 (GUI) 子系統
3 Windows 字元模式使用者界面 (CUI) 子系統
5 OS/2 CUI 子系統
7 POSIX CUI 子系統
9 Windows CE 子系統
10 可擴充固件接口 (EFI) 應用程式
11 帶引導服務的 EFI 驅動
12 帶運作時服務的 EFI 驅動
13 EFI ROM 映像
14 Xbox 子系統

DllCharacteristics

DESC : Dll 屬性。

描述
32 位 64 位
0x0001 保留
0x0002 保留
0x0004 保留
0x0008 保留
0x0020 具有64位位址空間的ASLR 無文檔資訊
0x0040 DLL 可以在加載時重新定位
0x0080 強制進行代碼完整性校驗
0x0100 映像與資料執行保護 (DEP) 相容
0x0200 映像可以隔離,但不應該隔離
0x0400 映像不使用結構化異常處理 (SHE),無法在映像中調用任何處理程式
0x0800 不綁定映像
0x1000 映像應該在 AppContainer 中執行 保留
0x2000 WDM 驅動
0x4000 映像支援控制流保護 保留
0x8000 映像支援終端伺服器

SizeOfStackReserve

SizeOfStackCommit

DESC : 棧保留大小和棧送出大小。棧在加載時僅使用 SizeOfStackCommit 大小的記憶體, 剩餘的在達到棧保留大小前每次僅使用一頁。

SizeOfHeapReserve

SizeOfHeapCommit

DESC : 堆保留大小和堆送出大小。堆在加載時僅使用 SizeOfHeapCommit 大小的記憶體, 剩餘的在達到堆保留大小前每次僅使用一頁。

DataDirectory

DESC : 目錄表,為 IMAGE_DATA_DIRECTORY 結構體數組,共 16 個元素,描述相應表項的位置和大小資訊。

PE檔案格式總結基本介紹1.DOS Header 和 DOS stub2.NT headers3.Section headers4.Sections其他

IMAGE_DATA_DIRECTORY.VirtualAddress 為表項内容的 RVA。

表項如下:

索引值 描述
導出表
1 導入表
2 資源目錄
3 異常目錄
4 安全目錄
5 基本重定位表
6 調試資訊目錄
7 特殊結構資料表
8 全局指針寄存器相對虛拟位址
9 線程局部儲存 (TLS) 表
10 加載配置表
11 綁定導入表
12 導入位址表
13 延遲導入描述
14 CLR 頭
15 保留

3.Section headers

DESC : 區段表,由 IMAGE_SECTION_HEADER 結構體數組構成,每個元素描述一個區段的資訊,以 NULL 元素結束。

FOA : IMAGE_DOS_HEADER.elfanew + NT headers大小 (緊跟 NT headers)

PE檔案格式總結基本介紹1.DOS Header 和 DOS stub2.NT headers3.Section headers4.Sections其他

Name

DESC : 區段名, 一個 8 位元組、0x00 填充的 UTF-8 字元串。

如果字元串長度正好為 8 個字元,則不存在 ’\0’ 終止符。如果名稱較長, 此成員值為 正斜杠 (/) + ASCII 表示的十進制數, 該十進制數為名稱在字元串表中的偏移量。可執行映像不使用字元串表,也不支援長度超過 8 個字元的區段名。

Misc.VirtualSize

DESC : 加載到記憶體時整個區段的實際大小, 如果值大于 SizeOfRawData , 說明有未初始化的資料,這部分将由 PE 加載器完成初始化。

僅可執行映像有效,對于 obj 檔案該值為 0。

VirtualAddress

DESC : 區段的 RVA。

對于 obj 檔案該值為重定位前的位址。

SizeOfRawData

DESC : 區段在磁盤上已初始化資料的大小。值必須為 IMAGE_OPTIONAL_HEADER.FileAlignment 的倍數。如果該值小于 Misc.VirtualSize,區段剩餘部分由 PE 加載器填充零,完成初始化。如果區段僅包含未初始化資料, 該值為 0。

PointerToRawData

DESC : 區段資料的 FOA, 值必須為 IMAGE_OPTIONAL_HEADER.FileAlignment 的倍數。如果區段僅包含未初始化資料, 該值為 0。

PointerToRelocations

PointerToLinenumbers

DESC : 區段的重定位項和行号項的檔案指針。如果沒有, 該值為 0。

NumberOfRelocations

NumberOfLinenumbers

DESC: 重定位項數和行号項數。

可執行映像的重定位項數為 0。

Characteristics

DESC : 區段的屬性。

描述
0x00000000 保留
0x00000001 保留
0x00000002 保留
0x00000004 保留
0x00000008 棄用
0x00000010 保留
0x00000020 區段包含可執行代碼
0x00000040 區段包含已初始化資料
0x00000080 區段包含未初始化資料
0x00000100 保留
0x00000200 區段包含注釋或其他資訊, 僅對 obj 檔案有效
0x00000400 保留
0x00000800 區段不會成為映像一部分, 僅對 obj 檔案有效
0x00001000 區段包含 COMDAT 資料, 僅對 obj 檔案有效
0x00002000 保留
0x00004000 重置 TLB 表的風險異常處理位
0x00008000 區段包含通過全局指針引用的資料
0x00010000 保留
0x00020000 保留
0x00040000 保留
0x00080000 保留
0x00100000 按1位元組對齊資料, 僅對 obj 檔案有效
0x00200000 按2位元組對齊資料, 僅對 obj 檔案有效
0x00300000 按4位元組對齊資料, 僅對 obj 檔案有效
0x00400000 按8位元組對齊資料, 僅對 obj 檔案有效
0x00500000 按16位元組對齊資料, 僅對 obj 檔案有效
0x00600000 按32位元組對齊資料, 僅對 obj 檔案有效
0x00700000 按64位元組對齊資料, 僅對 obj 檔案有效
0x00800000 按128位元組對齊資料, 僅對 obj 檔案有效
0x00900000 按256位元組對齊資料, 僅對 obj 檔案有效
0x00A00000 按512位元組對齊資料, 僅對 obj 檔案有效
0x00B00000 按1024位元組對齊資料, 僅對 obj 檔案有效
0x00C00000 按2048位元組對齊資料, 僅對 obj 檔案有效
0x00D00000 按4096位元組對齊資料, 僅對 obj 檔案有效
0x00E00000 按8192位元組對齊資料, 僅對 obj 檔案有效
0x01000000 區段包含擴充重定位
0x02000000 可以根據需要丢棄該區段
0x04000000 區段不能被緩存
0x08000000 區段不能分頁
0x10000000 區段在記憶體中可共享
0x20000000 區段可執行
0x40000000 區段可讀
0x80000000 區段可寫

4.Sections

DESC: 每個區段在檔案中的資料(已初始化資料),大小為相應區段表項的 IMAGE_SECTION_HEADER. SizeOfRawData 值。

FOA : 區段表各項的 PointerToRawData 成員值。

區段在檔案中的資料為已初始化資料 (這裡暫時将可執行代碼也視為已初始化資料),因為對齊要求必須為 IMAGE_OPTIONAL_HEADER. FileAlignment 的倍數,是以檔案中區段末尾一般存在編譯時填充的 0x00 位元組,而 Section Header 中 Misc.VirtualSize 值通常沒有包括這部分填充的初始化資料。但 Misc.VirtualSize 值還包括了未初始化資料大小,是以他們的值在不同情況下有不同大小關系。

IMAGE_SECTION_HEADER.SizeOfRawData = 已初始化資料(含填充資料)大小

IMAGE_SECTION_HEADER.Misc.VirtualSize = 已初始化資料(一般不含填充資料)大小 + 未初始化資料大小

其他

通過 RVA 确定其 FOA 的方法:

a) 分析 Section Headers 确定各區段資料的 RVA 範圍和 FOA 範圍。

b) 比較已知 RVA 和各區段 RVA 範圍,确定已知 RVA 屬于哪個區段。

c) 計算已知 RVA 相對于該區段起始 RVA 的偏移值 Offset。

d) 已知 RVA 對應的 FOA 為該區段起始 FOA 加上一步得到的 Offset。

繼續閱讀