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