PE文件格式(加密与解密3)(一)
本次的了解主要講解 PE的基本概念、MS-DOS文件頭、PE文件頭、區(qū)塊、輸入表、輸出表等。
這里我將會(huì)結(jié)合一個(gè)簡(jiǎn)單的小程序來(lái)加深我對(duì)PE文件結(jié)構(gòu)的了解。
?
使用學(xué)習(xí)工具:有StudyPE、LordPE、PEID。
?學(xué)習(xí)PE建議看書(shū)。。和自己動(dòng)手。。。
?
PE文件:
在WIN上,32位的可執(zhí)行文件是PE文件,64位的是PE32+文件 ,DLL文件的格式和PE格式差不多,唯一的區(qū)別是PE和DLL的有一個(gè)字段標(biāo)識(shí)這個(gè)文件是EXE還是DLL。
如上就是一個(gè)PE文件的結(jié)構(gòu)圖,PE文件使用的是一個(gè)平面地址空間,所有的數(shù)據(jù)都融合在一起,文件的內(nèi)容又被分割為不同的區(qū)塊(Section),
各個(gè)區(qū)塊按頁(yè)的邊界來(lái)對(duì)齊。每個(gè)塊都有自己的屬性(是否可讀,是否可寫(xiě),是否可執(zhí)行等等)。
?
基地址:
? ? ? 當(dāng)PE文件被裝載器裝載了之后,內(nèi)存中的板塊被稱為模塊。映射文件的起始地址被稱為模塊句柄---內(nèi)存中的模塊代表這進(jìn)程從這個(gè)可執(zhí)行文件中所需要的代碼、數(shù)據(jù)、資源、輸入表、輸出表及其他東西所使用的東西放在一個(gè)連續(xù)的內(nèi)存塊中。在裝載中,PE文件的一個(gè)字段會(huì)告訴系統(tǒng)把文件映射到內(nèi)存需要多少內(nèi)存,不能被映射的數(shù)據(jù)被放置在文件的尾部。
? ? ? 在WIN32中,可以使用HMODULE GetModuleHandle(LPCTSTR lpModuleName)來(lái)獲得一個(gè)模塊的名稱。當(dāng)傳遞一個(gè)可執(zhí)行文件或者DLL作為參數(shù),
如果系統(tǒng)成功找到這個(gè)文件,就會(huì)返回該可執(zhí)行文件或者DLL文件映像加載到的基地址。
? ? ? 在PE文件中,有一個(gè)字符設(shè)置了基地址,VC++建立的exe文件的基地址是0x00400000h,DLL文件的基地址是0x10000000h。
?
相對(duì)虛擬地址:
? ? 為了讓程序的載入更加的靈活-也為了在PE文件中出現(xiàn)有確定的內(nèi)存地址,出現(xiàn)了相對(duì)虛擬地址(Relative Vritual Address, RVA),當(dāng)你的程序加載后,假設(shè)你的text塊的RVA = 0x00001000h,映射到程序中時(shí),VA(虛擬地址) = ImagineBase(基地址)+RVA(相對(duì)虛擬地址),你的代碼區(qū)塊在內(nèi)存中就開(kāi)始與0x00401000h。
?
文件偏移地址:
? ? 因?yàn)槲覀兊奈募谴鎯?chǔ)在磁盤(pán)上的,某個(gè)數(shù)據(jù)相對(duì)于文件頭的偏移量就是這個(gè)數(shù)據(jù)的偏移地址,稱為文件偏移地址(File Offset)或者物理地址(RAW Offset),偏移地址的起始值是0。
?
MS-DOS頭部(IMAGE_DOS_HEADER):
? ?每個(gè)PE文件是以一個(gè)DOS程序開(kāi)始的,還有MZ header之后的DOS stub(DOS塊)。如果這個(gè)可執(zhí)行文件不能被這個(gè)系統(tǒng)支持,會(huì)打印一串提示符
"This program cannot be run is MS-DOS mode",DOS頭部中主要是WORD e_magic和 LONG e_lfanew這個(gè)字段比較重要。這些數(shù)據(jù)結(jié)構(gòu)可以在winnt.h中找到。
#define IMAGE_DOS_SIGNATURE 0x5A4D #define IMAGE_OS2_SIGNATURE 0x454E #define IMAGE_OS2_SIGNATURE_LE 0x454C #define IMAGE_VXD_SIGNATURE 0x454C #define IMAGE_NT_SIGNATURE 0x00004550#include "pshpack2.h" //這里就是IMAGE_DOS_HEADER的結(jié)構(gòu)了。typedef struct _IMAGE_DOS_HEADER {WORD e_magic; // DOS可執(zhí)行文件標(biāo)記“MZ”WORD e_cblp;WORD e_cp;WORD e_crlc;WORD e_cparhdr;WORD e_minalloc;WORD e_maxalloc;WORD e_ss;WORD e_sp;WORD e_csum;WORD e_ip; //DOS代碼入口IPWORD e_cs; //DOS代碼的入口CSWORD e_lfarlc;WORD e_ovno;WORD e_res[4];WORD e_oemid;WORD e_oeminfo;WORD e_res2[10];LONG e_lfanew; // 指向PE文件頭, “PE”,0,0} IMAGE_DOS_HEADER,*PIMAGE_DOS_HEADER;?LONG e_lfanew是指向PE文件頭的一個(gè)地址,它的文件偏移地址是0x3C--也就是60字節(jié)開(kāi)始,然后占據(jù)了4個(gè)字節(jié),指向PE文件頭,具體看下圖
我們可以看到0x000000F8在偏移60字節(jié)的地方,看到PE文件頭在0x000000F8,具體可以自己找一個(gè)文件來(lái)測(cè)試(加深印象)
?DOS文件頭就到這里了,接下來(lái)繼續(xù)介紹PE頭,也就是IMAGE_NT_HEADER,下面的代碼是對(duì)于定義32還是64的PE頭,我們可以看到相應(yīng)的宏語(yǔ)句
和對(duì)應(yīng)的數(shù)據(jù)結(jié)構(gòu)定義。
#ifdef _WIN64 //如果采用64的架構(gòu)typedef IMAGE_OPTIONAL_HEADER64 IMAGE_OPTIONAL_HEADER;typedef PIMAGE_OPTIONAL_HEADER64 PIMAGE_OPTIONAL_HEADER; #define IMAGE_SIZEOF_NT_OPTIONAL_HEADER IMAGE_SIZEOF_NT_OPTIONAL64_HEADER #define IMAGE_NT_OPTIONAL_HDR_MAGIC IMAGE_NT_OPTIONAL_HDR64_MAGIC #else /* _WIN64 */ //如果不是采用64而是32位的架構(gòu)typedef IMAGE_OPTIONAL_HEADER32 IMAGE_OPTIONAL_HEADER;typedef PIMAGE_OPTIONAL_HEADER32 PIMAGE_OPTIONAL_HEADER; #define IMAGE_SIZEOF_NT_OPTIONAL_HEADER IMAGE_SIZEOF_NT_OPTIONAL32_HEADER #define IMAGE_NT_OPTIONAL_HDR_MAGIC IMAGE_NT_OPTIONAL_HDR32_MAGIC #endif /* _WIN64 */ //上面的typedef都是改變結(jié)構(gòu)體的名稱typedef struct _IMAGE_NT_HEADERS64 {//這里是64位的PE頭的結(jié)構(gòu)體的定義DWORD Signature;IMAGE_FILE_HEADER FileHeader;IMAGE_OPTIONAL_HEADER64 OptionalHeader;} IMAGE_NT_HEADERS64,*PIMAGE_NT_HEADERS64;typedef struct _IMAGE_NT_HEADERS {//這里是32位的PE頭的結(jié)構(gòu)體的定義DWORD Signature;IMAGE_FILE_HEADER FileHeader;IMAGE_OPTIONAL_HEADER32 OptionalHeader;} IMAGE_NT_HEADERS32,*PIMAGE_NT_HEADERS32;在PE的文件頭中,第一個(gè)DWORD Signature, 被定義為了0x00004550h,也就是"PE\0\0"這四個(gè)字符。這個(gè)標(biāo)志沒(méi)有什么作用。(DOS中指向的地方)。
主要是IMAGE_FILE_HEADER和IMAGE_OPTIONAL_HEADER這兩個(gè)結(jié)構(gòu)體中的幾個(gè)字段重要。
我么接下來(lái)觀看PE文件頭中的IMAGE FILE_HEADER FileHeader這個(gè)結(jié)構(gòu)體
typedef struct _IMAGE_FILE_HEADER {WORD Machine; //這里定義的是運(yùn)行平臺(tái),i386= 0x014Ch這個(gè)值,還有其他平臺(tái),看書(shū)吧。。WORD NumberOfSections; //這個(gè)是標(biāo)識(shí)區(qū)塊的數(shù)目,緊跟在PE頭的后面,也就是IMAGE_NT_HEADERS的后面DWORD TimeDateStamp;DWORD PointerToSymbolTable;DWORD NumberOfSymbols;WORD SizeOfOptionalHeader; //這里表明了IMAGE_NT_HEADERS中的大小(RAW SIZE),32位一般是0x00E0, 64位PE+一般是0x00F0WORD Characteristics; //普通的EXE是0x010fh, DLL文件是0x210Eh} IMAGE_FILE_HEADER,*PIMAGE_FILE_HEADER;接下來(lái)我們看一下IMAGE_OPTIONAL_HEADER這個(gè)結(jié)構(gòu)體,一樣下面的是這個(gè)結(jié)構(gòu)體在winnt.h中的定義,下面這個(gè)是32位的,還有64位的,但是差不多的,可以看winnt.htypedef struct _IMAGE_OPTIONAL_HEADER
typedef struct _IMAGE_OPTIONAL_HEADER {WORD Magic;BYTE MajorLinkerVersion;BYTE MinorLinkerVersion;DWORD SizeOfCode; //這里定義了包含代碼區(qū)塊的大小DWORD SizeOfInitializedData; //這里定義了已經(jīng)初始化的變量的區(qū)塊的大小DWORD SizeOfUninitializedData; //這里是未初始化的變量的區(qū)塊的大小DWORD AddressOfEntryPoint; //這里是程序入口的RVA(相對(duì)虛擬地址)DWORD BaseOfCode; //這里是程序代碼塊的起始RVADWORD BaseOfData; //這里是數(shù)據(jù)塊起始RVADWORD ImageBase; //這里是程序默認(rèn)裝入的基地址(ImageBase)DWORD SectionAlignment; //內(nèi)存中區(qū)塊的對(duì)齊值,非常重要DWORD FileAlignment; //文件中區(qū)塊的對(duì)齊值,非常重要WORD MajorOperatingSystemVersion;WORD MinorOperatingSystemVersion;WORD MajorImageVersion;WORD MinorImageVersion;WORD MajorSubsystemVersion;WORD MinorSubsystemVersion;DWORD Win32VersionValue;DWORD SizeOfImage;DWORD SizeOfHeaders;DWORD CheckSum;WORD Subsystem; //這里定義了文件的子系統(tǒng),圖形接口子系統(tǒng),字符子系統(tǒng),具體可以看具體的定義WORD DllCharacteristics;DWORD SizeOfStackReserve;DWORD SizeOfStackCommit;DWORD SizeOfHeapReserve;DWORD SizeOfHeapCommit;DWORD LoaderFlags;DWORD NumberOfRvaAndSizes; //這里定義了數(shù)據(jù)目錄表的項(xiàng)數(shù),一直保持為16IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; //這個(gè)是數(shù)據(jù)目錄表,指向輸入、輸出表、資源塊等數(shù)據(jù),很重要} IMAGE_OPTIONAL_HEADER32,*PIMAGE_OPTIONAL_HEADER32;?這個(gè)IMAGE_OPTIONAL_HEADER只需要關(guān)注一些關(guān)鍵字段就行了,記住。。
接下來(lái)我么就看一看這個(gè)數(shù)據(jù)目錄表,數(shù)據(jù)目錄表簡(jiǎn)單點(diǎn)說(shuō)就是一個(gè)長(zhǎng)度為16的IMAGE_DATA_DIRECTORY結(jié)構(gòu)體數(shù)組而已
typedef struct _IMAGE_DATA_DIRECTORY {DWORD VirtualAddress; //數(shù)據(jù)塊的其實(shí)RVA,很重要DWORD Size; //數(shù)據(jù)塊的長(zhǎng)度} IMAGE_DATA_DIRECTORY,*PIMAGE_DATA_DIRECTORY;這是一個(gè)16位的數(shù)組,最有一個(gè)數(shù)組元素作為保留,全部為0,其他的從開(kāi)頭一直到倒數(shù)第二個(gè)數(shù)據(jù)都是已經(jīng)規(guī)定好了的,我們看一下這個(gè)數(shù)據(jù)目錄表成員
#define IMAGE_DIRECTORY_ENTRY_EXPORT 0 //Export Table #define IMAGE_DIRECTORY_ENTRY_IMPORT 1 //Import Table 輸入表這里比較重要 #define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 #define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 #define IMAGE_DIRECTORY_ENTRY_SECURITY 4 #define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 #define IMAGE_DIRECTORY_ENTRY_DEBUG 6 #define IMAGE_DIRECTORY_ENTRY_ARCHITECTURE 7 #define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 #define IMAGE_DIRECTORY_ENTRY_TLS 9 #define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 #define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11 #define IMAGE_DIRECTORY_ENTRY_IAT 12 //IAT (import address table), 這里也很重要 #define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13 #define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14還有也可以使用LordPE的PE editor來(lái)查看這個(gè)目錄,現(xiàn)在的查看目錄表的工具很多。。。。。
PE的第一階段到這里,接下來(lái)會(huì)繼續(xù)學(xué)習(xí),增加熟悉度。。。。。。。。。。-----------好好學(xué)習(xí),天天向上!
?
轉(zhuǎn)載于:https://www.cnblogs.com/binlmmhc/p/6151113.html
總結(jié)
以上是生活随笔為你收集整理的PE文件格式(加密与解密3)(一)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 梦到捡到黄金首饰是什么意思
- 下一篇: shell循环和分支