1. 程式人生 > >PE檔案格式分析

PE檔案格式分析

最近需要對檔案加殼,看到這篇文章挺好的轉載一下,原文地址http://blog.csdn.net/shitdbg/article/details/49734495

一、PE的基本概念

    PE(Portable Execute)檔案是Windows下可執行檔案的總稱,常見的有DLL,EXE,OCX,SYS等,事實上,一個檔案是否是PE檔案與其副檔名無關,PE檔案可以是任何副檔名。

    認識PE檔案不是作為單一記憶體對映檔案被裝入記憶體是很重要的。Windows載入器(又稱PE載入器)遍歷PE檔案並決定檔案的哪一部分被對映,這種對映方式是將檔案較高的偏移位置對映到較高的記憶體地址中。

PE檔案的結構在磁碟和記憶體中是基本一樣的,但在裝入記憶體中時又不是完全複製。Windows載入器會決定載入哪些部分,哪些部分不需要載入。而且由於磁碟對齊與記憶體對齊的不一致,載入到記憶體的PE檔案與磁碟上的PE檔案各個部分的分佈都會有差異。



二、PE結構分析


圖1:PE檔案的框架結構

PE檔案至少包含兩個段,即資料段和程式碼段。Windows NT 的應用程式有9個預定義的段,分別為 .text 、.bss 、.rdata 、.data 、.pdata 和.debug 段,這些段並不是都是必須的,當然,也可以根據需要定義更多的段(比如一些加殼程式)。
在應用程式中最常出現的段有以下6種:
.執行程式碼段,通常  .text (Microsoft)或 CODE(Borland)命名;
.資料段,通常以 .data 、.rdata 或 .bss(Microsoft)、DATA(Borland)命名;
.資源段,通常以 .rsrc命名;
.匯出表,通常以 .edata命名;
.匯入表,通常以 .idata命名;
.除錯資訊段,通常以 .debug命名;

1、DOS頭結構

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

  1. typedefstruct IMAGE_DOS_HEADER{  
  2.       WORD e_magic;         //DOS頭的標識,為4Dh和5Ah。分別為字母MZ
  3.       WORD e_cblp;  
  4.       WORD e_cp;  
  5.       WORD e_crlc;  
  6.       WORD e_cparhdr;  
  7.       WORD e_minalloc;  
  8.       WORD
     e_maxalloc;  
  9.       WORD e_ss;  
  10.       WORD e_sp;  
  11.       WORD e_csum;  
  12.       WORD e_ip;  
  13.       WORD e_cs;  
  14.       WORD e_lfarlc;  
  15.       WORD e_ovno;  
  16.       WORD e_res[4];  
  17.       WORD e_oemid;  
  18.       WORD e_oeminfo;  
  19.       WORD e_res2[10];  
  20.       DWORD e_lfanew;             //指向IMAGE_NT_HEADERS的所在
  21. }IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;  

DOS頭後跟一個DOS Stub資料,是連結器連結執行檔案的時候加入的部分資料,一般是“This program must be run under Microsoft Windows”。這個可以通過修改連結器的設定來修改成自己定義的資料。

2、PE標頭檔案

    緊跟著DOS stub的時PE標頭檔案(PE Header)。PE Header是PE相關結構NT映像頭(IMAGE_NT_HEADER)的簡稱,其中包含許多PE裝載器用到的重要欄位。執行體在支援PE檔案結構的作業系統中執行時,PE裝載器將從IMAGE_DOS_HEADER結構中的e_lfanew欄位裡找到PE Header的起始偏移量,加上基址得到PE檔案頭的指標。

PNTHeader = ImageBase + dosHeader->e_lfanew

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

  1. typedefstruct IMAGE_NT_HEADERS{  
  2.       DWORD Signature;  
  3.       IMAGE_FILE_HEADER FileHeader;  
  4.       IMAGE_OPTIONAL_HEADER32 OptionalHeader;  
  5. }IMAGE_NT_HEADERS,*PIMAGE_NT_HEADERS;   

