天天看點

PE檔案及其結構

文章目錄

  • ​​一.什麼叫PE檔案​​
  • ​​1.位址​​
  • ​​1.1虛拟記憶體位址:​​
  • ​​1.2相對虛拟記憶體位址:​​
  • ​​1.3檔案偏移位址:​​
  • ​​1.4特殊位址:​​
  • ​​2.指針​​
  • ​​3.資料目錄​​
  • ​​4.節​​
  • ​​5.對齊​​
  • ​​6.Unicode字元串​​
  • ​​二.PE檔案的結構​​
  • ​​1. DOS頭​​
  • ​​2. PE頭​​
  • ​​2.1 第一部分:PE頭辨別Signature​​
  • ​​2.2 第二部分:标準PE頭IMAGE_FILE_HEADER​​
  • ​​2.3 第三部分:擴充PE頭,IMAGE_OPTIONAL_HEADER32​​
  • ​​2.4 PE頭中的資料目錄項:IMAGE_DATA_DIRECTORY​​
  • ​​3 節表項IMAGE_SECTION_HEADER​​
  • ​​4 節内容(區塊)​​

一.什麼叫PE檔案

PE (Portable Executeable File Format,可移植的執行體檔案格式),使用該格式的目的是使連接配接生成的EXE檔案能在不同的CPU指令下工作。

Windows中可執行程式有很多種,COM,PIF,SCR,EXE等,這些檔案的格式大部分都繼承于PE。其中EXE是最常見的PE檔案,動态連結庫(大部分以dll為擴充名的檔案)也是PE檔案。

在了解PE檔案格式之前,我們需要學習一下于PE檔案相關的幾個概念

  • 位址
  • 指針
  • 資料目錄
  • 對齊

1.位址

  • 虛拟記憶體位址(VA)
  • 相對虛拟記憶體位址(RVA)
  • 檔案偏移位址(FOA)
  • 特殊位址

1.1虛拟記憶體位址:

PE檔案被作業系統加載進記憶體以後,PE對應的程序配置設定了自己獨立4GB虛拟空間,這個空間中地位的位址稱為虛拟記憶體位址(VA),是以虛拟記憶體位址的範圍是 00000000h~ 0fffffffh。在PE中,程序本身的VA被解釋為:程序的基位址+相對虛拟記憶體位址 VA = IMAGE_BASE_ADDRESS + RVA

1.2相對虛拟記憶體位址:

一個程序被作業系統加載到虛拟記憶體空間後,相關的dll也會被加載,加載到記憶體空間的檔案稱為子產品,每一格子產品在加載時都會有一個基位址,也就是告訴作業系統,從哪裡開始存儲該子產品。

RVA于具體的子產品相關,它有一個範圍,此範圍從子產品的開始到結束,脫離這個範圍 RVA是無效無意義的,稱為越界。

RVA是相對子產品而言,VA是相對整個位址空間而言

PE檔案及其結構

1.3檔案偏移位址:

與檔案有關與記憶體無關,指某個位置距離檔案頭的偏移

1.4特殊位址:

從某個特定的位置開始算起的特殊情況

2.指針

與C語言中的指針定義類似

3.資料目錄

PE中有一種資料結構稱為資料目錄,其中記錄了所有可能的資料類型,這些類型包括:導出表,導入表,資源表,異常表,屬性證書表,重定位表,調試資料,Architecture,Global Ptr,線程局部儲存,加載配置表,綁定導入表,IAT,延遲導入表,CLR運作時頭部

4.節

節就是存放不同資料類型的地方,不同的節具有不同的通路限權,解釋PE檔案種存放代碼或資料的基本單元。如彙編中的,.data .code僞指令。

5.對齊

  • 記憶體對齊
  • 檔案對齊
  • 資源資料對齊

6.Unicode字元串

unicode 是繼阿斯克碼後的另一種新型字元編碼,ASCII碼每個字元用7位表示,Unicode則使用16位表示一個字元,是以又稱為寬字元串

二.PE檔案的結構

PE檔案,我們可以将其了解為“頭”+“身體”式結構

PE檔案及其結構

以32位系統的PE結構為例

PE檔案及其結構

1. DOS頭

所有的PE檔案都是以一個64位元組的DOS頭開始。這個DOS頭隻是為了相容早期的DOS作業系統。

typedef struct IMAGE_DOS_HEADER{  
      WORD e_magic; 
      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;  
      WORD e_cs;  
      WORD e_lfarlc;  
      WORD e_ovno;  
      WORD e_res[4];  
      WORD e_oemid;  
      WORD e_oeminfo;  
      WORD e_res2[10];  
      DWORD e_lfanew; 
}IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;      

