PE檔案格式(一)
- 一.介紹
- 二.PE檔案格式
- 1. 基本結構
- 1.1 基本結構
- 1.2VA&RVA
- 1.3PE頭
- DOS頭
- DOS存根
- 1.4 NT頭
- 1.5 NT頭:檔案頭
- 1.6 可選頭定義
- 1.7 節表
- 1.8 節資料
一.介紹
-
PE檔案是Windows作業系統下使用的可執行檔案檔案格式,
-
PE檔案是指32位的可執行檔案,也叫PE32,64位的可執行檔案稱為PE+或者PE32+,是PE檔案的一種擴展形式(不是PE64),
二.PE檔案格式

以上的檔案型別中,OBJ(物件)檔案是不可以執行的,其他都是可以執行的,DLL,SYS檔案不能直接在shell上執行,但是在除錯器或服務上是可執行的,(學過匯編語言的同學都知道OBJ是編譯結果檔案,也是PE檔案)
下面以記事本(notepad.exe)程式進行簡單說明,首先使用Hex Editor打丁開記事本程式,

圖是notepad.exe檔案的起始部分,也是PE檔案的頭部分(PE header),notepad.exe檔案運行需要的所有資訊就存盤在這個PE頭中,
在學習PE檔案時,最重要的就是學習PE頭中的結構體,
書中將以 Windows XP SP3 的notepad.exe 為例進行說明,與其他版本Windows 下的notepad.exe 檔案結構類似,但是地址不同,
1. 基本結構
1.1 基本結構
notepad.exe具有普通PE檔案的基本結構,
從DOS頭(DOS header)到節區頭(Sectionheader)是PE頭部分,其下的節區合稱PE體,檔案中使用偏移(o1fset),記憶體中使用VA (Virtual Address,虛擬地址)來表示位置,檔案加載到記憶體時,情況就會發生變化(節區的大小、位置等),檔案的內容一般可分為代碼(.text)、資料data)、資源(.rsrc)節,分別保存,
提示
根據所用的不同開發工具(VB/VC++/Delphiletc)與編譯選項,節區的名稱、大小個數、存盤的內容等都是不同的,
最重要的是它們按照不同的用途分類保存到不同的節中,

各節區頭定義了各節區在檔案或記憶體中的大小、位置、屬性等,

1.2VA&RVA
RVA+Imagebase=VA
RVA是相對虛擬地址(相對地址)
VA是行程虛擬記憶體的絕對地址
Imagebase是基址
32位系統中VA的范圍是00000000~FFFFFFFF
1.3PE頭
DOS頭
一個PE檔案起始的部分開始就是DOS頭,這和GIF,BMP,JPG,RAR等等都一樣,只是在檔案起始部位標識這個檔案屬于什么檔案型別,這里是DOS頭的結構體:
typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header
WORD e_magic; // Magic number
WORD e_cblp; // Bytes on last page of file
WORD e_cp; // Pages in file
WORD e_crlc; // Relocations
WORD e_cparhdr; // Size of header in paragraphs
WORD e_minalloc; // Minimum extra paragraphs needed
WORD e_maxalloc; // Maximum extra paragraphs needed
WORD e_ss; // Initial (relative) SS value
WORD e_sp; // Initial SP value
WORD e_csum; // Checksum
WORD e_ip; // Initial IP value
WORD e_cs; // Initial (relative) CS value
WORD e_lfarlc; // File address of relocation table
WORD e_ovno; // Overlay number
WORD e_res[4]; // Reserved words
WORD e_oemid; // OEM identifier (for e_oeminfo)
WORD e_oeminfo; // OEM information; e_oemid specific
WORD e_res2[10]; // Reserved words
LONG e_lfanew; // File address of new exe header
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
IMAGE_DOS_HEADER結構體的大小為64位元組,而在結構體中必須知道的兩個重要成員:
e_magic:DOS簽名(MZ->4D5A)
e_ifanew:指示NT頭的偏移(可變值)
DOS存根
DOS存根在DOS頭下方,是由代碼和資料混合組成的,

