PE文件格式(加密與解密3)(一)

本次的了解主要講解 PE的基本概念、MS-DOS文件頭、PE文件頭、區塊、輸入表、輸出表等。

這里我將會結合一個簡單的小程序來加深我對PE文件結構的了解。

?

使用學習工具:有StudyPE、LordPE、PEID。

?學習PE建議看書。。和自己動手。。。

?

PE文件:

  在WIN上,32位的可執行文件是PE文件,64位的是PE32+文件 ,DLL文件的格式和PE格式差不多,唯一的區別是PE和DLL的有一個字段標識這個文件是EXE還是DLL。

  

如上就是一個PE文件的結構圖,PE文件使用的是一個平面地址空間,所有的數據都融合在一起,文件的內容又被分割為不同的區塊(Section),

各個區塊按頁的邊界來對齊。每個塊都有自己的屬性(是否可讀,是否可寫,是否可執行等等)。

?

基地址:

? ? ? 當PE文件被裝載器裝載了之后,內存中的板塊被稱為模塊。映射文件的起始地址被稱為模塊句柄---內存中的模塊代表這進程從這個可執行文件中所需要的代碼、數據、資源、輸入表、輸出表及其他東西所使用的東西放在一個連續的內存塊中。在裝載中,PE文件的一個字段會告訴系統把文件映射到內存需要多少內存,不能被映射的數據被放置在文件的尾部。

? ? ? 在WIN32中,可以使用HMODULE GetModuleHandle(LPCTSTR lpModuleName)來獲得一個模塊的名稱。當傳遞一個可執行文件或者DLL作為參數,

如果系統成功找到這個文件,就會返回該可執行文件或者DLL文件映像加載到的基地址。

? ? ? 在PE文件中,有一個字符設置了基地址,VC++建立的exe文件的基地址是0x00400000h,DLL文件的基地址是0x10000000h。

?

相對虛擬地址:

? ? 為了讓程序的載入更加的靈活-也為了在PE文件中出現有確定的內存地址,出現了相對虛擬地址(Relative Vritual Address, RVA),當你的程序加載后,假設你的text塊的RVA = 0x00001000h,映射到程序中時,VA(虛擬地址) = ImagineBase(基地址)+RVA(相對虛擬地址),你的代碼區塊在內存中就開始與0x00401000h。

?

文件偏移地址:

? ? 因為我們的文件是存儲在磁盤上的,某個數據相對于文件頭的偏移量就是這個數據的偏移地址,稱為文件偏移地址(File Offset)或者物理地址(RAW Offset),偏移地址的起始值是0。

?

MS-DOS頭部(IMAGE_DOS_HEADER):

? ?每個PE文件是以一個DOS程序開始的,還有MZ header之后的DOS stub(DOS塊)。如果這個可執行文件不能被這個系統支持,會打印一串提示符

"This program cannot be run is MS-DOS mode",DOS頭部中主要是WORD e_magic和 LONG e_lfanew這個字段比較重要。這些數據結構可以在winnt.h中找到。

#define IMAGE_DOS_SIGNATURE 0x5A4D
#define IMAGE_OS2_SIGNATURE 0x454E
#define IMAGE_OS2_SIGNATURE_LE 0x454C
#define IMAGE_VXD_SIGNATURE 0x454C
#define IMAGE_NT_SIGNATURE 0x00004550#include "pshpack2.h"
//這里就是IMAGE_DOS_HEADER的結構了。typedef struct _IMAGE_DOS_HEADER {WORD e_magic; // DOS可執行文件標記“MZ”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;       //DOS代碼入口IPWORD e_cs;      //DOS代碼的入口CSWORD e_lfarlc;WORD e_ovno;WORD e_res[4];WORD e_oemid;WORD e_oeminfo;WORD e_res2[10];LONG e_lfanew;   // 指向PE文件頭, “PE”,0,0} IMAGE_DOS_HEADER,*PIMAGE_DOS_HEADER;

?LONG e_lfanew是指向PE文件頭的一個地址,它的文件偏移地址是0x3C--也就是60字節開始,然后占據了4個字節,指向PE文件頭,具體看下圖

我們可以看到0x000000F8在偏移60字節的地方,看到PE文件頭在0x000000F8,具體可以自己找一個文件來測試(加深印象)

?DOS文件頭就到這里了,接下來繼續介紹PE頭,也就是IMAGE_NT_HEADER,下面的代碼是對于定義32還是64的PE頭,我們可以看到相應的宏語句

和對應的數據結構定義。

