2011-04-12 73 views
11

我一直試圖解析/顯示加載並運行後的進程的導入地址表(IAT)中的信息。我理解程序中的API調用會跳轉到IAT中的相關位置,然後跳轉到加載的DLL中的實際函數。導入表(IT)vs導入地址表(IAT)

可以通過讀取PE頭文件和OptionalHeader.DataDirectory [1]指針找到IMAGE_IMPORT_DESCRIPTORs數組來找到IAT是否正確。然後繼FirstThunk指針。而指針在這裏,會給你原來的導入表(IT)?

我也嘗試了PE頭中的OptionalHeader.DataDirectory [12]指針,但是這種方法甚至不太成功。

我一直在試圖用notepad.exe(32位)解析這個結構,使用另一個進程的ReadProcessMemory來測試這個。

下面是我在做什麼粗糙的C-僞代碼:

char buf[128]; 

// get first import descriptor 
readMemory(&import, procImgBase + DataDirectory[1].VirtualAddress, sizeof(IMAGE_IMPORT_DESCRIPTOR)); 

// get dll name 
readMemory(buf, import.Name + procImgBase, 127); 
printf("libname: %s\n", buf); 

// get first function name 
DWORD iltAddress = 0; 
readMemory(&iltAddress, import.FirstThunk + procImgBase, 4); 
readMemory(buf, iltAddress + procImgBase, 127); 
printf("fname: %s\n", libName + 2); // <-- the +2 for the 2byte 'hint' of import lookup table entries 

如果,在3日到最後一行,我import.OriginalFirstThunk代替FirstThunk所代替它,它會打印一切如預期。我在概念上必須錯過一些東西,所以我想知道是否有人能澄清這是什麼,對我來說?

非常感謝!

回答

6

看起來你正朝着正確的方向前進。一些注意事項:

  • 的DataDirectory目錄給你一個偏移 到 IMAGE_IMPORT_DESCRIPTOR這是 由全零的條目終止的數組。 將有入口即
  • 的 IMAGE_IMPORT_DESCRIPTOR每個DLL 一個 IMAGE_IMPORT_DESCRIPTOR具有偏移 至2陣列IMAGE_THUNK_DATA的,一個 維持偏移名稱的導入函數 (OriginalFirstThunk) ,另一個 現擁有

由於您的可執行文件運行 功能(FirstThunk所)的實際地址,在IAT應該包含函數的實際地址,而不是一個RVA到一個名字條目。

你可以做這樣的事情,而不是:

DWORD rva_to_name_of_function = 0; 
DWORD address_of_function = 0; 

// get the RVA of the IMAGE_IMPORT_BY_NAME entry 
readMemory(&rva_to_name, import.OriginalFirstThunk + procImgBase, 4); 

// copy the name of the import 
readMemory(buf, rva_to_name + procImgBase + 2, 127); 

// get the actual address that was filled in by the loader 
readMemory(&address_of_function, import.FirstThunk + procImgBase, 4); 

printf("fname: %s address: %X", buf, address_of_function); 

看看這篇文章的一些有用的細節: http://msdn.microsoft.com/en-us/magazine/cc301808.aspx

+0

謝謝!現在有道理。我想我應該已經意識到,當我回來的價值看起來像有效的地址,而不是RVA的。 – kwytay 2011-04-13 06:52:32

+0

@Eric拉姆,你確定你的第一個要點嗎?在'winnt.h'中,可選的頭結構定義了'IMAGE_DATA_DIRECTORY DataDirectory [IMAGE_NUMBEROF_DIRECTORY_ENTRIES];',而不是'IMAGE_IMPORT_DESCRIPTOR DataDirectory [IMAGE_NUMBEROF_DIRECTORY_ENTRIES];' – 2017-05-22 20:31:55

+0

這就是我現在卡住的地方......我要獲取數據目錄,但是如何將它們加載到正確的結構中以從IAT或ILT或INT獲取DLL名稱目前阻止了我。 – 2017-05-22 20:33:50

4

埃裏克給了一個很好的答案,這裏有一些補充說明:

我知道程序中的API調用會跳轉到IAT中的相關位置,然後跳轉到加載的DLL中的實際函數。

該程序使用CALL PTR DS:[IAT-ADDRESS]從IAT中的地址讀取以確定程序在運行時的位置。

雖然OriginalFirstThunk指針在這裏會給你原來的導入表(IT)嗎?

OriginalFirstThunk指針指向導入查找表(ILT)。如果在磁盤上打開二進制文件,則ILT和IAT是相同的;都包含RVA的函數名稱字符串。程序加載完成後,IAT的條目(內存中)將被導入的函數的地址覆蓋。

根據我的經驗,導入表及其所有伴隨數據結構的最佳信息來源是PE規範本身。如果您耐心閱讀有關進口的部分,所有內容都將明確。

http://msdn.microsoft.com/en-us/windows/hardware/gg463125

+0

感謝您澄清。我已閱讀並重新閱讀MSDN文檔,但我的大腦似乎以不同方式連接到作者 - 我無法理解這部分內容。你說話的方式更清晰:-) – kwytay 2011-04-13 06:53:44

+0

pecoff docx真的讓我很厭惡。它有很多信息,但是它有一些非常有害的缺陷......也有誤傳。具有'.idata'的「幾乎所有可執行文件」條款並不完全包含...... – 2017-05-22 20:27:48