PE格式第四講,數據目錄表之導入表,以及IAT表


           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/
版權所有,歡迎保留原文鏈接進行轉載:)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM