PE結構詳解(加殼脫殼必備知識)

        近期太忙一直沒有抽出時間來更新文章,週末抽空寫一篇關於PE結構相關知識,PE結構是windows下的可執行文件的標準結構。可執行文件的裝載、內存分步、執行等都依賴於PE結構。如果要掌握反病毒、免殺、權益保護、反調試、加殼脫殼等相關知識,那瞭解PE結構則是重中之重。

一、PE結構概述

PE文件大致可以分爲兩部分,即數據管理結構及數據部分。數據管理結構包含:DOS頭、PE頭、節表。數據部分包括節表數據(節表數據是包含着代碼、數據等內容)。詳情見下圖:

1.DOS頭

DOS頭分爲兩個部分,分別是MZ頭及DOS存根,MZ頭是真正的DOS頭部,它的結構被定義爲IMAGE_DOS_HEADER。DOS存根是一段簡單程序,主要是用於兼容DOS程序,當不兼容DOS程序時,輸出:"this program cannot be run in DOS mode"。

2.PE頭

PE頭分爲三個部分,分別是PE標識(IMAGE_NT_SIGNATRUE)、文件頭(IMAGE_FILE_HEADER)、可選頭(IMAHE_OPTION_HEADER)。PE頭是固定不變的,位於DOS頭部中e_ifanew字段指出位置。

3.節表

程序中組織按照不同屬性存在不同的節中,如果PE中文件頭的NumberOfSections值中有N個節,那麼節表就是由N個節表(IMAGE_SECTION_HEADER)組成。節表主要是存儲了何種借的屬性、文件位置、內存位置等。位置緊跟PE頭後。

4.節表數據

PE文件真正程序部分的存儲位置,有幾個節表就有幾個節表數據,根據節表的屬性、地址等信息,程序的程序就分佈在節表的指定位置。位置緊跟節表後。

二、通過代碼進行詳解

我本地編寫了簡單的"hello word"的代碼。運行程序彈出"hello word"提示框。

2.1基礎環境介紹

具體代碼如下圖:

2.2 DOS頭介紹

這時我們通過c32asm查看該程序的二進制文件,詳情見下圖。

其中 5A 4D 十六進制爲MZ。(系統使用的是小尾存儲方式,所以需要倒序)。F8 00是DOS頭部的e_ifanew字段存儲的值。所以PE開頭位置位於上圖箭頭標示處,具體DOS頭部代碼定義,請見下圖(位於winnt.h頭文件下)。

其中的DOS存根就位於兩者之間,見下圖:

DOS存根部分經常由於各種需要而保存其它數據,因此可以進行填充,填充內容你可以自己想象啦。

2.3 PE頭介紹

PE在結構概述中,我們講到,PE頭分爲三個部分,分別是PE標識(IMAGE_NT_SIGNATRUE)、文件頭(IMAGE_FILE_HEADER)、可選頭(IMAHE_OPTION_HEADER)。PE標識佔4個字節,文件頭佔20個字節,可選頭的大小由文件頭的SizeOfOptionalHeader的值來確定。

PE標識見下圖:

文件頭標識見下圖:

其中 machine字段的值爲 4c 01,其代表可執行文件的目標CPU類型。

014c:intel;0184:DEC Alpha;0200:inter(64-bit);0284: DEC Alpha(64-bit)

characteristics字段的值爲0201即 0x0102,該值表示文件運行的目標爲32位平臺。

具體不過多介紹啦,有興趣的小夥伴自行查找吧~

可選頭標識見下圖:

由於可選頭大小由SizeOfOptionalHeader存儲的值確定,所以可選頭大小爲 0x00E0(十進制爲224),具體大小見下圖:

可選頭是文件頭的補充,主要用來管理PE文件被操作系統裝載時所需的信息。

2.4節表介紹

PE->可選頭結束後,即爲節表個數由PE中文件頭的NumberOfSections值中有N個節。本程序中NumberOfSections值爲9個,如下圖:

每個節表(IMAGE_SECTION_HEADER) 40個字節,所以總節表共9*40=360個字節。

name字段節名的長度爲8個字節,多餘會被截取,本示例中2E 74 65 78 74 000000爲".text",見下圖 。

黑客入口點通常在第一節區。

.text:V偏移:0x00001001;V大小:00004af0; R大小:0000 c400;R偏移;00000400;

.text段是代碼段

.data段是數據段。

bss段是全局變量數據段。

節表具體結構如下圖:

Name[IMAGE_SIZEOF_SHORT_NAME]; // 節表名稱,如“.text”

PhysicalAddress; // 物理地址

VirtualSize; // 真實長度

VirtualAddress; // 節區的 RVA 地址

SizeOfRawData; // 在文件中對齊後的尺寸

PointerToRawData; // 在文件中的偏移量

PointerToRelocations; // 在OBJ文件中使用,重定位的偏移

PointerToLinenumbers; // 行號表的偏移(供調試使用地)

NumberOfRelocations; // 在OBJ文件中使用,重定位項數目

NumberOfLinenumbers; // 行號表中行號的數目

Characteristics; // 節屬性如可讀,可寫,可執行等

關於PE結構對的三種存儲地址 VA;RVA;FILEOFFSET,以及如何進行定位我們下篇進行詳細介紹。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章