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是相對整個地址空間而言
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文件,我們可以將其理解為“頭”+“身體”式結構
以32位系統的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文件身體=節內容。
2. PE頭
IMAGE_NT_HEADERS
這個結構是廣義上的PE頭,在標準的PE文件中,其大小為456個字節,是接下來三個小節提到的數據結構的組合
PE頭的數據結構被定義為IMAGE_NT_HEADERS。包含三部分,其結構如下:
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 STRUCTVirtualAddress DWORD ?;isize DWARD ?; IMAGE_DATA_DIRECTOR ENDS兩個字段依次為VirtualAddress和isize
3 節表項IMAGE_SECTION_HEADER
PE頭的IMAGE_NT_HEADER后緊跟著節表,有許多個節表項組成,節表項的數據結構詳細如下,每個節的結構也是類似于“頭”+“身體”結構,節表項就是這個結構的“頭”
IMAGE_SECTION_HEADERName1 db IMAGE_SIZEOF_SHORT_NAME dup(?);union MiscPhysicalAddress dd ?;VirtualSize dd ?;endsVirtualAddress 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 | 異常表 |
| .didat | 延遲裝入數據 |
總結
- 上一篇: 安装汇编环境,写一个最简单的窗口程序
- 下一篇: CSS伪元素速查