#ifdef _WIN64             //如果采用64的架構typedef IMAGE_OPTIONAL_HEADER64 IMAGE_OPTIONAL_HEADER;typedef PIMAGE_OPTIONAL_HEADER64 PIMAGE_OPTIONAL_HEADER;
#define IMAGE_SIZEOF_NT_OPTIONAL_HEADER IMAGE_SIZEOF_NT_OPTIONAL64_HEADER
#define IMAGE_NT_OPTIONAL_HDR_MAGIC IMAGE_NT_OPTIONAL_HDR64_MAGIC
#else  /* _WIN64 */      //如果不是采用64而是32位的架構typedef IMAGE_OPTIONAL_HEADER32 IMAGE_OPTIONAL_HEADER;typedef PIMAGE_OPTIONAL_HEADER32 PIMAGE_OPTIONAL_HEADER;
#define IMAGE_SIZEOF_NT_OPTIONAL_HEADER IMAGE_SIZEOF_NT_OPTIONAL32_HEADER
#define IMAGE_NT_OPTIONAL_HDR_MAGIC IMAGE_NT_OPTIONAL_HDR32_MAGIC
#endif /* _WIN64 */ //上面的typedef都是改變結構體的名稱typedef struct _IMAGE_NT_HEADERS64 {//這里是64位的PE頭的結構體的定義DWORD Signature;IMAGE_FILE_HEADER FileHeader;IMAGE_OPTIONAL_HEADER64 OptionalHeader;} IMAGE_NT_HEADERS64,*PIMAGE_NT_HEADERS64;typedef struct _IMAGE_NT_HEADERS {//這里是32位的PE頭的結構體的定義DWORD Signature;IMAGE_FILE_HEADER FileHeader;IMAGE_OPTIONAL_HEADER32 OptionalHeader;} IMAGE_NT_HEADERS32,*PIMAGE_NT_HEADERS32;

在PE的文件頭中,第一個DWORD Signature, 被定義為了0x00004550h,也就是"PE\0\0"這四個字符。這個標志沒有什么作用。(DOS中指向的地方)。

主要是IMAGE_FILE_HEADER和IMAGE_OPTIONAL_HEADER這兩個結構體中的幾個字段重要。

我么接下來觀看PE文件頭中的IMAGE FILE_HEADER FileHeader這個結構體

