日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

PE文件格式详解(一)

發(fā)布時間:2023/12/10 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 PE文件格式详解(一) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

PE文件格式介紹(一)

0x00 前言

??PE文件是portable File Format(可移植文件)的簡寫,我們比較熟悉的DLLexe文件都是PE文件。了解PE文件格式有助于加深對操作系統(tǒng)的理解,掌握可執(zhí)行文件的數(shù)據(jù)結(jié)構(gòu)機器運行機制,對于逆向破解,加殼等安全方面方面的同學(xué)極其重要。接下來我將通過接下來幾篇詳細(xì)介紹PE文件的格式。

0x01 基本概念

PE文件使用的是一個平面地址空間,所有代碼和數(shù)據(jù)都被合并在一起,組成一個很大的組織結(jié)構(gòu)。文件的內(nèi)容分割為不同的區(qū)塊(Setion,又稱區(qū)段,節(jié)等),區(qū)段中包含代碼數(shù)據(jù),各個區(qū)塊按照頁邊界來對齊,區(qū)塊沒有限制大小,是一個連續(xù)的結(jié)構(gòu)。每塊都有他自己在內(nèi)存中的屬性,比如:這個塊是否可讀可寫,或者只讀等等。

認(rèn)識PE文件不是作為單一內(nèi)存映射文件被裝入內(nèi)存是很重要的,windows加載器(PE加載器)便利PE文件并決定文件的哪個部分被映射,這種映射方式是將文件較高的偏移位置映射到較高的內(nèi)存地址中。當(dāng)磁盤的數(shù)據(jù)結(jié)構(gòu)中尋找一些內(nèi)容,那么幾乎能在被裝入到內(nèi)存映射文件中找到相同的信息。但是數(shù)據(jù)之間的位置可能改變,其某項的偏移地址可能區(qū)別于原始的偏移位置,不管怎么樣,所表現(xiàn)出來的信息都允許從磁盤文件到內(nèi)存偏移的轉(zhuǎn)換,如下圖:

?PS:PE文件頭以下的地址無論在內(nèi)存映射中還是在磁盤映射中都是一樣的,當(dāng)內(nèi)存分頁和磁盤分頁一致時無需進(jìn)行地址轉(zhuǎn)換,只有當(dāng)磁盤分頁和內(nèi)存分頁不一樣時才要進(jìn)行地址轉(zhuǎn)化,這點很重要,拿到PE文件是首先查看分頁是否一致。前兩天一直沒碰到內(nèi)存和磁盤分頁不一樣的,所以這個點一直沒發(fā)現(xiàn),今天特來補上。

下面要介紹幾個重要概念,分別是基地址(ImageBase,相對虛擬地址(Relative Virtual Address),文件偏移地址(File Offset)。

1)基地址

定義:當(dāng)PE文件通過Windows加載器被裝入內(nèi)存后,內(nèi)存中的版本被稱作模塊(Module)。映射文件的起始地址被稱作模塊句柄(hMoudule),可以通過模塊句柄訪問其他的數(shù)據(jù)結(jié)構(gòu)。這個初始內(nèi)存弟子就是基地址。

內(nèi)存中的模塊代表著進(jìn)程從這個可執(zhí)行文件中所需要的代碼,數(shù)據(jù),資源,輸入表,輸出表以及其他有用的數(shù)據(jù)結(jié)構(gòu)所使用的內(nèi)存都放在一個連續(xù)的內(nèi)存塊中,編程人員只要知道裝載程序文件映像到內(nèi)存的基地址即可。在32位系統(tǒng)中可以直接調(diào)用GetModuleHandle以取得指向DLL的指針,通過指針訪問DLL module的內(nèi)容,例如:

HMODULE GetmoduleHandleLPCTSRT lpModuleName);

當(dāng)調(diào)用該函數(shù)時,傳遞一個可執(zhí)行文件或者DLL文件名字字符串。如果系統(tǒng)找到該文件,則返回該可執(zhí)行文件的或者DLL文件映像加載到的基地址。也可以調(diào)用GetModuleHandle,傳遞NULL參數(shù),則返回調(diào)用的可執(zhí)行文件的基地址。

2)相對虛擬地址

在可執(zhí)行文件中,有相當(dāng)多的地方需要指定內(nèi)存的地址。例如:引用全局變量時,需要指定它的地址。PE文件盡管有一個首選的載入地址(基地址),但是他們可以載入到進(jìn)程空間的任意地方,所以不能依賴與PE的載入點。由于這個原因,必須有一個方法來指定一個地址而不是依賴于PE載入點。

為了在PE文件中避免有確定的內(nèi)存地址,出現(xiàn)了相對虛擬地址(Relative Virtual Addres,簡稱RVA)的概念。RVA只是內(nèi)存中的一個簡單的相對于PE文件裝入地址的偏移地址,它是一個“相對”地址,或者稱位“偏移量”地址。例如:假設(shè)一個EXE文件從地址40000h處載入,并且它的代碼區(qū)塊開始于4010000h,代碼區(qū)的RVA將是:

