2023年10月09日 星期日 16:23
**自 cvvd
最終編輯 cvvd
圖1pe
載入器在完成檔案實體資料到記憶體虛擬資料的對映之後,便開始從位於
image_option_header
末端的image_data_directory
陣列的第
2項(如圖
2),取出輸入表的
rva和大小,準備開始輸入函式的初始化。輸入表的
rva實際上是指向乙個以
image_import_descriptor
為元素的陣列,該陣列以乙個全零的結構作為結尾。
圖2
圖3從該結構(如圖3)的
name
字段,可以推測每乙個該結構都只能描述乙個動態庫,事實上也是如此。
其中originalfirstthunk
和fristthunk
都是image_thunk_data32
的rva
,它們如此相像不是巧合,因為在本質上它們所描述的資訊是一致的。如圖
4我們可以清楚的看出
originalfristthunk
和fristthunk
是不同的值。
圖4但實際上它們如描述的
rva卻是相同的如圖5(
originalfirstthunk)和6
圖5
圖6pe載入器一般會從
originalfirstthunk
讀取輸入函式的資訊(如果
originalfirstthunk為0
則從firstthunk
處讀取),並將它(輸入函式)的位址填入
fristthunk
所描述的
rva處,你一定想問乙個動態庫的輸入函式不一定只有乙個,那其他的函式應該怎麼辦?其實答案很簡單,
originalfirstthunk
和fristthunk
所儲存的
rva都是乙個陣列的起始位置,
pe載入器只需要每處理一對輸入資訊就將指標下移
4個位元組即可,談到輸入表,你一定會想到
iat(
import address table
),其實你只要足夠細心就會發現第乙個輸入表描述符中的
fristthunk
和iat
的表頭是同乙個
rva,這足以證明
pe載入器實際上是在完成
iat表的填寫工作。那麼原來儲存在
iat所描述的
rva處的資料又是什麼呢?在本測試程式上
iat的位址是
2000h
也就是檔案偏移
e00h
。即pe
檔案的對映基址
+2000h
開始的資料也就是圖
6上的資料將被系統填充為輸入函式的位址,該過程也就是傳說中的填寫
iat。
我們再來看看圖5圖
6中描述的資料是什麼,
ea210000
,fc21000
也就記憶體
rva:
000021ea
和000021fc
,我們將第乙個
000021ea
轉換中檔案偏移,也就是
21ea-2000+e00=feah
。可以看到此處的資料都是乙個
import_by_name
結構。如圖7和
圖7
圖8這樣輸入函式名和輸出序號就都有了,
pe載入器接下來的工具就跟我們平時動態載入乙個
dll獲取其輸出函式差不多了:
pe通過呼叫
loadlibrary+dll
名載入所需要的動態庫,並根據
originalfirstthunk
描述的rva
找到image_import_by_name
結構指標陣列,然後迴圈遍歷該組,為該
dll匯入的所有函式填寫位址,之後
pe載入器會繼續遍歷下乙個
dll直到遇到乙個全零的
image_import_descriptor
結構結束輸入函式初始化,完成
iat的構建。
載入PE檔案 PE載入器模擬法
1 找到檔案載入到記憶體的基址 通常為0x0040 0000 2 取得記憶體對齊粒度 3 載入pe頭,按照記憶體對齊粒度讀取到指定起始位址的記憶體處 4 載入各個節。得到節數目,定位節表,按照記憶體對齊粒度讀取到記憶體,不足的用0填充。5 基址不對,需要重定位修復。include stdafx.h ...
PE檔案的裝載過程(2)
image nt headers struct signature dword pe檔案標識 fileheader image file header optionalheader image optional header32 image nt headers ends signature為pe檔...
載入PE檔案 記憶體對映檔案
將程式安裝記憶體對齊的方式讀取到記憶體有兩種方法 1 記憶體對映檔案 2 pe載入器模擬法 1 記憶體對映檔案 lpheader所指記憶體是唯讀的,儘管是page readwrite include stdafx.h include include int main int argc,char ar...