Signature欄位:PE頭的標識。雙字結構。為50h, 45h, 00h, 00h. 即“PE\0\0”。

FileHeader欄位:IMAGE_FILE_HEADER(映像標頭檔案)結構包含了檔案的物理層資訊及檔案屬性。共20位元組的資料,其結構如下:

  1. typedefstruct _IMAGE_FILE_HEADER {  
  2.     WORD    Machine;                    //執行平臺
  3.     WORD    NumberOfSections;           //檔案的區塊數目
  4.     DWORD   TimeDateStamp;              //檔案建立日期和時間
  5.     DWORD   PointerToSymbolTable;       //指向符號表(用於除錯)
  6.     DWORD   NumberOfSymbols;            //符號表中符號個數(用於除錯)
  7.     WORD    SizeOfOptionalHeader;       //IMAGE_OPTIONAL_HEADER32結構大小
  8.     WORD    Characteristics;            //檔案屬性
  9. } IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;  
OptionalHeader欄位:IMAGE_OPTIONAL_HEADER(可選映像頭)是一個可選的機構,實際上IMAGE_FILE_HEADER結構不足以定義PE檔案屬性,因此可選映像頭中定義了更多的資料。總共224個位元組,最後128個位元組為資料目錄(Data Directory),其結構如下:
  1. typedefstruct _IMAGE_OPTIONAL_HEADER {  
  2.     WORD    Magic;                          //標誌字
  3.     BYTE    MajorLinkerVersion;             //連結器主版本號
  4.     BYTE    MinorLinkerVersion;             //連結器次版本號
  5.     DWORD   SizeOfCode;                     //所有含有程式碼表的總大小
  6.     DWORD   SizeOfInitializedData;          //所有初始化資料表總大小
  7.     DWORD   SizeOfUninitializedData;        //所有未初始化資料表總大小
  8.     DWORD   AddressOfEntryPoint;            //程式執行入口RVA
  9.     DWORD   BaseOfCode;                     //程式碼表其實RVA
  10.     DWORD   BaseOfData;                     //資料表其實RVA
  11.     DWORD   ImageBase;                      //程式預設裝入基地址
  12.     DWORD   SectionAlignment;               //記憶體中表的對齊值
  13.     DWORD   FileAlignment;                  //檔案中表的對齊值
  14.     WORD    MajorOperatingSystemVersion;    //作業系統主版本號
  15.     WORD    MinorOperatingSystemVersion;    //作業系統次版本號
  16.     WORD    MajorImageVersion;              //使用者自定義主版本號
  17.     WORD    MinorImageVersion;              //使用者自定義次版本號
  18.     WORD    MajorSubsystemVersion;          //所需要子系統主版本號
  19.     WORD    MinorSubsystemVersion;          //所需要子系統次版本號
  20.     DWORD   Win32VersionValue;              //保留,通常設定為0
  21.     DWORD   SizeOfImage;                    //映像裝入記憶體後的總大小
  22.     DWORD   SizeOfHeaders;                  //DOS頭、PE頭、區塊表總大小
  23.     DWORD   CheckSum;                       //映像校驗和
  24.     WORD    Subsystem;                      //檔案子系統
  25.     WORD    DllCharacteristics;             //顯示DLL特性的旗標
  26.     DWORD   SizeOfStackReserve;             //初始化堆疊大小
  27.     DWORD   SizeOfStackCommit;              //初始化實際提交堆疊大小
  28.     DWORD   SizeOfHeapReserve;              //初始化保留堆疊大小
  29.     DWORD   SizeOfHeapCommit;               //初始化實際保留堆疊大小
  30.     DWORD   LoaderFlags;                    //與除錯相關,預設值為0
  31.     DWORD   NumberOfRvaAndSizes;            //資料目錄表的項數
  32.     IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];  
  33. 相關推薦

    PE檔案格式分析

    最近需要對檔案加殼,看到這篇文章挺好的轉載一下,原文地址http://blog.csdn.net/shitdbg/article/details/49734495 一、PE的基本概念     PE(Portable Execute)檔案是Windows下可

    PE檔案格式詳解(六)

    0x00 前言   前面兩篇講到了輸出表的內容以及涉及如何在hexWorkShop中找到輸出表及輸入DLL,感覺有幾個地方還是沒有理解好,比如由資料目錄表DataDirectory[16]找到輸出表表後以為找到輸入DLL就完了,其實這一流程的最終功能是通過輸入DLL找到輸入DLL呼叫的函

    PE檔案格式學習(二):總體結構

    1.概述 PE檔案分為幾個部分,分別是: DOS頭 DOS Stub NT頭(PE頭) 檔案頭 可選頭 區段頭(一個數組,每個元素都是一個結構體,稱之為IMAGE_SECTION_HEADER) .text .rdata .data .rs

    PE檔案格式學習(三):匯出表

    1.回顧 上篇文章中介紹過,可選頭中的資料目錄表是一個大小為0x10的陣列,匯出表就是這個陣列中的第一個元素。 我們再回顧下資料目錄表的結構體: struct _IMAGE_DATA_DIRECTORY {     DWORD VirtualAddress;    

    PE檔案格式學習(一):概述

    1.PE檔案簡介 PE檔案格式是Windows系統中應用最廣泛的檔案格式之一,我們常見的可執行檔案.exe、動態連結庫.dll以及驅動檔案.sys等都是PE檔案格式的。 可以通過十六進位制工具如010editor檢視PE檔案,可以看到PE檔案都有一個共同的特點,就是它們的最開頭都是4D5A,也就是ASCI

    PE檔案格式學習(十三):載入配置表

    1.介紹 載入配置表早期是用於描述當PE檔案頭或PE可選頭無法描述或者因為太大而無法描述的各種功能。 後來以XP及以後的系統主要是為了儲存SEH控制代碼,稱為安全結構化異常處理程式列表,如果SEH異常處理沒有經過註冊,在載入配置表中沒有控制代碼,這個異常處理就不會被執行。 具體的例子就不演示了,看起來只要是

    PE檔案格式學習(十四):繫結匯入表

    1.介紹 繫結匯入表的作用是加快程式的啟動速度,一個PE程式在啟動時會去載入匯入表中的dll檔案,並將匯入表的FirstThunk指向的陣列填入函式的真實地址,這需要耗去時間,繫結匯入表中儲存了匯入函式的真實地址,所以當PE在啟動時系統檢測到有繫結匯入表,就會直接將地址填入FirstThunk裡,這樣就省去

    PE檔案格式詳解(五)

    0x00 前言   前一篇瞭解了區塊虛擬地址和檔案地址轉換的相關知識,這一篇該把我們所學拿出來用用了。這篇我們將瞭解更為重要的一個知識點——輸入表和輸出表的知識。 0x01 輸入表   首先我們有疑問。這個輸入表是啥?為啥有輸入表?其實輸入表就是記錄PE輸入函式相

    PE檔案格式詳解(四)

    PE檔案格式詳解(四) 0x00 前言   上一篇介紹了區塊表的資訊,以及如何在hexwrokshop找到區塊表。接下來,我們繼續深入瞭解區塊,並且學會檔案偏移和虛擬地址轉換的知識。 0x01 區塊對齊值   首先我們要知道啥事區塊對齊?為啥要區塊對齊?這個問題

    PE檔案格式學習(十六):延遲載入表

    1.介紹 延遲載入表本質上跟繫結匯入表的目的是一樣的,都是為了加快程式載入檔案的速度,只不過方法不一樣。 延遲載入是指在呼叫某個DLL時才去載入,目的是為了避免在程式啟動之初就載入了不必要的DLL而浪費了時間。微軟建議在兩種情況下使用延遲載入: 程式並非在啟動時就會呼叫D

    PE檔案格式學習(十二):TLS表

    1.介紹 TLS全稱執行緒區域性儲存器,它用來儲存變數或回撥函式。 TLS裡面的變數和回撥函式都在程式入口點(AddressOfEntry)之前執行,也就是說程式在被除錯時,還沒有在入口點處斷下來之前,TLS中的變數和回撥函式就已經執行完了,所以TLS可以用作反除錯之類的操作。

    PE檔案格式學習(八):基址重定位表

    1.簡介 基址重定位表位於資料目錄表中的第六個,它位於安全表的後面。 這個表的作用是用來索引那些需要重定位的資料的。當系統發現DLL的真實載入基址跟PE檔案中的ImageBase中的值不一樣時,就會啟用基址重定位表修復一些資料的地址。我們知道一個程式中可能包含多個DLL,因此有可

    PE檔案格式學習(七):安全表

    1.介紹 如果一個應用程式有數字簽名,那麼它的安全表就不會為空。它位於異常表的後面。 2.安全表解析 通過資料目錄表裡提供的RVA,我們轉換成offset,找到了安全表的位置,如下: 安全表的結構體如下: typedef struct _WIN_CERTIFIC

    PE檔案格式學習(六):異常表

    1.概述 x86系統採用動態的方式構建SEH結構,相比而言x64系統下采用靜態的方式處理SEH結構,它儲存在PE檔案中,通常在.pdata區段。因此本文的例子採用x64編譯過的程式。 異常表在資源表的後面。 2.異常表解析 資料目錄表的第四個元素指向異常表,RVA指向的是

    PE檔案格式學習(五):資源表

    1.概述 程式內部和外部的介面等元素的二進位制資料統稱為資源,程式把它們放在一個特定的表中,符合資料和程式分離的設計原則。 Windows程式中的資源大致分為六類:選單、對話方塊、點陣圖、游標、圖示、自定義資源 資源表是資料目錄表中的第三個元素,排在匯入表的後面。 2.資

    PE檔案格式學習(四):匯入表

    UPDATE: 在文章的末尾更新了一張圖,在網上找的,有助於理解匯入表的結構 1.概述 匯入表是逆向和病毒分析中比較重要的一個表,在分析病毒時幾乎第一時間都要看一下程式的匯入表的內容,判斷程式大概用了哪些功能。 匯入表是資料目錄表中的第2個元素,排在匯出表的

    ArcGIS 切片快取緊湊檔案格式分析與使用

    一、分析 在ArcGIS 10中出現了一種新的切片快取檔案格式:緊湊型儲存(Compact)。與之前的鬆散型儲存(Exploded)相比,它有遷移方便、建立更快、減少儲存空間等諸多優點,已經成為了建立切片快取的預設格式。對於本身ArcGIS的產品而言,訪問緊湊型儲存與訪問鬆

    Linux ELF檔案格式分析---objcopy命令的使用

    本文轉自:https://blog.csdn.net/xj178926426/article/details/73777611  Linux ELF檔案格式分析—objcopy命令的使用 最近在看《程式設計師的自我修養—連結、裝載與庫》一書,對書中提到的一個小問題,自己做了

    mp4(H264容器)的詳細檔案格式分析

    十六進位制碼流分析:ftyp Box00 00 00 1C:  size ,28,表示此BOX有28個位元組,表示長度的四個位元組也計算在內。以下同66 74 79 70:  type,表示BOX TYPE,此處為ftyp6D 70 34 32:  可能是相容的格式資訊,/////mp4200 00 00 0

    hadoop 1.0.4 fsimage 檔案格式分析

    2013-01-08 周海漢 2013.1.8 http://abloz.com/2013/01/08/hadoop-1-0-4-fsimage-file-format.html fsimage檔案存放在NameNode中,