目標(biāo)地址401000h ——轉(zhuǎn)入地址400000hRVA=1000h

RVA地址轉(zhuǎn)換成真實地址,只需簡單的翻轉(zhuǎn)這個過程:將實際裝入地址加上RVA即可得到實際的內(nèi)存地址。順便一提,在PE用語里,實際的內(nèi)存地址被稱作虛擬地址(Vritual Address,簡稱VA),另外也可以把虛擬地址想象為加上首選裝入地址的RVA。不要忘了前面提到的裝入地址等同于模塊句柄,它們之間的關(guān)系如下:

虛擬地址(VA)=基地址(ImageBase+相對虛擬地址(RVA)

3)文件偏移地址

當(dāng)PE文件存儲在磁盤上時,某個數(shù)據(jù)的位置相對于文件頭的偏移量也稱文件偏移地址(FileOffset)或者物理地址(RAW Offset)。文件偏移地址從PE文件的第一個字節(jié)開始計數(shù),起始為零。用十六進(jìn)制工具比如:winhexhexworkshop都可以查看。注意這個物理地址和虛擬地址的區(qū)別,物理地址是文件在磁盤上相對于文件頭的地址,而虛擬地址是PE可執(zhí)行程序加載在內(nèi)存中的地址。

0x02 幾個重要頭部信息介紹

接下來介紹MS-DOS頭部信息,PE文件頭信息及幾個重要字段。

1)MS-DOS頭部

每個PE文件是以一個DOS程序開始的,有了它,一旦程序在DOS下執(zhí)行,DOS就能辨別出這是個有效的執(zhí)行體,然后運行緊隨MZ header(后面會介紹)之后的DOS stub(DOS)。DOS stub實際上是一個有效的EXE,在不支持PE文件格式的操作系統(tǒng)中,它將簡單顯示一個錯誤提示,類似于字符串“This Program cannot be run in MS-DOS”。用戶通常對DOS stub 不感興趣,因為大多數(shù)情況下他們由匯編器自動生成。平常把DOS stubDOS MZ頭部合稱為DOS文件頭。

PE文件的第一個字節(jié)起始于一個傳統(tǒng)的MS-DOS頭部,被稱作IMAGE_DOS_HEADER。其IMAGE_DOS_HEADER的結(jié)構(gòu)如下(左邊的數(shù)字是到文件頭的偏移量):

IMAGE_DOS_HEADER STRUCT?

{?

+0h WORD e_magic? ?// Magic DOS signature MZ(4Dh 5Ah) ? ? DOS可執(zhí)行文件標(biāo)記?

+2h ? WORD? e_cblp ?// Bytes on last page of file? ??

+4h WORD? e_cp? ?// Pages in file?

+6h WORD? e_crlc? ?// Relocations?

+8h WORD? e_cparhdr ? // Size of header in paragraphs?

+0ah WORD? e_minalloc ?// Minimun extra paragraphs needs?

+0ch WORD? e_maxalloc ?// Maximun extra paragraphs needs?

+0eh WORD? e_ss? ? // intial(relative)SS value ? ???DOS代碼的初始化堆棧SS?

+10h WORD? e_sp? ? // intial SP value ? ? ? ? ? ?? ? ?DOS代碼的初始化堆棧指針SP?

+12h WORD? e_csum? ? // Checksum?

+14h WORD? e_ip? ? // ? ?intial IP value? ? ? ? ? ? ? ? ? ? ?DOS代碼的初始化指令入口[指針I(yè)P]?

+16h WORD? e_cs? ? // intial(relative)CS value ? ? ? ? ? ? ? ? ? ?DOS代碼的初始堆棧入口?

+18h WORD? e_lfarlc? ? // File Address of relocation table?

+1ah WORD? e_ovno ? ? ? ?// ? ?Overlay number?

+1ch WORD? e_res[4]? ? // Reserved words?

+24h WORD? e_oemid? ? // ? ?OEM identifier(for e_oeminfo)?

+26h WORD ? ? ?e_oeminfo ? // ? ?OEM information;e_oemid specific ?

+29h WORD? e_res2[10] ? // ? ?Reserved words?

+3ch DWORD ? e_lfanew ? ? // Offset to start of PE?header ? ? ? ? ? ? 指向PE文件頭?

} IMAGE_DOS_HEADER ENDS

?

這個結(jié)構(gòu)中有兩字段很重要,一個是e_magic,一個是e_lfanew。e_magic(一個字大小)字段需要被設(shè)置為5A4Dh這個也是PE程序載入的重要標(biāo)志,這個值非常有意思,他們對應(yīng)的字符分別位ZM,是為了紀(jì)念MS-DOS的最初創(chuàng)建者Mark Zbikowski而專門設(shè)置的,由于在hex編輯器中顯示是由低位到高位故顯示為4D5Ah,剛好是創(chuàng)建者的名字縮寫。另一個字段是e_lfanew。這個字段表示的是真正的PE文件頭部相對偏移地址(RVA),它指出了真正PE頭部文件偏移位置。它占用四個字節(jié),位于文件開始偏移的3ch字節(jié)中。

