這兩天對于PE的學習總結:
1.PE結構的應用
(1)windows下exe檔案
(2)動态連結庫(大部分是以dll為擴充名得檔案)
2.關于PE分節
(1)節省硬碟空間 (2)一個應用程式多開
對齊 | 舊式的電腦 | 新款 |
硬碟對齊 | 200h | 1000h |
記憶體對齊 | 1000h | 1000h |
3.PE整體結構
DOS頭 NT頭 節表/塊表 .text塊 .rdata塊 data塊
(後面這幾個快不确定位置和數量,這些由節表确定)
下面介紹的都是幾個頭中重點的幾個辨別,是以詳細的自己百度
4. DOS頭(一般運用在16位系統中 )
WORD e_magic * "MZ标記" 用于判斷是否為可執行檔案. (即判斷是否在windows上執行)
DWORD e_lfanew; * PE頭相對于檔案的偏移,用于定位PE檔案
DOS頭和NT頭之間由垃圾資料填充
5.NT頭
NT頭分為三部分(1)PE标記(2)标準PE頭(3)可選PE頭
(1)PE标記
dword signature (由DoS頭裡e_lfanew确定位置)
(2)标準PE頭 fileheader
WORD Machine; * 程式運作的CPU型号:0x0 任何處理器/0x14C 386及後續處理器
WORD NumberOfSections; * 檔案中存在的節的總數,如果要新增節或者合并節 就要修改這個值.
DWORD TimeDateStamp; * 時間戳:檔案的建立日期和時間(和作業系統的建立時間無關),編譯器填寫的.
DWORD PointerToSymbolTable;
DWORD NumberOfSymbols;
WORD SizeOfOptionalHeader; * 可選PE頭的大小,32位PE檔案預設E0h 64位PE檔案預設為F0h 大小可以自定義.
WORD Characteristics; * 檔案屬性,每個位有不同的含義,普通exe檔案值為10Fh 即0 1 2 3 8位置1 Dll檔案一般是210Eh
(3)可選pe頭 optionalheader(由标準pe頭裡sizeOfOptionalHeader确定)
WORD Magic; * 說明檔案類型:10B 32位下的PE檔案 20B 64位下的PE檔案
BYTE MajorLinkerVersion;
BYTE MinorLinkerVersion;
DWORD SizeOfCode;* 所有代碼節的和,必須是FileAlignment的整數倍 編譯器填的 沒用
DWORD SizeOfInitializedData;* 已初始化資料大小的和,必須是FileAlignment的整數倍 編譯器填的 沒用
DWORD SizeOfUninitializedData;* 未初始化資料大小的和,必須是FileAlignment的整數倍 編譯器填的 沒用
DWORD AddressOfEntryPoint;* 程式入口
DWORD BaseOfCode;* 代碼開始的基址,編譯器填的 沒用
DWORD BaseOfData;* 資料開始的基址,編譯器填的 沒用
DWORD ImageBase;* 記憶體鏡像基址
DWORD SectionAlignment;* 記憶體對齊
DWORD FileAlignment;* 檔案對齊
WORD MajorOperatingSystemVersion;
WORD MinorOperatingSystemVersion;
WORD MajorImageVersion;
WORD MinorImageVersion;
WORD MajorSubsystemVersion;
WORD MinorSubsystemVersion;
DWORD Win32VersionValue;
DWORD SizeOfImage;* 記憶體中整個PE檔案的映射的尺寸,可以比實際的值大,但必須是SectionAlignment的整數倍
DWORD SizeOfHeaders;* 所有頭+節表按照檔案對齊後的大小,否則加載會出錯
DWORD CheckSum;* 校驗和,一些系統檔案有要求.用來判斷檔案是否被修改.
WORD Subsystem;
WORD DllCharacteristics;
DWORD SizeOfStackReserve;* 初始化時保留的堆棧大小
DWORD SizeOfStackCommit;* 初始化時實際送出的大小 DOS
DWORD SizeOfHeapReserve;* 初始化時保留的堆大小 ...
DWORD SizeOfHeapCommit;* 初始化時實踐送出的大小 PE标記
DWORD LoaderFlags; 标準PE
DWORD NumberOfRvaAndSizes;* 目錄項數目 可選PE頭
6.節表(由标準PE頭裡NumberOfsections可知節表數目)
#define IMAGE_SIZEOF_SHORT_NAME 8
typedef struct _IMAGE_SECTION_HEADER {
BYTE Name[IMAGE_SIZEOF_SHORT_NAME];
union {
DWORD PhysicalAddress;
DWORD VirtualSize;
} Misc;
DWORD VirtualAddress;
DWORD SizeOfRawData;
DWORD PointerToRawData;
DWORD PointerToRelocations;
DWORD PointerToLinenumbers;
WORD NumberOfRelocations;
WORD NumberOfLinenumbers;
DWORD Characteristics;
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
1、Name 8個位元組 一般情況下是以"\0"結尾的ASCII嗎字元串來辨別的名稱,内容可以自定義.
注意:該名稱并不遵守必須以"\0"結尾的規律,如果不是以"\0"結尾,系統會截取8個位元組的長度進行處理.
2、Misc 雙字 是該節在沒有對齊前的真實尺寸,該值可以不準确。
3、VirtualAddress 節區在記憶體中的偏移位址。加上ImageBase才是在記憶體中的真正位址.
4、SizeOfRawData 節在檔案中對齊後的尺寸
5、PointerToRawData 節區在檔案中的偏移.
6、PointerToRelocations 在obj檔案中使用 對exe無意義
7、PointerToLinenumbers 行号表的位置 調試的時候使用
8、NumberOfRelocations 在obj檔案中使用 對exe無意義
9、NumberOfLinenumbers 行号表中行号的數量 調試的時候使用
10、Characteristics * 節的屬性
(這是一個節表資訊,幾個節表資訊連續)
7.三種不同的位址
檔案中的位址(FA): 在檔案位址空間中,檔案載入的起始位置總是等于0,FA位址表現為一個偏移位址;
虛拟位址(VA):PE檔案被映射到記憶體中時,在記憶體中的映射位址;
相對偏移位址(RVA):程式某一結構的VA減去FA的結果;
程式被裝載入記憶體中時,由檔案結構不變,故其RVA不變,但裝載起始位址不變,因為很難保證計算機的運作狀态時時刻刻都是一緻的。