久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

PE文件格式詳解(一)

 價(jià)值發(fā)現(xiàn) 2020-10-04

0x00 前言

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

0x01 基本概念

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

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

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

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

1)基地址

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

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

HMODULE GetmoduleHandleLPCTSRT lpModuleName),;

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

2)相對虛擬地址

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

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

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

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

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

3)文件偏移地址

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

0x02 幾個(gè)重要頭部信息介紹

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

1)MS-DOS頭部

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

PE文件的第一個(gè)字節(jié)起始于一個(gè)傳統(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

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

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

 

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

2)PE文件頭文件

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

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

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

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

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

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

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

} IMAGE_NT_HEADER ENDS

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

  1. Signature字段

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

2.IMAGE_FILE_HEADER字段

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

typedef struct _IMAGE_FILE_HEADER {

WORD Machine;//運(yùn)行平臺(tái)

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

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

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

DWORD NumberOfSymbols;//符號(hào)表中符號(hào)的個(gè)數(shù)

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

WORD Characteristics;//文件屬性

} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;

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

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

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

機(jī)器              標(biāo)識(shí)     

Intel I386          14ch

MIPS R3000        162h

Alpha AXP          184h

Power PC           1F0h

MIPS R4000         184h

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

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

3TimeDateStamp

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

4PointerToSymbolTable,。這個(gè)字段用的比較少,略

5NumberOfSymbol,。這個(gè)字段也用得很少,,略

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

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

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多