typedef struct _IMAGE_FILE_HEADER {WORD Machine;                     //這里定義的是運行平臺,i386= 0x014Ch這個值,還有其他平臺,看書吧。。WORD NumberOfSections;       //這個是標識區塊的數目,緊跟在PE頭的后面,也就是IMAGE_NT_HEADERS的后面DWORD TimeDateStamp;DWORD PointerToSymbolTable;DWORD NumberOfSymbols;WORD SizeOfOptionalHeader;     //這里表明了IMAGE_NT_HEADERS中的大小(RAW SIZE),32位一般是0x00E0, 64位PE+一般是0x00F0WORD Characteristics;       //普通的EXE是0x010fh, DLL文件是0x210Eh} IMAGE_FILE_HEADER,*PIMAGE_FILE_HEADER;

接下來我們看一下IMAGE_OPTIONAL_HEADER這個結構體,一樣下面的是這個結構體在winnt.h中的定義,下面這個是32位的,還有64位的,但是差不多的,可以看winnt.htypedef struct _IMAGE_OPTIONAL_HEADER

typedef struct _IMAGE_OPTIONAL_HEADER {WORD Magic;BYTE MajorLinkerVersion;BYTE MinorLinkerVersion;DWORD SizeOfCode;           //這里定義了包含代碼區塊的大小DWORD SizeOfInitializedData;    //這里定義了已經初始化的變量的區塊的大小DWORD SizeOfUninitializedData;   //這里是未初始化的變量的區塊的大小DWORD AddressOfEntryPoint;     //這里是程序入口的RVA(相對虛擬地址)DWORD BaseOfCode;          //這里是程序代碼塊的起始RVADWORD BaseOfData;          //這里是數據塊起始RVADWORD ImageBase;           //這里是程序默認裝入的基地址(ImageBase)DWORD SectionAlignment;       //內存中區塊的對齊值,非常重要DWORD FileAlignment;        //文件中區塊的對齊值,非常重要WORD MajorOperatingSystemVersion;WORD MinorOperatingSystemVersion;WORD MajorImageVersion;WORD MinorImageVersion;WORD MajorSubsystemVersion;WORD MinorSubsystemVersion;DWORD Win32VersionValue;DWORD SizeOfImage;DWORD SizeOfHeaders;DWORD CheckSum;WORD Subsystem;          //這里定義了文件的子系統,圖形接口子系統,字符子系統,具體可以看具體的定義WORD DllCharacteristics;DWORD SizeOfStackReserve;DWORD SizeOfStackCommit;DWORD SizeOfHeapReserve;DWORD SizeOfHeapCommit;DWORD LoaderFlags;DWORD NumberOfRvaAndSizes;   //這里定義了數據目錄表的項數,一直保持為16IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; //這個是數據目錄表,指向輸入、輸出表、資源塊等數據,很重要} IMAGE_OPTIONAL_HEADER32,*PIMAGE_OPTIONAL_HEADER32;

?這個IMAGE_OPTIONAL_HEADER只需要關注一些關鍵字段就行了,記住。。

接下來我么就看一看這個數據目錄表,數據目錄表簡單點說就是一個長度為16的IMAGE_DATA_DIRECTORY結構體數組而已

typedef struct _IMAGE_DATA_DIRECTORY {DWORD VirtualAddress;            //數據塊的其實RVA,很重要DWORD Size;             //數據塊的長度} IMAGE_DATA_DIRECTORY,*PIMAGE_DATA_DIRECTORY;

這是一個16位的數組,最有一個數組元素作為保留,全部為0,其他的從開頭一直到倒數第二個數據都是已經規定好了的,我們看一下這個數據目錄表成員

#define IMAGE_DIRECTORY_ENTRY_EXPORT 0              //Export Table
#define IMAGE_DIRECTORY_ENTRY_IMPORT 1        //Import Table              輸入表這里比較重要
#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2
#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3
#define IMAGE_DIRECTORY_ENTRY_SECURITY 4
#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5
#define IMAGE_DIRECTORY_ENTRY_DEBUG 6
#define IMAGE_DIRECTORY_ENTRY_ARCHITECTURE 7
#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8
#define IMAGE_DIRECTORY_ENTRY_TLS 9
#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10
#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11
#define IMAGE_DIRECTORY_ENTRY_IAT 12          //IAT (import address table), 這里也很重要
#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13
#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14

還有也可以使用LordPE的PE editor來查看這個目錄,現在的查看目錄表的工具很多。。。。。

PE的第一階段到這里,接下來會繼續學習,增加熟悉度。。。。。。。。。。-----------好好學習,天天向上!

?

轉載于:https://www.cnblogs.com/binlmmhc/p/6151113.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/397138.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/397138.shtml
英文地址,請注明出處:http://en.pswp.cn/news/397138.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

mysql用戶_MySQL用戶權限管理詳解

用戶權限管理主要有以下作用:1. 可以限制用戶訪問哪些庫、哪些表2. 可以限制用戶對哪些表執行SELECT、CREATE、DELETE、DELETE、ALTER等操作3. 可以限制用戶登錄的IP或域名4. 可以限制用戶自己的權限是否可以授權給別的用戶一、用戶授權mysql> grant all privile…

對ContentProvider中getType方法的一點理解

在上篇博客中我們介紹了自定義ContentProvider,但是遺漏掉了一個方法,那就是getType,自定義ContentProvider一般用不上getType方法,但我們還是一起來探究下這個方法究竟是干什么的?我們先來看看ContentProvider中對這個…

手把手教Electron+vue的使用

.現如今前端框架數不勝數,尤其是angular、vue吸引一大批前端開發者,在這個高新技術快速崛起的時代,自然少不了各種框架的結合使用。接下來是介紹electronvue的結合使用。 2.Electron是什么?? 對于我來說Electron相當于…

shell循環和分支

循環和分支對代碼塊的操作是構造組織shell腳本的關鍵. 循環和分支結構為腳本編程提供了操作代碼塊的工具.10.1. Loops循環就是重復一些命令的代碼塊,如果條件不滿足就退出循環.for loopsfor arg in [list]這是一個基本的循環結構.它與C的for結構有很大不同.forarg in [list]do …

mysql主從_MySQL主從原理及配置詳解

MySQL主從配置及原理,供大家參考,具體內容如下一、環境選擇:1.Centos 6.52.MySQL 5.7二、什么是MySQL主從復制MySQL主從復制是其最重要的功能之一。主從復制是指一臺服務器充當主數據庫服務器,另一臺或多臺服務器充當從數據庫服務…

引導修復 不是活動的_河南省視頻數據修復中心

河南省視頻數據修復中心 lk6afds河南省視頻數據修復中心 文件預覽我找到了我要恢復文件,可是,這個文件能能正確恢復呢。沒有用的文件不可以刪掉嗎。我們先來看看盤文件夾都是什么吧。(以下僅限于~系統)一般來說,剛剛安裝的電腦系統盤主要包含…

企業日志分析 五大問題需重點注意

資訊 | 安全 | 論壇 | 下載 | 讀書 | 程序開發 | 數據庫 | 系統 | 網絡 | 電子書 | 微信學院 | 站長學院 | 源碼 | QQ | 專欄 | 考試 | 系統安全| 網站安全| 企業安全| 網絡安全| 工具軟件| 殺毒防毒| 加密解密|首頁 > 安全 > 企業安全 > 正文企業安全…

sqlite換成mysql_從SQLITE的數據轉到MYSQL

接同事需求,要求從SQLITE的數據轉到MYSQL,這東西以前也沒接觸過。這里搜搜,那里試試,下面把過程列一下。主要過程分三步:1,把SQLITE表結構導出來,作一定的格式調整2,把SQLITE數據導出…

python學習筆記(一):python入門

上周六終于開始接觸心心念念的python了,本人學習語言算是零基礎,java語法比較復雜,所以選擇了一個語法相對還是比較簡單,而且現在使用也是越來越廣泛的python進行了學習。下面就言歸正傳吧 在學習python之前先來了解下現今比較流行…

MySQL查詢優化之explain的深入解析

在分析查詢性能時,考慮EXPLAIN關鍵字同樣很管用。EXPLAIN關鍵字一般放在SELECT查詢語句的前面,用于描述MySQL如何執行查詢操作、以及MySQL成功返回結果集需要執行的行數。explain 可以幫助我們分析 select 語句,讓我們知道查詢效率低下的原因,從而改進我…

怎么驗證proftpd安裝成功_英雄聯盟手游泰服安卓賬號怎么注冊

英雄聯盟手游中泰服安卓賬號怎么注冊?泰服安卓賬號的注冊流程是怎樣的?泰服安卓賬號的注冊與其他服安卓賬號的注冊是否一致?接下來就給介紹下手游中泰服安卓賬號的注冊,希望對各位玩家能有所幫助。英雄聯盟游戲新泰服安卓賬號怎樣…

oracle實現mysql的if_oracle中decode函數 VS mysql中的if函數和case函數

oracle中有decode函數,如下:select sum(decode(sex,男,0,1)) 男生數 from school;統計男生數目,含義為:decode()中sex字段為男時,用1代替,然后計算總和而mysql中沒有該函…

mysql 刪掉重復數據

--不知道為啥這個mysql外邊還要包一層,不然就報錯DELETE FROMcourse WHEREname IN ( select mm.name from (SELECTa.name as nameFROMcourse aGROUP BYa. NAMEHAVINGcount(a.NAME) > 1)mm) AND id NOT IN ( select nn.id from (SELECTmin(id) as idFROMcours…

spring中用到哪些設計模式

1.工廠模式,這個很明顯,在各種BeanFactory以及ApplicationContext創建中都用到了; 2.模版模式,這個也很明顯,在各種BeanFactory以及ApplicationContext實現中也都用到了; 3.代理模式,在Aop實現中…

visio對象放入word顯示不全_辦公人士必學visio技能 手把手教你使用visio繪制項目全景圖!...

Hi,大家好!我是愛踢汪。今天本汪想問問你用什么總結項目,Word、PPT還是視頻?下面我們聊聊畫圖。畫圖固然是為了好看,視覺上的沖擊加深印象。更重要的是,圖像模型帶來的“潛臺詞”,有意想不到的效果&#xf…

java 回調函數很好懂

首先先介紹回調函數的概念。比如客戶端client,想要調用服務器端server的某個函數為你提供服務。比如炒西紅柿炒蛋,cookTomato() 這時候,服務器端說,你先付錢才能為你服務,這時候服務器端要調用客戶端的getMoney().才能…

mongoDB操作詳細

簡介 它和我們使用的關系型數據庫最大的區別就是約束性,可以說文件型數據庫幾乎不存在約束性,理論上沒有主外鍵約束,沒有存儲的數據類型約束等等 關系型數據庫中有一個 "表" 的概念,有 "字段" 的概念,有 "數據條目" 的概念 MongoDB中也同樣有以上…

mysql 存儲過程 on_MySQL存儲過程的權限問題小結

MySQL的存儲過程,沒錯,看起來好生僻的使用場景。問題源于一個開發同學提交了權限申請的工單,需要開通一些權限。本來是一個很正常的操作,但在我來看是比較著急且緊迫的,說來慚愧,忙著方向規劃和開發的事情&…

搜索引擎蜘蛛爬蟲原理

permike 原文 搜索引擎蜘蛛爬蟲原理 關于搜索引擎的大話還是少說些,下面開始正文搜索引擎蜘蛛爬蟲原理: 1 聚焦爬蟲工作原理及關鍵技術概述 網絡爬蟲是一個自動提取網頁的程序,它為搜索引擎從Internet網上下載網頁,是搜索引擎的重…

《Android開發藝術探索》讀書筆記 (10) 第10章 Android的消息機制

第10章 Android的消息機制 10.1 Android消息機制概述 (1)Android的消息機制主要是指Handler的運行機制,其底層需要MessageQueue和Looper的支撐。MessageQueue是以單鏈表的數據結構存儲消息列表但是以隊列的形式對外提供插入和刪除消息操作的消息隊列。MessageQueue只…