DOS頭共64個位元組

  • e_magic:判斷一個檔案是不是PE檔案
  • e_lfanew:相對與檔案首的偏移量,常用于定位PE頭位置

PE頭的絕對位置定位:

PE_start = DOS MZ 基位址 + IMAGE_DOS_HEADER.e_lfanew。

PE檔案頭部=DOS頭+PE頭+節表

PE檔案身體=節内容。

PE檔案及其結構

2. PE頭

IMAGE_NT_HEADERS

這個結構是廣義上的PE頭,在标準的PE檔案中,其大小為456個位元組,是接下來三個小節提到的資料結構的組合

PE頭的資料結構被定義為IMAGE_NT_HEADERS。包含三部分,其結構如下:

typedef struct IMAGE_NT_HEADERS{  
      DWORD Signature;  
      IMAGE_FILE_HEADER FileHeader;  
      IMAGE_OPTIONAL_HEADER32 OptionalHeader;  
}IMAGE_NT_HEADERS,*PIMAGE_NT_HEADERS;      
PE檔案及其結構

2.1 第一部分:PE頭辨別Signature

緊跟在DOS Stub之後,與大部分檔案格式的頭部結果一樣,PE頭部中有一個四位元組的辨別,該辨別位于指針IMAGE_DOS_HEADER.e_lfanew指向的内同。其内容固定,對應于ASCII碼的字元串“PE\0\0”。

2.2 第二部分:标準PE頭IMAGE_FILE_HEADER

标準PE頭,IMAGE_FILE_HEADER緊跟在PE頭辨別之後,記錄了PE檔案的全局屬性,常用于判斷此PE檔案時exe類型還是dll類型

2.3 第三部分:擴充PE頭,IMAGE_OPTIONAL_HEADER32

檔案執行是的入口位址,檔案被作業系統裝入到記憶體後的預設基位址,以及節在磁盤和記憶體中的對齊機關等資訊都可以在此結構中找到,其内容比标準PE頭還要多,對于該結果中的某些數值的改動可能導緻PE檔案加載或運作失敗

2.4 PE頭中的資料目錄項:IMAGE_DATA_DIRECTORY

該字段定義了PE檔案中所有不同類型資料的目錄資訊

IMAGE_DATA_DIRECTORY STRUCT
  VirtualAddress DWORD ?;
  isize DWARD ?;
IMAGE_DATA_DIRECTOR ENDS      

兩個字段依次為VirtualAddress和isize

PE檔案及其結構

3 節表項IMAGE_SECTION_HEADER

PE頭的IMAGE_NT_HEADER後緊跟着節表,有許多個節表項組成,節表項的資料結構詳細如下,每個節的結構也是類似于“頭”+“身體”結構,節表項就是這個結構的“頭”

IMAGE_SECTION_HEADER
  Name1 db IMAGE_SIZEOF_SHORT_NAME dup(?);
  union Misc
    PhysicalAddress     dd    ?;
    VirtualSize       dd    ?;
  ends
  VirtualAddress        dd    ?;      //節内容的RVA 
  SizeofRawData       dd    ?;      //節内容檔案中對齊後的大小
  PointerToRawData      dd    ?;      //在檔案中的偏移
  PointerToRelocations    dd    ?;
  PointerToLinenumbers    dd    ?;
  NumberOfRelocations     dw    ?;
  NumberOfLinenumbers     dw    ?;
  Characteristics       dd    ?;      //區塊屬性,如可讀,可寫,可執行等
IMAGE_SECTION_HEADER ENDS      

注:IMAGE_OPTION_HEADER32.AddressOfEntryPoint

雙字,該字段的值是一個RVA,他記錄了啟動代碼距離該PE加載後的起始位置到底有多少個位元組,我們可以修改這裡的值,使之指向自己代碼的位置,然後…進行一些操作,然後繼續跳轉執行原來的代碼。

許多病毒程式,加密程式,更新檔程式都是用的這個法子

4 節内容(區塊)

名稱 描述
.text 預設的代碼區域,内容全是指令代碼
.data 預設的讀/寫資料塊,全局變量,靜态變量一般存在這個區域
.rdata 預設隻讀資料塊
.idata 包含其他外來的DLL的函數及資料資訊,即輸入表
.edata 輸出表,當建立一個輸出API或資料的可執行檔案時,連接配接器會建立一個.EXP檔案,這個.EXP檔案會包含一個.edata區塊,其會被加載到可執行檔案中,經常被合并到.text或.rdate區域中
.rsrc 資源,包括子產品的全部資源,圖示,菜單,位圖
.bss 未初始化的資料
.crt 用于C++運作時(CRT)所添加的資料
.tls 線程局部儲存器
.reloc 可執行檔案的機制重定位
.sdate 相對于全局指針的可被定位的,短的讀寫資料
.pdata 異常表