下面我將用hexworkshop打開一個pe文件向大家展示一下上面這段話的含義。

?

?

第一張圖說明的就是IMAGE_DOS_HEADER的第一個字段e_magic的值與地址。第二張圖就是上面所講的第二個關(guān)鍵字段e_fannew字段的值(注意:不同的PE程序這個值可能不一樣,但原理一樣),這個值就是PE頭文件的起始偏移量。

2)PE文件頭文件

相對于MS-DOS頭文件,PE頭文件PEheader要復(fù)雜的多,下面將詳細(xì)講解其中的幾個字段。

緊跟著DOS頭文件下面的就是peheader。PEheaderPE相關(guān)結(jié)構(gòu)NT映像頭(IMAGE_NT_HEADER)的簡稱,其中包含許多PE裝載器用到的重要字段。執(zhí)行體在支持PE文件結(jié)構(gòu)的操作系統(tǒng)執(zhí)行時,PE裝載器將IMAGE_DOS_HEADER結(jié)構(gòu)中的e_fanew字段找到PEheader的起始偏移量,加上基址得到PE文件頭的指針:

PNTHeader=IMAGBase+dosHeader->e_lfanewr(其實就是去字段e_lfanew的值)。

下面來討論IMAGE_NT_HEADER的結(jié)構(gòu),它是由三個字段組成(左邊的數(shù)字是PE文件頭的偏移量):IMAGE_NT_HEADER STRUCT?

{?

?

+0h Signature ?DWORD ?????????????//PE文件標(biāo)志

+4h FileHeader IMAGE_FILE_HEADER ?//文件頭初始偏移地址

+18 optionalHeader IMAGE_OPTION_HEADER //另一個重要頭部初始偏移地址

?

} IMAGE_NT_HEADER ENDS

下面對這三個字段逐個詳細(xì)分析:

  • Signature字段
  • 這個字段是PE文件的標(biāo)志字段,通常設(shè)置成00004550h,其ASCII碼為PE00,這個字段是PE文件頭的開始,前面的DOS_HEADER結(jié)構(gòu)中的字段e_lfanew字段就是指向這里。

    2.IMAGE_FILE_HEADER字段

    這個字段也是包含幾個字段結(jié)構(gòu),它包含了PE文件的一些基本信息,最重要的是其中一個域指出了IMAGE_OPTIONAL_HEADER的大小。

    typedef struct _IMAGE_FILE_HEADER {

    WORD Machine;//運行平臺

    WORD NumberOfSections;//文件的區(qū)塊數(shù)目

    DWORD TimeDateStamp;//文件創(chuàng)建的用時間戳標(biāo)識的日期

    DWORD PointerToSymbolTable;//指向符號表(用于調(diào)試)

    DWORD NumberOfSymbols;//符號表中符號的個數(shù)

    WORD SizeOfOptionalHeader;//IMAGE_OPTIONAL_HEADER32結(jié)構(gòu)大小

    WORD Characteristics;//文件屬性

    } IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;

    上圖標(biāo)出七個字段的位置及各自的值。

    1)Machine字段,表示目標(biāo)CPU 的類型。

    幾個常見的及其標(biāo)識如下:

    機器 ?????????????標(biāo)識 ????

    Intel I386 ?????????14ch

    MIPS R3000 ???????162h

    Alpha AXP ?????????184h

    Power PC ??????????1F0h

    MIPS R4000 ????????184h

    根據(jù)以上信息我們知道這個PE文件要運行在Intel I386機器上。

    2)NumberOfSection,標(biāo)識區(qū)塊的數(shù)目,關(guān)于區(qū)塊后面會詳細(xì)講。

    3TimeDateStamp

    這個字段沒啥好說的,指的就是PE文件創(chuàng)建的事件,這個時間是指從197011日到創(chuàng)建該文件的所有的秒數(shù)。

    4PointerToSymbolTable。這個字段用的比較少,略

    5NumberOfSymbol。這個字段也用得很少,略

    6SizeOfOptionalHeader:緊跟著IMAGE_FILE_HEADER后面的數(shù)據(jù)大小,這也是一個數(shù)據(jù)結(jié)構(gòu),它叫做IMAGE_OPTIONAL_HEADER,其大小依賴于是64位還是32位文件。32位文件值通常是00EOh,對于64位值通常為00F0h。

    7Characteristics:文件屬性,普通EXE文件這個字段值為010fhDLL文件這個字段一般是0210h。

    下一篇將從字段IMAGE_OPTIONAL_HEADER講起。

    ?

    轉(zhuǎn)載于:https://www.cnblogs.com/2f28/p/9800992.html

    總結(jié)

    以上是生活随笔為你收集整理的PE文件格式详解(一)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。