IT系統(tǒng)運(yùn)維-PE文件結(jié)構(gòu)
2020-05-01 17:37 作者:艾銻無限 瀏覽量:
在Windows
系統(tǒng)運(yùn)維中,對(duì)各種文件結(jié)構(gòu)必須有個(gè)清晰的了解。其中PE文件結(jié)構(gòu)是我們
系統(tǒng)運(yùn)維必須要了解的結(jié)構(gòu)體。PE(Portable Executable:可移植的執(zhí)行體)是Win32環(huán)境自身所帶的可執(zhí)行文件格式。它的一些特性繼承自Unix的Coff(Common Object File Format)文件格式。可移植的執(zhí)行體意味著此文件格式是跨win32平臺(tái)的,即使Windows運(yùn)行在非Intel的CPU上,任何win32平臺(tái)的PE裝載器都能識(shí)別和使用該文件格式。當(dāng)然,移植到不同的CPU上PE執(zhí)行體必然得有一些改變。除VxD和16位的Dll外,所有 win32執(zhí)行文件都使用PE文件格式。因此,研究PE文件格式是我們洞悉Windows結(jié)構(gòu)的良機(jī)。
文件結(jié)構(gòu)
圖表結(jié)構(gòu):
DOS頭是用來兼容MS-DOS操作系統(tǒng)的
NT頭包含windows PE文件的主要信息
節(jié)表:是PE文件后續(xù)節(jié)的描述
節(jié):每個(gè)節(jié)實(shí)際上是一個(gè)容器,可以包含代碼、數(shù)據(jù)等等,每個(gè)節(jié)可以有獨(dú)立的內(nèi)存權(quán)限,比如代碼節(jié)默認(rèn)有讀/執(zhí)行權(quán)限,節(jié)的名字和數(shù)量可以自己定義
文件地址
1、PE文件在硬盤上和在內(nèi)存里是不完全一樣的,被加載到內(nèi)存以后其占用的虛擬地址空間要比在硬盤上占用的空間大一些,這是因?yàn)楦鱾€(gè)節(jié)在硬盤上是連續(xù)的,而在內(nèi)存中是按頁(yè)對(duì)齊的。
2、PE結(jié)構(gòu)內(nèi)部,表示某個(gè)位置的地址采用了兩種方式,針對(duì)在硬盤上存儲(chǔ)文件中的地址,稱為原始存儲(chǔ)地址或物理地址表示距離文件頭的偏移;另外一種是針對(duì)加載到內(nèi)存以后映象中的地址,稱為相對(duì)虛擬地址(RVA),表
示相對(duì)內(nèi)存映象頭的偏移。
3、CPU的某些指令是需要使用絕對(duì)地址的,比如取全局變量的地址,傳遞函數(shù)的地址編譯以后的匯編指令中肯定需要用到絕對(duì)地址而不是相對(duì)映象頭的偏移,因此PE文件會(huì)建議操作系統(tǒng)將其加載到某個(gè)內(nèi)存地址(這個(gè)叫基地
址),這種表示方式叫做虛擬地址(VA)
4、PE文件無法加載到預(yù)期的地址,那么系統(tǒng)會(huì)幫他重新選擇一個(gè)合適的基地址將他加載到此處,這時(shí)原有的VA就全部失效了,NT頭保存了PE文件加載所需的信息,在不知道PE會(huì)加載到哪個(gè)基地址之前,VA是無效的,所以在
PE文件頭中大部分是使用RVA來表示地址的
可執(zhí)行文件頭
1、PE文件可以導(dǎo)出函數(shù)讓其他的PE文件使用,也可以從其他PE文件導(dǎo)入函數(shù)
2、PE文件通過導(dǎo)出表指明自己導(dǎo)出那些函數(shù),通過導(dǎo)入表指明需要從哪些模塊導(dǎo)入哪些函數(shù)。
3、DOS頭和NT頭就是PE文件中兩個(gè)重要的文件頭
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;
重點(diǎn)關(guān)注字段
e_magic:一個(gè)WORD類型,值是一個(gè)常數(shù)0x4D5A,用文本編輯器查看該值位‘MZ’,可執(zhí)行文件必須都是'MZ'開頭。
e_lfanew:為32位可執(zhí)行文件擴(kuò)展的域,用來表示DOS頭之后的NT頭相對(duì)文件起始地址的偏移。
NT頭
typedef struct _IMAGE_NT_HEADERS {
DWORD Signature;
IMAGE_FILE_HEADER FileHeader;
IMAGE_OPTIONAL_HEADER32 OptionalHeader;
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
Signature:類似于DOS頭中的e_magic,其高16位是0,低16是0x4550,用字符表示是'PE‘。
I
MAGE_FILE_HEADER是PE文件頭
typedef struct _IMAGE_FILE_HEADER {
WORD Machine;
WORD NumberOfSections;
DWORD TimeDateStamp;
DWORD PointerToSymbolTable;
DWORD NumberOfSymbols;
WORD SizeOfOptionalHeader;
WORD Characteristics;
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
PE文件頭
Machine:該文件的運(yùn)行平臺(tái),是x86、x64還是I64
NumberOfSections:該P(yáng)E文件中有多少個(gè)節(jié),也就是節(jié)表中的項(xiàng)數(shù)。
TimeDateStamp:PE文件的創(chuàng)建時(shí)間,一般有連接器填寫。
PointerToSymbolTable:COFF文件符號(hào)表在文件中的偏移。
NumberOfSymbols:符號(hào)表的數(shù)量。
SizeOfOptionalHeader:緊隨其后的可選頭的大小。
Characteristics:可執(zhí)行文件的屬性,可以是下面這些值按位相或。
PE導(dǎo)入表
IMAGE_DIRECTORY_ENTRY_IMPORT就是導(dǎo)入表,在PE文件加載時(shí),會(huì)根據(jù)這個(gè)表里的內(nèi)容加載依賴的DLL,并填充所需函數(shù)的地址IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT叫做綁定導(dǎo)入表,在第一種導(dǎo)入表導(dǎo)入
地址的修正是在PE加載時(shí)完成,如果一個(gè)PE文件導(dǎo)入的DLL或者函數(shù)多那么加載起來就會(huì)略顯的慢一些,所以出現(xiàn)了綁定導(dǎo)入,在加載以前就修正了導(dǎo)入表,這樣就會(huì)快一些。IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT
叫做延遲導(dǎo)入表,一個(gè)PE文件也許提供了很多功能,也導(dǎo)入了很多其他DLL,但是并非每次加載都會(huì)用到它提供的所有功能,也不一定會(huì)用到它需要導(dǎo)入的所有DLL,因此延遲導(dǎo)入就出現(xiàn)了,只有在一個(gè)PE文件真正用到需要的
DLL,這個(gè)DLL才會(huì)被加載,甚至于只有真正使用某個(gè)導(dǎo)入函數(shù),這個(gè)函數(shù)地址才會(huì)被修正。
IMAGE_DIRECTORY_ENTRY_IAT是導(dǎo)入地址表,前面的三個(gè)表其實(shí)是導(dǎo)入函數(shù)的描述,真正的函數(shù)地址是被填充在導(dǎo)入地址表中的。
裝載PE文件的主要步驟
第一:當(dāng)PE文件被執(zhí)行,PE裝載器檢查DOS MZ header里的PE header偏移量。如果找到,則跳轉(zhuǎn)到PE header。
第二:PE裝載器檢查PE header的有效性。如果有效,就跳轉(zhuǎn)到PE header的尾部。
第三:緊跟PE header的是節(jié)表。PE裝載器讀取其中的節(jié)索引信息,并采用文件映射方法將這些節(jié)映射到內(nèi)存,同時(shí)附上節(jié)表里指定的節(jié)屬性。
第四:PE文件映射入內(nèi)存后,PE裝載器將處理PE文件中類似import table(引入表)邏輯部分。
艾銻無限科技專業(yè):IT外包、
企業(yè)外包、
北京IT外包、桌面運(yùn)維、
弱電工程、網(wǎng)站開發(fā)、wifi覆蓋方案,
網(wǎng)絡(luò)外包,網(wǎng)絡(luò)管理服務(wù),
網(wǎng)管外包,綜合布線,服務(wù)器運(yùn)維服務(wù),
中小企業(yè)it外包服務(wù),服務(wù)器維保公司,硬件運(yùn)維,網(wǎng)站運(yùn)維服務(wù)
以上文章由北京艾銻無限科技發(fā)展有限公司整理