這幾天家裏有點事情,所以更新慢了點,本來想把編程的部分一塊兒更新了,誰知自己沒太看明白.....今天貼一下導入表相關,真是難,看了好幾遍,主要講了3個表,導入表,導入函數地址表和綁定導入表。《PE》中說這部分內容在加殼時有重要應用,看來以後自己還得回過頭再學。
4
4.1
導入表
1導入表
12導入函數地址表
11綁定導入表
13延遲加載導入表
實現代碼重用
4.2
導入函數地址表的機制————編譯時做了地址替換
//知識點1
文件對齊,代碼在第一個段,400h
內存對齊,代碼在第一個節,1000h
這兩個地方開始應該是一樣的(按ImageBase裝載)
//知識點2
invoke api被編譯分解成
壓棧×n
call段內調用,跳轉到地址XXXXXXXX(代碼段)
jmp無條件轉移,跳轉到地址YYYYYYYY(導入函數地址表),這個地址存的值是API函數在內存中的VA
//知識點3
文件對齊,導入表在第二個段,600h
內存對齊,導入表在第二個節,2000h
//4
裝入內存之前,YYYYYYYY存了一個地址A,指向API函數Hint/Name,編譯器根據這個值
獲取了API函數的VA,覆蓋A
導入函數地址表中排列了所有導入函數的地址
4.3
三學導入表:
導入函數地址表的工作機制(get)
導入表
由一系列IMAGE_IMPORT_DECRIPTOR組成
每一個結構對應一個DLL文件
所有結構的最後有一個空結構收尾(全0)
IMAGE_IMPORT_DECRIPTOR
union
Characteristics
OriginalFirstThunk //指向一個雙字數組,最後一個內容爲0
ends
TimeDatestamp
ForwarderChain
Name //RVA,指向DLL文件名
FirstThunk //指向一個雙字數組,最後一個內容爲0
由Name找DLL
由雙橋尋找具體的函數序號和名
OriginalFirstThunk和FirstThunk各指向一個雙字數組,這兩個雙字數組是一樣的
這個雙字數組的最高位爲1代表函數序號尋找,低位是函數的序號
最高位爲0代表函數名尋找,是RVA
兩個雙字數組指向同一個結構數組,其中存儲了函數序號和名
IMGE_IMPORT_BY_NAME
程序被裝入內存後FirstThunk指向的雙字數組被對應改寫成函數的入口地址
這個雙字數組就是導入地址表
所以一共有兩種方法找到導入地址表
4.5
綁定導入機制
系統負責修正IAT的地址,如果函數多就會佔用一些時間
解決辦法:
在裝載直接手動進行
在裝載前由專門程序完成
需要告訴系統這些函數不需要你導入了
即:綁定地址表
但是,不同系統DLL加載的VA是不同的,所以微軟又引入了檢測錯誤的機制,
當綁定地址表不能完成任務時,加載程序就會接管
綁定導入表
由IMAGE_BOUND_IMPORT_DECRIPTOR結構數組組成
TimeDataStamp //糾錯用
OffsetModuleName //以第一個IMAGE_BOUND_IMPORT_DESCRIPOR爲基址,DLL名稱字符串的偏移
NumberOfModuleForwarderResfsf //IMAGE_BOUND_IMPORT_DESCRIPOR後IMAGE_BOUND_FORWARDER_REF數組的個數
IMAGE_BOUND_FORWARDER_REF個數不定,爲兼容使用