DOS存根是一段簡單的DOS程式,主要用來輸出類似“This program cannot be run in DOS mode.”的提示陳述句,由于DOS存根里的內容無關緊要,所以可以把這部分用來存盤其他資料而不改變程式原本的功能,
1.4 NT頭
IMAGE_NT_HEADERS結構體:


- 這個PE頭標志,也就是標準PE頭
- NT頭這個結構體的大小為F8
1.5 NT頭:檔案頭


20個位元組,對應的結構體名字:IMAGE_FILE_HEADER STRUCT
從結構的定義可以看到第二個欄位是當前PE檔案的節的數目,
Machine:指出該檔案運行所需的CPU,
NumberOfSections:檔案的節數目,
Characteristics檔案屬性:區分檔案是exe還是dll等,
1.6 可選頭定義

對應的結構體名字:IMAGE_OPTIONAL_HEADER32 STRUCT
由于可選頭欄位數目多達32個,這里沒有對全部欄位的定義進行列舉,只列舉了幾個相對重要的一些欄位(12個),
可選頭中定義了如下重要資訊:
- 所有含代碼的節的總大小
- 所有含已初始化資料的節的總大小
- 所有含未初始化資料的節的大小
- 程式執行入口RVA
- 代碼的節的起始RVA
- 資料的節的起始RVA
- 程式的建議裝載地址
- 記憶體中的節的對齊粒度
- 檔案中的節的對齊粒度
- 記憶體中整個PE映像尺寸
- 所有頭+節表的大小
- 匯出表 匯入表
- 資源
- 重定位表
- 除錯資訊
- 著作權資訊
- 匯入函式地址表
1.7 節表

節表:PE代碼和資料的結構資料,指示裝載系統代碼段在哪里,資料段在哪里等,
PE檔案中所有節的屬性都被定義在節表(段表)中,節表是一個由IMAGE_SECTION_HEADER結構組成的陣列,每個結構用來描述一個節,
結構的排列順序和它們描述的節在檔案中的排列順序是一致的,全部有效結構的最后以一個空的IMAGE_SECTION_HEADER結構作為結束,所以節表中總的IMAGE_SECTION_HEADER結構數量等于節的數量加一,節表總是被存放在緊接在PE檔案頭的地方,也就是從PE檔案頭開始的偏移為00f8h的地方,
(注意:不是檔案本身的頭部,由于程式的dos塊的大小并不是固定的,所以導致PE頭相對于mz頭的偏移變化的,所以我們在計算偏移的時候,對于PE頭后面的資料都習慣用相對于PE頭的偏移,PE頭大小是固定的的,)
在檔案頭中已經定義了檔案的節的數目:0ah個,那么該檔案的節表共有11個IMAGE_SECTION_HEADER結構,
1.8 節資料
常見的節資料:
- text:代碼段,是在編譯或匯編結束時產生的一種塊,它的內容全部是指令代碼,也有的編譯器將該段命名為.code
- .data:初始化的資料塊,是初始化的資料塊,包含那些編譯時被初始化的變數、字串
- .idata:輸入表,包含其他外來dll的函式和資料資訊,也就是輸入表,也有人稱之為匯入表,
- .rsrc:資源資料塊,包含模塊的全部資源資料,如圖示、選單、位圖等,
- .reloc:重定位表,用于保存基址的重定位表,即當裝在程式不能按照連接器所指定的地址裝載檔案是,需要對指令或已經初始化的變數進行調整,該塊中也包含了調整程序中所需要的一些資料,如果裝載能夠正常裝在則忽略此段中的資料,
- .edata:匯出表,是pe檔案的輸出表,以供其他模塊使用,并不是每個pe檔案都有此資料段,因為有的檔案并不需要輸出一些函式,該資料段常見于動態連接庫檔案中,
- .radata:存放除錯目錄、說明字串,該資料塊并不常見主要是用于存放一些除錯資訊,
后續更新PE檔案的其他學習內容
參考教材《逆向工程核心原理》
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/323320.html
標籤:其他
