导入表 (IT) 与导入地址表 (IAT)

发布于 2024-11-01 09:01:42 字数 1109 浏览 5 评论 0原文

我一直在尝试在加载并运行进程后解析/显示进程的导入地址表(IAT)中的信息。我理解程序中的 API 调用跳转到 IAT 中的相关点,然后跳转到加载的 DLL 中的实际函数。

通过读取 PE 标头并跟随OptionalHeader.DataDirectory[1] 指针到 IMAGE_IMPORT_DESCRIPTOR 数组可以找到 IAT,这是否正确?然后跟随 FirstThunk 指针。而这里的 OriginalFirstThunk 指针将为您提供原始导入表 (IT)?

我也尝试过跟踪PE标头中的OptionalHeader.DataDirectory[12]指针,但这更不成功。

我一直在尝试使用另一个进程中的 ReadProcessMemory 来解析 notepad.exe (32 位)的结构来测试这一点。

这是我正在做的粗略的 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

如果在第三行到最后一行,我将其替换为 import.OriginalFirstThunk 而不是 FirstThunk,它将按预期打印所有内容。我一定在概念上遗漏了一些东西,所以我想知道是否有人能为我澄清这是什么?

非常感谢!

I've been trying to parse/display the information in the Import Address Table (IAT) of a process after it is loaded and running. I understand API calls in programs jump to the relevant point in the IAT, which then jumps to the actual function in the loaded DLL's.

Is it correct that the IAT can be found by reading the PE header and following the OptionalHeader.DataDirectory[1] pointer, to the array of IMAGE_IMPORT_DESCRIPTORs. Then following the FirstThunk pointers. Whereas the OriginalFirstThunk pointers here, will give you the original Import Table (IT)?

I have also tried following the OptionalHeader.DataDirectory[12] pointer in the PE header, but this was even less successful.

I've been testing this by trying to parse this structure for notepad.exe (32bit), using ReadProcessMemory from another process.

Here's the rough C-psuedocode for what I'm doing:

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

If, on the 3rd to last line, i replace it with import.OriginalFirstThunk instead of FirstThunk, it will print everything as expected. I must be missing something conceptually, and so I was wondering if anyone could clarify what this is, for me?

Many thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

长梦不多时 2024-11-08 09:01:42

看来您正朝着正确的方向前进。一些注意事项:

  • DataDirectory 为您提供了偏移量
    到一个数组
    IMAGE_IMPORT_DESCRIPTOR 是
    由全零条目终止。
    会有一个
    每个 DLL 的 IMAGE_IMPORT_DESCRIPTOR
    也就是进口

  • 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

It looks like you're heading the right direction. Some notes:

  • The DataDirectory gives you an offset
    to an array of
    IMAGE_IMPORT_DESCRIPTOR which is
    terminated by an entry of all zeros.
    There will be one
    IMAGE_IMPORT_DESCRIPTOR for each DLL
    that is imported
  • The
    IMAGE_IMPORT_DESCRIPTOR has offsets
    to 2 arrays of IMAGE_THUNK_DATA, one
    that maintains offsets to the names
    of the imported functions
    (OriginalFirstThunk) and another that
    now has the actual addresses of the
    functions (FirstThunk)

Since your executable is running, the IAT should contain the actual address of the function rather than an RVA to a name entry.

You could do something like this instead:

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); 

Take a look at this article for some helpful details:
http://msdn.microsoft.com/en-us/magazine/cc301808.aspx

蓝眸 2024-11-08 09:01:42

Eric 给出了很好的答案,这里有一些补充说明:

我理解程序中的 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

Eric gave a good answer, here are some additional clarifications:

I understand API calls in programs jump to the relevant point in the IAT, which then jumps to the actual function in the loaded DLL's.

The program uses a CALL PTR DS:[IAT-ADDRESS] that reads from an address in the IAT to determine where the program is at runtime.

Whereas the OriginalFirstThunk pointers here, will give you the original Import Table (IT)?

The OriginalFirstThunk pointers point you at the Import Lookup table (ILT). If you open up the binary on disk, the ILT and the IAT are identical; both contain RVA's to function name strings. Once the program has been loaded, the IAT's entries (in memory) are overwritten with the addresses of the imported functions.

In my experience, the best source of information on the import table and all of its attendant data structures is the PE specification itself. If you read patiently through the section on imports, all will be made clear.

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文