pe檔案中的輸入表含有三個重要結構iid,int,iat。pe檔案為需要載入的dll檔案建立乙個iid結構,乙個dll與乙個iid對應。int是輸入名稱表,iat輸入位址表,在沒有繫結輸入的情況下磁碟中的檔案int與iat相同。如果有繫結輸入的話因為繫結輸入的函式其磁碟檔案中的iat項就已經是對應函式的位址了,所以int與iat就不同了。
我們一般在呼叫函式的時候都是直接用函式的名稱,例如messagebox()這種其在底層彙編指令上並不是直接呼叫messagebox()函式的位址而是呼叫iat中對應函式的位址(也就是函式的位址實際存放在iat中)。一般在pe檔案載入進入記憶體時,windows載入器會根據int(如果int為空就根據iat)的函式資訊在對應的dll中查詢實際函式的位址,然後重寫到iat中。也就是在載入到記憶體前iat與int儲存的都是輸入函式的資訊,並不包含函式的實際位址。只有當windows載入器將pe檔案載入到記憶體後iat中才會存放函式的實際位址,而我們實際呼叫函式的指令會指向這對應的iat中函式的位置,完成函式的呼叫。這種方式稱為函式隱式呼叫。
如果我們呼叫函式的時候不直接使用函式名稱,而是使用loadlibrary()和getprocaddress()函式在執行時動態獲取函式的位址,這種函式呼叫根本不依賴於iat,稱為顯示鏈結。
注意當我們自己的**直接使用loadlibrary()和getprocaddress()函式時其彙編**就是呼叫對應的函式位址。
對於函式隱式呼叫而言,因為需要在pe檔案載入到記憶體時通過int中的函式資訊從dll中獲取函式的位址然後寫到iat中,這效率很低。如果我們能讓pe檔案在沒載入到記憶體時就確定對應iat中函式的位址的話就可以大大提高效率,這種就稱為繫結輸入函式。為了防止繫結輸入的函式對應的dll發生改變造成函式呼叫出錯,pe檔案有對應的繫結輸入表可以通過資料目錄表訪問,在pe檔案載入到記憶體時windows載入器會依據繫結輸入表中的資訊與載入的dll的資訊進行對比,如果發現不一致則會重新改寫iat。
延遲載入dll需要在鏈結器進行設定,這樣會在資料目錄表中的延遲載入表中形成對應的資料結構包含對應的iat和int,此iat和int與正常的iat和int一樣只不過此iat不是windows載入器寫入的。這樣在第一次呼叫延遲載入的其中乙個函式時執行庫就會呼叫loadlibrary()和getprocaddress()寫入此iat,然後以後呼叫此函式都會來到此iat處。
因為顯式呼叫不依賴與iat所以iat_hook對其進行無效,而對於延遲載入的dll需要在其對應的延遲載入dll的iat處hook。對於eat_hook來說其只對後續載入的模組的hook有效果,因為如果是隱式呼叫,其在pe載入到記憶體時會根據eat修改iat,但是自此以後eat對其就沒用了。而後續載入的模組,例如顯式呼叫和延遲載入其會利用eat獲取函式的位址,所以eat_hook對二者有用.
注意動態鏈結是指將對應dll中的資訊儲存到pe檔案的iid中,然後呼叫的函式資訊存在iat和int中。當pe檔案載入到記憶體中時將iid對應的dll加入到記憶體中進一步完成函式的呼叫。而靜態鏈結是將函式對應的dll中的**全部整合到pe檔案中,這樣函式的呼叫就不依賴於dll也不會形成對應的iid。執行時鏈結是與函式的顯示呼叫一起的,通過loadlibrary()鏈結dll,在通過getprocaddress()獲得api的位址顯示呼叫函式。
關於PE檔案 輸入表
什麼是輸入表?輸入表就相當於exe檔案與 dll檔案溝通的橋梁,形象的可以比喻成兩個城市之間交流的高速公路。在pe檔案對映到記憶體後,windows將相應的dll檔案裝入,exe檔案通過 輸入表 找到相應的dll中的匯入函式,從而完成程式的正常執行。輸入表的組成與工作原理?首先大概了解整體的結構 三...
PE檔案詳解五 PE詳解之輸入表(匯入表)詳解1
首先,我們知道pe 檔案中的資料被載入記憶體後根據不同頁面屬性被劃分成很多區塊 節 並有區塊表 節表 的資料來描述這些區塊。這裡我們需要注意的問題是 乙個區塊中的數 據僅僅只是由於屬性相同而放在一起,並不一定是同一種用途的內容。例如輸入表 輸出表等就有可能和唯讀常量一起被放在同乙個區塊中,因為他們的...
PE檔案詳解五 PE詳解之輸入表(匯入表)詳解1
首先,我們知道pe 檔案中的資料被載入記憶體後根據不同頁面屬性被劃分成很多區塊 節 並有區塊表 節表 的資料來描述這些區塊。這裡我們需要注意的問題是 乙個區塊中的數 據僅僅只是由於屬性相同而放在一起,並不一定是同一種用途的內容。例如輸入表 輸出表等就有可能和唯讀常量一起被放在同乙個區塊中,因為他們的...