pe(portable execute)檔案是windows下可執行檔案的總稱,常見的有dll,exe,ocx,sys等,事實上,乙個檔案是否是pe檔案與其副檔名無關,pe檔案可以是任何副檔名。那windows是怎麼區分可執行檔案和非可執行檔案的呢?我們呼叫loadlibrary傳遞了乙個檔名,系統是如何判斷這個檔案是乙個合法的動態庫呢?這就涉及到pe檔案結構了。
pe檔案的結構一般來說如下圖所示:從起始位置開始依次是dos頭,nt頭,節表以及具體的節。
當乙個pe檔案被載入到記憶體中以後,我們稱之為「映象」(image),一般來說,pe檔案在硬碟上和在記憶體裡是不完全一樣的,被載入到記憶體以後其占用的虛擬位址空間要比在硬碟上占用的空間大一些,這是因為各個節在硬碟上是連續的,而在記憶體中是按頁對齊的,所以載入到記憶體以後節之間會出現一些「空洞」。
因為存在這種對齊,所以在pe結構內部,表示某個位置的位址採用了兩種方式,針對在硬碟上儲存檔案中的位址,稱為原始儲存位址或實體地址表示距離檔案頭的偏移;另外一種是針對載入到記憶體以後映象中的位址,稱為相對虛擬位址(rva),表示相對記憶體映象頭的偏移。
然而cpu的某些指令是需要使用絕對位址的,比如取全域性變數的位址,傳遞函式的位址編譯以後的彙編指令中肯定需要用到絕對位址而不是相對映象頭的偏移,因此pe檔案會建議作業系統將其載入到某個記憶體位址(這個叫基位址),編譯器便根據這個位址求出**中一些全域性變數和函式的位址,並將這些位址用到對應的指令中。例如在ida裡看上去是這個樣子:
這種表示方式叫做虛擬位址(va)。
也許有人要問,既然有va這麼簡單的表示方式為什麼還要有前面的rva呢?因為雖然pe檔案為自己指定載入的基位址,但是windows有茫茫多的dll,而且每個軟體也有自己的dll,如果指定的位址已經被別的dll佔了怎麼辦?如果pe檔案無法載入到預期的位址,那麼系統會幫他重新選擇乙個合適的基位址將他載入到此處,這時原有的va就全部失效了,nt頭儲存了pe檔案載入所需的資訊,在不知道pe會載入到哪個基位址之前,va是無效的,所以在pe檔案頭中大部分是使用rva來表示位址的,而在**中是用va表示全域性變數和函式位址的。
那又有人要問了,既然載入基址變了以後va都失效了,那存在於**中的那些va怎麼辦呢?答案是:重定位。系統有自己的辦法修正這些值,到後續重定位表的文章中會詳細描述。既然有重定位,為什麼nt頭不能依靠重定位採用va表示位址呢(十萬個為什麼)?因為不是所有的pe都有重定位,早期的exe就是沒有重定位的。
我們都知道pe檔案可以匯出函式讓其他的pe檔案使用,也可以從其他pe檔案匯入函式,這些是如何做到的?pe檔案通過匯出表指明自己匯出那些函式,通過匯入表指明需要從哪些模組匯入哪些函式。匯入和匯出表的具體結構會在單獨的文章中詳細解釋。
好了,看了這篇文章,相信大家應該對pe檔案有個整體的了解了,以後的篇章,我會將整個pe檔案常見部分進行「拆解「,敬請期待。
PE檔案結構詳解(一)基本概念
pe portable execute 檔案是windows下可執行檔案的總稱,常見的有dll,exe,ocx,sys等,事實上,乙個檔案是否是pe檔案與其副檔名無關,pe檔案可以是任何副檔名。那windows是怎麼區分可執行檔案和非可執行檔案的呢?我們呼叫loadlibrary傳遞了乙個檔名,系統...
PE檔案結構詳解(一)基本概念
pe portable execute 檔案是windows下可執行檔案的總稱,常見的有dll,exe,ocx,sys等,事實上,乙個檔案是否是pe檔案與其副檔名無關,pe檔案可以是任 何副檔名。那windows是怎麼區分可執行檔案和非可執行檔案的呢?我們呼叫loadlibrary傳遞了乙個檔名,系...
TCP IP詳解(一) 基本概念
一 什麼是tcp ip tcp ip是一組協議的代名詞,包括許多別的協議,組成了tcp ip協議簇。tcp ip 採納了arpanet參考模型,將協議分為4層。二 arpanet參考模型 編號名稱 描述 例子.7 應用層實質上是internet相容的任何應用,包括網頁 http dns dhcp 4...