俗話說的好,知己知彼百戰百勝;要防範它,先瞭解它。
因此今天的主題就是簡單介紹程式身家基本訊息:PE file structure
PE 是 Portable Executable 的縮寫,也就是 Windows 系統中的可執行(Executable)程式或動態連結函式庫(Dynamic link library)的文件格式,主要使用在 32 位和 64 位的 Windows 操作系统上。
為了能夠瞭解 PE 格式,我們需要以下的對照:
PE 格式示意圖
Hiew 程式,以小算盤為範例
PE 格式圖
泥馬,這麼多密密麻麻的東西,誰想看!
莫急莫慌莫害怕,只要冷靜下來找時光機把範圍劃分出來便可一目了然
以下為簡單對照
DOS MZ Header
開頭必定為"MZ"4D 5A,這是 DOS EXE 的 Signature。而這東西讓 PE file 在 DOS 模式下也可執行,所佔大小為 40h bytes。
DOS Stub
但也不是什麼都能在 DOS 底下執行,若是程式在 DOS 下無法執行便會跳出這邊的錯誤訊息:"This Program cannot be run in DOS mode
"。
PE Header
為了找到 PE 的開頭位置,我們可從 DOS Header 0x3C 的位置找到一個 Double word(又稱 dword,大小為 4 個 bytes),這個 dword 大小表示了整個 DOS MZ Header 的 size,
也就是 D8 00 00 00
,注意!這裡實際位置是 0x000000D8
,想必 IQ180
的各位已經注意到必須以 Byte 為單位顛倒過來看才行,這種反向讀取方式稱之為 Little-endian order
,在 PE 文件中皆採用此種讀取方式。
到了 PE 位置所看到的必定是 50 45,PE Header 裡包含了許許多多的訊息,其中最重要之一就是距離 PE 位置(0xD8)後 0x28 的 dword,這裡是這隻程式執行時的入口點(Entry point)。聽起來好像沒什麼重要的,不過若是入口點被設置在檔案的 Overlay
區域呢?這就很有趣了~正常來說是不會設置在這邊的。
什麼是 Overlay? 這個以後會再說
再往後數 12 Bytes 則是 Image base,下圖最後 4 Bytes,也就是 0x01000000
之前找到的入口點是相對虛擬位置(Relative virtual address, RVA)必須還得加上 ImageBase 才是真正的位置(Virtual address, VA)!
RVA 就是虛擬空間中到參考點的距離,也就是虛擬空間中的偏移量。舉上面的例子來說:小算盤被放入虛擬地址(Virtual address, VA)的 01000000h 處,且入口點的 RVA 在 0x102D6Ch 處,那在虛擬空間之中真正入口起始位置是 0x01000000 + 0x102D6C = 0x01102D6C。
Section Header
如果 PE file 之中有 4 個區段(section),Section Table 就會有 4 個成員,每個成員包含對應區段的屬性、內存大小、偏移量等訊息
Section
PE file 裡的內容,被劃分成各個區段,每個區段的名子以 ” . ” 當作開頭,以下是常見的區段名和作用:
區段名 | 作用 |
---|---|
.data | 已初始化的數據 |
.idata | 導入(import)的文件名表 |
.edata | 導出(export)的文件名表 |
.rdata | 只能讀的初始化數據(無法修改) |
.reloc | 重定位表信息 |
.rsrc | 資源 |
.text | Exe 或 dll 文件的可執行程式碼 |
當 PE file 被執行時,PE 裝載器先檢查 DOS MZ Header 中的 PE Header 偏移量,若找到則跳到 PE Header 所在位置。接著檢查 PE header 是否有效,若有則跳到 Section Table 頭部,讀取訊息並利用文件映射(file mapping)的方法將這些區段映射到記憶體中。
希望有興趣的讀者也能夠點個追蹤,有任何問題或有想多了解的地方也可以回覆在文章底下唷,謝謝你們XDDDD!
參考來源:
維基百科 https://en.wikipedia.org/wiki/Portable_Executable
請問一下
DOS MZ Header ,Stub
裡頭講解提到的數字還有D8 00 00 00
是您舉例的小算盤嗎
還是每個程式都這樣
因為沒有這方面基礎 這邊是完全看不懂
Hi jack1234552000
抱歉有段時間沒登入,隔太久才回覆您的問題,感謝提問唷!
其實都有在看IT鐵人,只是不常登入
0x0000003C 位置的 D8 00 00 00 會指向 PE header 開始的 address,也等於 MZ DOS header 與 Stub 的 size 總和,因為此指向的位置會受到 Stub size 的影響,所以此欄位的值並非固定
的唷。
至於 Stub 的內容是做什麼的呢? 推薦可以看看這篇
Exploring the MS-DOS Stub
根據文章中提到
It is a simple 16-bit assembly program which prints This program cannot be run in DOS mode and exit.
If we run this 64-bit PE inside DOS, the stub will execute, and we get that message.
This program cannot be run in DOS mode.
因為 DOS 的 executable file 同樣具有 MZ header,這樣的 Stub 設計可以使得程式在 DOS 中執行時能夠顯示"此程式無法在 DOS mode 中執行" 並中斷離開,以避免因為 format 問題造成後續錯亂。