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


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

通过读取PE头并跟随OptionalHeader.DataDirectory [1]指针到IMAGE_IMPORT_DESCRIPTORs数组,可以找到IAT是否正确。然后继续 FirstThunk所 指针。而且 OriginalFirstThunk 指针在这里,会给你原始的导入表(IT)吗?

我也试过跟随PE头中的OptionalHeader.DataDirectory [12]指针,但这甚至不太成功。

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

这是我正在做的粗略的C-psuedocode:

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替换它,它将按预期打印所有内容。我必须在概念上遗漏一些东西,所以我想知道是否有人能为我澄清这是什么?

非常感谢!


1078
2018-04-12 06:40


起源



答案:


看起来你正走向正确的方向。一些说明:

  • 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


6
2018-04-12 08:26



谢谢!现在有意义。我想我应该意识到我回来的价值,看起来像有效的地址,而不是RVA的。 - kwytay
@Eric Rahm,你确定你的第一个要点吗?在 winnt.h,可选的头部结构定义 IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];不是 IMAGE_IMPORT_DESCRIPTOR DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; - kayleeFrye_onDeck
这是我目前卡住的地方......我要获取数据目录,但如何在正确的结构中加载它们以从IAT或ILT或INT获取DLL名称目前阻止了我。 - kayleeFrye_onDeck


答案:


看起来你正走向正确的方向。一些说明:

  • 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


6
2018-04-12 08:26



谢谢!现在有意义。我想我应该意识到我回来的价值,看起来像有效的地址,而不是RVA的。 - kwytay
@Eric Rahm,你确定你的第一个要点吗?在 winnt.h,可选的头部结构定义 IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];不是 IMAGE_IMPORT_DESCRIPTOR DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; - kayleeFrye_onDeck
这是我目前卡住的地方......我要获取数据目录,但如何在正确的结构中加载它们以从IAT或ILT或INT获取DLL名称目前阻止了我。 - kayleeFrye_onDeck


埃里克给出了一个很好的答案,这里有一些额外的澄清:

我理解程序中的API调用跳转到IAT中的相关点,然后跳转到加载的DLL中的实际函数。

该程序使用CALL PTR DS:[IAT-ADDRESS]从IAT中的地址读取,以确定程序在运行时的位置。

而OriginalFirstThunk指针在这里,会给你原始的导入表(IT)吗?

OriginalFirstThunk指针指向Import Lookup表(ILT)。如果在磁盘上打开二进制文件,ILT和IAT是相同的;两者都包含RVA的函数名称字符串。加载程序后,IAT的条目(在内存中)将被导入函数的地址覆盖。

根据我的经验,导入表及其所有伴随数据结构的最佳信息来源是PE规范本身。如果您通过关于进口的部分耐心阅读,所有内容都将明确。

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


4
2018-04-13 03:40



谢谢你的澄清。我已经阅读并重新阅读了MSDN文档,但我的大脑似乎以不同的方式连接到作者 - 我只是无法理解它的这一部分。你说话的方式更清楚:-) - kwytay
那个pecoff docx真让我烦恼。它有大量的信息,但它有一些非常有害的空白......错误的信息。拥有它们的“几乎所有可执行文件”条款 .idata 并非如此无所不包...... - kayleeFrye_onDeck