網(wǎng)絡(luò)安全編程:PE文件結(jié)構(gòu)概述
PE結(jié)構(gòu)是Windows下可執(zhí)行文件的標準結(jié)構(gòu),可執(zhí)行文件的裝載、內(nèi)存分布、執(zhí)行等都依賴于PE結(jié)構(gòu),而在逆向分析軟件時,為了有目的、更高效地了解程序,必須掌握PE結(jié)構(gòu)。
PE(Portable Executable),即可移植的執(zhí)行體。在Windows平臺(包括Win 9x、Win NT、Win CE……)下,所有的可執(zhí)行文件(包括EXE文件、DLL文件、SYS文件、OCX文件、COM文件……)均使用PE文件結(jié)構(gòu)。這些使用PE文件結(jié)構(gòu)的可執(zhí)行文件也稱為PE文件。
普通的程序員也許沒有必要掌握PE文件結(jié)構(gòu),因為其大多是開發(fā)服務(wù)性、決策性、輔助性的軟件,比如MIS、HIS、CRM等軟件。但是對于學(xué)習黑客編程和學(xué)習安全編程的Hacker、Cracker和Programmer的人而言,掌握PE文件結(jié)構(gòu)的知識就非常重要了。
1. PE文件結(jié)構(gòu)全貌
Windows系統(tǒng)下的可執(zhí)行文件中包含著各種數(shù)據(jù),包括代碼、數(shù)據(jù)、資源等。雖然Windows系統(tǒng)下的可執(zhí)行文件中包含著如此眾多類型的數(shù)據(jù),但是其存放都是有序、結(jié)構(gòu)化的,這完全依賴于PE文件結(jié)構(gòu)對各種數(shù)據(jù)的管理。同樣,PE結(jié)構(gòu)是由若干個復(fù)雜的結(jié)構(gòu)體組合而成的,不是單單的一個結(jié)構(gòu)體那么簡單,它的結(jié)構(gòu)就像文件系統(tǒng)的結(jié)構(gòu)是由多個結(jié)構(gòu)體組成的。
PE結(jié)構(gòu)包含的結(jié)構(gòu)體有DOS頭、PE標識、文件頭、可選頭、目錄結(jié)構(gòu)、節(jié)表等。要掌握PE結(jié)構(gòu)必須對PE結(jié)構(gòu)有一個整體上的認識,要知道PE結(jié)構(gòu)分為哪些部分,這些部分大概是起什么作用的。有了宏觀上的概念以后,就可以深入地對PE結(jié)構(gòu)的各個結(jié)構(gòu)體進行細致的學(xué)習了。下面給出一張圖,讓大家對PE結(jié)構(gòu)有個大概的了解,如圖1所示。
圖1 PE結(jié)構(gòu)總覽圖
從圖1中可以看出,PE結(jié)構(gòu)分為4大部分,其中每個部分又進行了細分,存在若干個小的部分。從數(shù)據(jù)管理的角度來看,可以把PE文件大致分為兩部分,DOS頭、PE頭和節(jié)表屬于PE文件的數(shù)據(jù)管理結(jié)構(gòu)或數(shù)據(jù)組織結(jié)構(gòu)部分,而節(jié)表數(shù)據(jù)才是PE文件真正的數(shù)據(jù)部分,其中包含著代碼、數(shù)據(jù)、資源等內(nèi)容。
在進行逆向分析時,是對其代碼、數(shù)據(jù)、資源等具體數(shù)據(jù)進行分析,也就是圖1的“節(jié)表數(shù)據(jù)”部分。程序在內(nèi)存中或文件中的組織結(jié)構(gòu)是如何規(guī)劃的,并沒有去具體了解,而這部分內(nèi)容正是圖1的上面3部分內(nèi)容。
2. PE結(jié)構(gòu)各部分簡介
根據(jù)圖1給出的PE結(jié)構(gòu)總覽圖先來大致了解一下每部分的作用。
(1)DOS頭
DOS頭分為兩部分,分別是“MZ頭部”和“DOS存根”。MZ頭部是真正的DOS頭部,由于其開始處的兩個字節(jié)為“MZ”,因此DOS頭也可以叫作MZ頭。該部分用于程序在DOS系統(tǒng)下加載,它的結(jié)構(gòu)被定義為IMAGE_DOS_HEADER。
DOS殘留是一段簡單的程序,主要用于輸出“This program cannot be run in DOS mode.”類似的提示字符串。
為什么PE結(jié)構(gòu)的最開始位置有這樣一段DOS頭部呢?關(guān)鍵是為了該可執(zhí)行程序可以兼容DOS系統(tǒng)。通常情況下,Win32下的PE程序不能在DOS下運行,因此保留了這樣一個簡單的DOS程序用于提示“不能運行于DOS模式下”。
(2)PE頭
PE頭部保存著Windows系統(tǒng)加載可執(zhí)行文件的重要信息。PE頭部由IMAGE_ NT_HEADERS定義。從該結(jié)構(gòu)體的定義名稱可以看出,IMAGE_NT_HEADERS由多個結(jié)構(gòu)體組合而成,包括IMAGE_NT_SIGNATRUE、IMAGE_FILE_HEADER和IMAGE_OPTIO NAL_HEADER三部分。PE頭部在PE文件中的位置不是固定不變的,PE頭部的位置由DOS頭部的某個字段給出。
(3)節(jié)表
程序的組織按照各屬性的不同而被保存在不同的節(jié)中,在PE頭部之后就是一個數(shù)組結(jié)構(gòu)的節(jié)表。描述節(jié)表的結(jié)構(gòu)體是IMAGE_SECTION_HEADER,如果PE文件中有N個節(jié),那么節(jié)表就是由N個IMAGE_SECTION_HEADER組成的數(shù)組。節(jié)表中存儲了各個節(jié)的屬性、文件位置、內(nèi)存位置等相關(guān)的信息。
(4)節(jié)表數(shù)據(jù)
PE文件的真正程序部分就保存在節(jié)數(shù)據(jù)中。在PE結(jié)構(gòu)中,有幾個節(jié)表,就對應(yīng)有幾個節(jié)表的數(shù)據(jù)。根據(jù)節(jié)表的屬性、地址等信息,程序的數(shù)據(jù)就分布在節(jié)表指定的位置中。