關於PE可執行文件的修改(2)

我們將用“Module”這一術語來表示已裝入內存的可執行文件或DLL的代碼、數據及資源。除了程序中直接用到的代碼和數據以外,一個Module也指Windows中用於判斷代碼及數據在內存中位置的支撐數據結構。在16位Windows中,支撐數據結構在Module Database中(Hmodule指向這個段)。而在32位Windows中,這些數據結構放在了PE部首中。
對於PE文件,首先應該知道,磁盤中的執行文件與其被Windows裝載程序裝入後的Module看起來非常相似。Windows裝載程序把磁盤文件編程實際執行代碼的中作相當簡單,裝載程序使用文件內存映象機制將磁盤文件映射到虛擬地址空間。打個比方,PE文件象一個活動地房子,裝載時只需將某個塊放在某個地方,在把它和其它部分擰好即可(比如說,把它和DLL連結在一起)。加載PE文件格式的DLL同樣的簡單。一旦Module被裝入,在Windows中就同其它已經裝入的文件一樣了。
這種方式與16位的Windows 3.1明顯的不同。16位的NE格式文件裝載程序讀取部分磁盤文件,並生成一個完全不同的數據結構,在內存中建立Module。當代碼或數據需要裝入時,裝載程序必須從全局內存中分配出一塊,查找原始數據在文件的什麼地方,找到位置後再讀取原始的數據,最後再進行一些修整。還有,每一個16位的Module要負責記住現在使用的所有selector(段選擇符),該selector表示該段是否已經被拋棄等等。
對於Win32,某Module中的代碼、數據、資源、輸入表、輸出表及其他有用的數據結構等使用的內存都放在一個連續的內存塊中,編程人員只要知道裝載程序文件映像到內存後的地址即可。通過映像後面的各種指針可以輕易找到Module中所有內容。
我們還應該熟悉Win32中的“相對虛擬地址”(Relative Virual Address,RVA)這個名詞。PE文件中的許多項都是以RVA方式指定的,RVA就是某個項相對於文件映象地址的偏移。例如:裝載程序將一個PE文件裝入到虛擬地址空間中,從10000h開始的內存中,如果PE中某個表在映像中的起始地址是10464h,那麼該表的RVA就是464h。將RVA裝換爲可用的指針,只要將RVA的值加上Module的基址即可。基地址是指裝入到內存中的EXE或DLL程序的開始地址,它是Win32中的一個重要概念。爲了方便起見,Windows NT或Windows 95將Module的基地址作爲Module的實例句柄Instance Handle(Hinstance)。在Win32中稱基地址爲Hintance,似乎有些混淆,因爲Instance Handle一詞來源於16爲的Windows 3.1,其中每一個執行實例都有自己的數據段,依此來互相區分,這就是Instance Handle的來歷。在Win32中,以爲不存在共享地址空間,所以已用程序無需加以區別。當然,Win16和Win32中的Hinstance還有些聯繫:在Win32中可以直接調用GetModuleHandle以取得指向DLL的指針,通過指針訪問該DLL Module的內容。
我們還需要知道PE文件中“section”(塊)。在PE文件中section大致相當於NE格式中的段或資源。塊中包含代碼或數據,與段不同的是,塊沒有大小限制,是一個連續內存塊。有些塊中包含程序中聲明及直接使用的代碼和數據,而另外一些數據塊由連接器或庫管理程序產生,包含對*作系統極其重要的信息。有人把section稱爲object,但object具有太多的意義。


PE可執行文件的邏輯結構是段,比如代碼段“.text”、數據段“.data”、資源段“.rscs”等等。這些段大小都是按文件對齊,也就是說段大小 至少會按10h對齊,一般是1000h(4096字節),這由文件頭中指定(鏈接的時候確定)。但是代碼也好數據也好,不可能做到長度剛好是對齊的。也就是說,段的大小是大於段 中代碼或數據實際大小的。他們之間的差值就是該段冗餘的空間,這個空間被稱爲“空隙”。
//--------------------------------------
SFlags     DD        ? ; 塊屬性 
該字段是一組指出塊屬性(如代碼/數據/可讀/可寫等等)的標誌。比較重要的標誌如下:
00000020h該塊包含代碼,通常與可執行標誌(10000000h)一起設置。
00000040h該塊包含已初始化的數據。
00000080h該塊包含未初始化的數據。
02000000h該塊可被丟棄,因爲它一旦被裝入後,進程就不再需要它了。常見的可丟棄的是.reloc(重定位塊)
10000000h 該塊爲共享塊
20000000h該塊可以執行。通常當00000020h標誌被設置時,該標誌也被設置。
40000000h 該塊可讀。可執行文件中的塊總是設置該標誌。
80000000h該塊可寫。如果可執行文件沒有設置該標誌,裝載程序就會將內存映像頁標記爲可讀或可執行。 

發佈了5 篇原創文章 · 獲贊 2 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章