PE格式第四講,數據目錄表之導入表,以及IAT表
作者:IBinary
出處:http://www.cnblogs.com/iBinary/
版權所有,歡迎保留原文鏈接進行轉載:)
一丶IAT(地址表)
首先我們思考一個問題,程序加載的時候會調用API,比如我們以前寫的標准PE
那么他到底是怎么去調用的?
他會Call 下邊的Jmp位置
而Jmp位置則是對一個全局變量取內容.
看下全局變量內容是什么.
我們跟過去看下 75 98 FD AE
可以看出,這個位置保存了一張表格,這張表格保存的是MessageBoxA的函數地址.
那么我們想一下,在程序還沒加載之前.這張表格是否存在,內容是否是這個.
利用虛擬地址,轉文件地址,定位 虛擬地址502008
利用快捷方式轉化
FA = VA - 節區表首地址 + pointerToRawData的大小
節區表在內存中查看
得出節區表的首地址為502000 因為我們的虛擬地址大於502000,所以他屬於是.rdata區.
看下PE格式,文件中.radata的字段.
得出400
公式:
FA = VA - 節區表首地址 + pointerToRawData的大小
= 502008 - 502000 + 400
= 8 + 400
= 408 (文件偏移處)
看下文件偏移處
可以看出,205C是一個RVA偏移,轉為FA跟隨則是
FA = 5c + 400 = 45c位置
45C位置
正好是MsgBosA的字符串
這個IAT表格會跟你的函數個數,會預留很多個
加載到內存的時候,則會寫入到這里.
我們改成FFFFF試試.
發現還是可以正常運行的.
而這個表格的存儲方式則是
/* IAT [iat1......0 iat2........0] */
其中是以0結尾的.
二丶導入表
了解什么是導入表
上面我們說過,程序調用API,那么導入表就是保存這些API的信息
首先我們猜測一下
1.應該有函數名,因為根據函數名才可以在DLL中使用(當然也可以是序號,但是不兼容)
2.猜測應該有DLL名稱,要根據這個DLL才可以加載這個函數名
3.猜測應該會有存放IAT表格的RVA地址, 加載DLL了,根據函數名獲得了函數地址,程序啟動之后就會往IAT表格中填寫地址了.
等等.
看下結構體:
typedef struct _IMAGE_IMPORT_DESCRIPTOR { union { DWORD Characteristics; DWORD OriginalFirstThunk; //指向上面的IAT,是一個結構數組,里面保存了導入函數的信息(例如Msg的實際地址) }; //最后會以全0的結構為結束,其中每一項是一個結構,一項8個字節,是指向
//IMAGE_THUNK_DATA 看下面詳解
DWORD TimeDateStamp; //時間,一般不用 DWORD ForwarderChain; //鏈表前一個結構,一般不用 DWORD Name; //上面說的DLL名稱的RVA偏移通過偏移可以找到DLL名稱 DWORD FirstThunk; // IAT 的RVA偏移.和originalFirstThunk不同 } IMAGE_IMPORT_DESCRIPTOR;
看圖:
按照第一個偏移結構體來算,那么
雙字最高位為0,表示導入符號是一個數值,是一個RVA數值(比如我們的Msg可以利用符號導入)
雙字最高位為1,那么表示導入的符號是一個名稱(比如Msg的名字)
我們查看下user32.dll,里面的導出函數是Msg,我們看下它的序號是什么.
名字則直接是MessageBoxA了
可以使用
IAT結構數組結構表格
typedef struct _IMAGE_THUNK_DATA32 { union { PBYTE ForwarderString; PDWORD Function; DWORD Ordinal; PIMAGE_IMPORT_BY_NAME AddressOfData; } u1; } IMAGE_THUNK_DATA32;
表示IAT是按照什么加載的,序號加載,還是名稱加載.
三丶定位導入表
在數據目錄中,記錄的是導入表的RVA偏移
那么我們通過公式計算一下在文件中的偏移
這里使用標准PE
在數據目錄中找到偏移為 2010 RVA = 2010 位置
現在找模塊地址
模塊地址在 選項頭(或者叫做擴展頭)的成員ImageBase中存儲着 ,現在是00401000
那么現在要找節表
節表中記錄了虛擬地址的RVA 也就是虛擬地址和模塊首地址的RVA,我們則可以快速定位是哪個節表了.
這個顯然不是,1000的RVA,距離1000的位置,那么虛擬地址就是00401000 我們的虛擬地址是 00402010
那么看下下邊的節表
402000位置,顯然這個就是了
那么根據快速轉換公式得到
VA = 402010
FA = 402010 - 402000 + pointertoRawData(不截圖了,是400)
FA = 410
那么410位置就是導入表了.我們查看位置
按照上面的結構體,我們可以知道DLL 的RVA地址,那么現在是
206A 計算得出 FA = 6A + 400 = 46A,那么我們看看46A的位置是不是DLL名稱
,一句IAT的RVA偏移地址,得出IAT表格位置
現在是2008
FA = 8+400 = 408
那么408的位置就是IAT表格了
可以看出,表格中前四個字節還記錄了一個RVA偏移
那么這個偏移代表的就是函數名字的位置
FA = 5C+400 = 45C
那么45C的位置記錄就是函數名稱了
注意黃色方框的兩個字節,這個字節就是上面說的 高低雙字代表的意義
如果高字為1,那么這個API地址則是函數名導入
如果高字為0,那么就是序號導入
作者:IBinary
出處:http://www.cnblogs.com/iBinary/
版權所有,歡迎保留原文鏈接進行轉載:)