我們在分析Windows自帶的一些程序時,常常發現有的程序,如notepad,他的IAT表在文件加載內存前已經完成綁定,存儲了函數的地址。這樣做可以使得程序是無需修改IAT表而直接啟動,這時程序啟動速度變快。但這種方式只適用于dll按照預先設定ImageBase裝載而不重分配的情況
當dll沒有按照預先設定的ImageBase進行裝載,IAT表在文件加載內存前進行綁定就會出現問題了
為了判斷一個程序的IAT是否在加載內存前就已經進行了綁定,PE的導入表中提供了TimeDateStamp時間戳成員變量:當該值為0時,表示該導入表對應的IAT表在加載內存前尚未綁定。當該值為-1時,表示該導入表對應的IAT表加載內存前已經綁定。而真正綁定的時間存儲在綁定導入表中
綁定導入表
綁定導入表:用于存儲已經綁定(即完成綁定導入)的外部函數的信息。一個綁定導入表對應一個dll,通常存在于Windows操作系統自帶的程序中,但在win10以后操作系統中,其自帶的程序已經很少有綁定導入表了,逐漸被棄用
定位
通過數據目錄的第12個結構我們便可以定位到綁定導入表地址:
當有綁定導入表時,其起始地址是在節表后面,因此在新增節的時候,節表后面的數據不建議更改
結構
綁定導入表的結構如下:
struct _IMAGE_BOUND_IMPORT_DESCRIPTOR{ DWORD TimeDateStamp; WORD OffsetModuleName; WORD NumberOfModuleForwarderRefs;
};
DWORD?TimeDateStamp:時間戳,表示IAT表綁定的真正時間
操作系統通過程序使用到的DLL對應的綁定導入表結構中TimeDateStamp和該DLL的可選PE頭中的TimeDateStamp進行對比判斷dll在綁定IAT表以后是否發生修改:
如果兩個時間戳一樣:DLL的創建時間和把DLL中的函數絕對地址綁定到IAT表的時間是一樣,表明在綁定IAT表以后,DLL沒有更新或者修改。
如果兩個時間戳不一樣:DLL在創建以后被更新或者修改了,此時綁定到IAT表中的函數地址可能出現錯誤。這是由于DLL中的函數地址可能變了,但綁定到IAT中的數據可能是以前的函數地址
WORD OffsetModuleName:該值加上所有綁定導入表中的第一個綁定導入表的RVA表示該綁定導入表對應的DLL的名稱的RVA
WORD NumberOfModuleForwarderRefs:一個dll可能依賴于其他的dll,該值表示該dll依賴的其他的dll的數量。有多少dll,綁定導入表后就緊跟著多少_IMAGE_BOUND_FORWARDER_REF結構
_IMAGE_BOUND_FORWARDER_REF結構如下:
struct _IMAGE_BOUND_FORWARDER_REF { DWORD TimeDateStamp; //時間戳 WORD OffsetModuleName; //對應DLL的名字WORD Reserved; //保留(未使用)
};
?TimeDataStamp:和綁定導入表結構中的TimeDateStamp含義和用途是一樣的
OffsetModuleName:和綁定導入表結構中的OffsetModuleName含義和用途是一樣的
Reserved:保留字段(未使用),沒有任何含義
綁定導入表的文件分布如下:
當有sizeof(_IMAGE_BOUND_IMPORT_DESCRIPTOR)個0,表示綁定導入表結束?? ?