PE教程1:
PE檔案格式一覽
考慮到早期寫的PE教程1是自己所有教程中最糟糕的一篇,此番決心徹底重寫一篇以饗讀者。
PE
的意思就是 Portable
Executable(可移植的執行體)。它是 Win32環境自身所帶的執行體檔案格式。它的一些特性繼承自
Unix的
Coff (common object
file format)檔案格式。"portable
executable"(可移植的執行體)意味著此檔案格式是跨win32平臺的
: 即使Windows執行在非Intel的CPU上,任何win32平臺的PE裝載器都能識別和使用該檔案格式。當然,移植到不同的CPU上PE執行體必然得有一些改變。所有
win32執行體
(除了VxD和16位的Dll)都使用PE檔案格式,包括NT的核心模式驅動程式(kernel
mode drivers)。因而研究PE檔案格式給了我們洞悉Windows結構的良機。
本教程就讓我們瀏覽一下
PE檔案格式的概要。
DOS
MZ header |
DOS
stub |
PE
header |
Section
table |
Section
1 |
Section
2 |
Section
... |
Section
n |
上圖是
PE檔案結構的總體層次分佈。所有
PE檔案(甚至32位的
DLLs) 必須以一個簡單的
DOS MZ header 開始。我們通常對此結構沒有太大興趣。有了它,一旦程式在DOS下執行,DOS就能識別出這是有效的執行體,然後執行緊隨
MZ header 之後的
DOS stub。DOS
stub實際上是個有效的 EXE,在不支援
PE檔案格式的作業系統中,它將簡單顯示一個錯誤提示,類似於字串
"This program requires
Windows" 或者程式設計師可根據自己的意圖實現完整的 DOS程式碼。通常我們也不對
DOS stub 太感興趣:
因為大多數情況下它是由彙編器/編譯器自動生成。通常,它簡單呼叫中斷21h服務9來顯示字串"This
program cannot run in DOS mode"。
緊接著
DOS stub 的是
PE header。
PE header 是PE相關結構
IMAGE_NT_HEADERS
的簡稱,其中包含了許多PE裝載器用到的重要域。當我們更加深入研究PE檔案格式後,將對這些重要域耳目能詳。執行體在支援PE檔案結構的作業系統中執行時,PE裝載器將從
DOS MZ header
中找到 PE header
的起始偏移量。因而跳過了 DOS stub
直接定位到真正的檔案頭 PE
header。
PE檔案的真正內容劃分成塊,稱之為sections(節)。每節是一塊擁有共同屬性的資料,比如程式碼/資料、讀/寫等。我們可以把PE檔案想象成一邏輯磁碟,PE
header 是磁碟的boot扇區,而sections就是各種檔案,每種檔案自然就有不同屬性如只讀、系統、隱藏、文件等等。
值得我們注意的是 ----
節的劃分是基於各組資料的共同屬性:
而不是邏輯概念。重要的不是資料/程式碼是如何使用的,如果PE檔案中的資料/程式碼擁有相同屬性,它們就能被歸入同一節中。不必關心節中類似於"data",
"code"或其他的邏輯概念:
如果資料和程式碼擁有相同屬性,它們就可以被歸入同一個節中。(譯者注:節名稱僅僅是個區別不同節的符號而已,類似"data",
"code"的命名只為了便於識別,惟有節的屬性設定決定了節的特性和功能)如果某塊資料想付為只讀屬性,就可以將該塊資料放入置為只讀的節中,當PE裝載器對映節內容時,它會檢查相關節屬性並置對應記憶體塊為指定屬性。
如果我們將PE檔案格式視為一邏輯磁碟,PE
header是boot扇區而sections是各種檔案,但我們仍缺乏足夠資訊來定位磁碟上的不同檔案,譬如,什麼是PE檔案格式中等價於目錄的東東?別急,那就是
PE header 接下來的陣列結構
section table(節表)。
每個結構包含對應節的屬性、檔案偏移量、虛擬偏移量等。如果PE檔案裡有5個節,那麼此結構陣列內就有5個成員。因此,我們便可以把節表視為邏輯磁碟中的根目錄,每個陣列成員等價於根目錄中目錄項。
以上就是PE檔案格式的物理分佈,下面將總結一下裝載一PE檔案的主要步驟:
- 當PE檔案被執行,PE裝載器檢查
DOS MZ header 裡的
PE header 偏移量。如果找到,則跳轉到
PE header。
- PE裝載器檢查
PE header 的有效性。如果有效,就跳轉到PE
header的尾部。
- 緊跟
PE header 的是節表。PE裝載器讀取其中的節資訊,並採用檔案對映方法將這些節對映到記憶體,同時付上節表裡指定的節屬性。
- PE檔案對映入記憶體後,PE裝載器將處理PE檔案中類似
import table(引入表)邏輯部分。
上述步驟是基於本人觀察後的簡述,顯然還有一些不夠精確的地方,但基本明晰了執行體被處理的過程。
你應該下載
LUEVELSMEYER的《PE檔案格式》。 該文的描述相當詳細,可用作案頭的參考手冊。
翻譯:iamgufeng
[Iczelion's Win32 Assembly Homepage][LuoYunBin's Win32 ASM Page]