else if ( argv[i][1] = = 'h' )
fshowrawsectiondata = true;
else if ( argv[i][1] = = 'l' )
fshowlinenumbers = true;
else if ( argv[i][1] = = 'r' )
fshowrelocations = true;
else if ( argv[i][1] = = 's' )
fshowsymboltable = true;
}else // not a switch character. must be the filename}}
int main(int argc, char *argv)
filename = processcommandline(argc, argv);
if ( filename )
dumpfile( filename );
return 0;}
1 win32 與 pe 基本概念
讓我們複習一下幾個透過pe檔案的設計了解到的基本概念(見圖1)。我用術語"module"來表示乙個可執行檔案或乙個dll載入記憶體的**(code)、資料(data)、資源(resources),除了**和資料是你的程式直接使用的,乙個模組還可以由windows用來確定資料和**載入的位置的支撐資料結構組成。在16位windows中,這些支撐資料結構在模組資料庫(用乙個hmodule來指示的段)中。在win32裡面,這些資料結構在pe檔案頭中,這些我將會簡要地解釋一下。
圖1 pe檔案略圖
word numberofsections
這個檔案中的塊數目。
dword timedatestamp
聯結器產生這個檔案的日期(對obj檔案是編譯器),這個域儲存的數是從2023年12月下午4:00開始到現在經過的秒數。
dword pointertosymboltable
coff符號表的檔案偏移量。這個域只用於有coff除錯資訊的obj檔案和pe檔案,pe檔案支援多種除錯資訊格式,所以偵錯程式應該指向資料目錄的image_directory_entry_debug條目。
dword numberofsymbols
coff符號表的符號數目。見上面。
word sizeofoptionalheader
這個結構後面的可選首部的尺寸。在obj檔案中,這個域是0。在可執行檔案中,這是跟在這個結構後的image_optional_header結構的尺寸。
word characteristics
關於這個檔案資訊的標誌。一些重要的域如下:
0x0001 這個檔案中沒有重定位資訊
0x0002 可執行檔案映像(不是obj或lib檔案)
0x2000 檔案是動態連線庫,而非程式
其它域定義在winnt.h中。
pe首部的第三個組成部分是乙個image_optional_header型的結構。對pe檔案,這一部分當然不是"可選的"。coff格式允許單獨實現來定義乙個超出標準image_file_header附加資訊的結構。image_optional_header裡面的域是pe的實現者感到超出image_file_header基本資訊以外非常關鍵的資訊。
並非 image_optional_header 的所有域都是重要的(見圖4)。比較重要,需要知道的是imagebase 和 subsystem 域。你可以忽略其它域的描述。
表3 image_file_header 的域:
word magic
表現為一些類別的標誌字,通常是0x010b 。
byte majorlinkerversion
byte minorlinkerversion
生成這個檔案的聯結器的版本。這個數字以十進位制顯示比用十六進製製好。乙個典型的聯結器版本是2.23。
dword sizeofcode
所有**塊的進製尺寸。通常大多數檔案只有乙個**塊,所以這個域和 .text 塊匹配。
dword sizeofinitializeddata
已初始化的資料組成的塊的大小(不包括**段)。然而,和它在檔案中的表現形式並不一致。
dword sizeofuninitializeddata
載入器在虛擬記憶體中申請空間,但在磁碟上的檔案中並不占用空間的塊的尺寸。這些塊在程式啟動時不需要指定初值,因此術語名就是"未初始化的資料"。未初始化的資料通常在乙個名叫 .bss 的塊中。
dword addressofentrypoint
載入器開始執行這個程式的位址,即這個pe檔案的入口位址。這是乙個rva,通常在 .text 塊中。
dword baseofcode
**塊起始位址的rva 。在記憶體中,**塊通常在pe首部之後,資料塊之前。在微軟的聯結器產生的exe檔案中,這個值通常是0x1000 。borland 的聯結器 tlink32 也一樣,把映像第乙個**塊的rva和映像基址相加,填入這個域。
譯註:這個域好像一直沒有什麼用
dword imagebase
聯結器建立乙個可執行檔案時,它假定這個檔案被對映到記憶體中的乙個指定的地方,這個位址就存在這個域中,假定乙個載入位址可以使聯結器優化以便節省空間。如果載入器真的把這個檔案對映到了這個地方,在執行之前**不需要任何改變。在為windowsnt 建立的可執行檔案中,預設的imagebase 是0x10000。對dll,預設是0x40000。在window95中,位址0x10000不能用來載入32位exe檔案,因為這個區域在乙個被所有程序共享的線性位址空間中。因此,微軟把win32可執行檔案的預設基址改為0x40000,假定基址為0x10000 的老程式坐在windows95 中需要更長的載入時間,這是因為載入器需要重定位基址。
譯註:這個域即"prefered load address",如果沒有什麼意外,這就是該pe檔案載入記憶體後的位址。
dword sectionalignment
對映到記憶體中時,每個塊都必須保證開始於這個值的整數倍。為了分頁的目的,預設的sectionalignment 是 0x1000。
dword filealignment
在pe檔案中,組成每個塊的生鮮資料必須保證開始於這個值的整數倍。預設值是0x200 位元組,也許是為了保證塊都開始於乙個磁碟扇區(乙個扇區通常是 512 位元組)。這個域和ne檔案中的段/資源對齊(segment/resource alignment)尺寸是等價的。和ne檔案不同的是,pe檔案通常沒有數百個的塊,所以,為了對齊而浪費的通常空間很少。
word majoroperatingsystemversion
word minoroperatingsystemversion
這個程式執行需要的作業系統的最小版本號。這個域有點含糊,因為subsystem 域(後面將會說到)可以提供類似的功能。這個域在到目前為止的win32中預設是1.0。
word majorimageversion
word minorimageversion
乙個可由使用者定義的域。這允許你有不同的exe和dll版本。你可以通過鏈結器的 /version 選項設定這個域的值。例如:"link /version:2.0 myobj.obj"。
word majorsubsystemversion
word minorsubsystemversion
這個程式執行需要的最小子系統版本號。這個域的乙個典型值是3.10 (表示windowsnt 3.1)。
dword reserved1
通常是 0 。
dword sizeofimage
載入器必須關心的這個映像所有部分的大小總和。是從映像的開始到最後乙個塊結尾這段區域的大小。最後乙個塊結尾按sectionalignment進製。
譯註:這個很重要,可以大,但不可以小!
dword sizeofheaders
pe首部和塊表的大小。塊的實際資料緊跟在所有首部元件之後。
dword checksum
這個檔案的crc校驗和。在微軟可執行格式中,這個域被忽略並且置為0 。這個規則的乙個例外情況是信任服務,這類exe檔案必須有乙個合法的校驗和。
word subsystem
可執行檔案的使用者介面使用的子系統型別。winnt.h 定義了下面這些值:
native 1 不需要子系統(比如裝置驅動)
PE檔案格式
pe 的意思是 portable executable 可移植的執行體 它是 win32環境自身所帶的執行檔案格式。它的一些特性繼承自unix的coff common object file format 檔案格式。portable executable 可移植的執行體 意味著此檔案格式是跨win3...
PE檔案格式
pe檔案格式分析及修改 圖 1 2009 01 09 14 08 pe 的意思是 portable executable 可移植的執行體 它是 win32環境自身所帶的執行檔案格式。它的一些特性繼承自unix的coff common object file format 檔案格式。portable ...
PE檔案格式
pe檔案格式應用於所有32位windows系統 windows 9x,windows nt,windows 2000及windows xp vista已經對pe格式進行了公升級,也出現了pe64 而在msdn 98中有pe的大量詳細資料 按目錄 msdn library visual studio ...