JUMP Table 接近 .text 部分的末尾

JUMP Table close to the end of the .text section

我编写了以下非常简单的程序:

#include <Windows.h>
#include <stdio.h>

int wmain(void) {
    DWORD dwProcId = GetCurrentProcessId();
    HANDLE hProc = OpenProcess(0x0400, FALSE, dwProcId);
    wprintf(L"Process handle is %p\n.", hProc);

    return 0;
}

当我在 x64dbg(或任何其他调试器)上打开它时,我可以看到 IAT 位于 .rdata 部分的开头,它确实包含我使用的函数,GetCurrentProcessIdOpenProcess,以及其他人。

然而,接近正文部分的末尾,我看到了这段代码,它也似乎是跳转的东西table: What is this table?

我可以看到似乎被调用的函数也在 IAT 中被导入,但是我在我阅读的任何 PE 指南中都找不到对此 table 的任何引用。

这是什么 table 以及如何通过 PE 部分或结构以编程方式引用它?

这个table确实叫跳跃table。请记住,当您编译代码时,编译器对内存中外部符号(如 GetCurrentProcessId)的地址一无所知。因此调用的 op-code 将类似于 0xE8 00000000(E8 是调用的 op-code 但您可以看到地址为空)。但是,编译器在 object 文件中创建了一个符号 table,这对 linker(例如 Microsoft linker)非常有用。

当您 link 您的代码时,linker 读取符号 table 并读取所有外部符号(如 API 调用),然后创建一个jump table (就像你拥有的那样)通常在 .text 部分的末尾。跳转table的形式为:

jmp dword ptr ds:[Address of the FirstThunk in IMAGE_IMPORT_DESCRIPTOR]

然后,linker 修改代码中的所有 call 指令以调用跳转中的相应条目 table。

当您将二进制文件加载到内存中时,加载器(例如 Windows 加载器)负责在您的导入 table 中用适当的值填充 FirstThunk 字段。

通过这种方法以及编译器、linker 和加载程序之间的协作,您可以成功地使用外部 APIs 和函数。您可以阅读this post以更好地理解跳转table。

how can I reference it somehow programmatically, via PE sections or structures?

我认为你做不到。 table 是 .text 部分的一部分,headers 中没有关于它的信息。但是,在普通的 PE 文件(未打包或混淆)中,您可以反汇编 .text 部分(甚至不需要将二进制文件加载到内存中),并查找 0xFF25XXXXXXXX 形式的所有指令,其中 XXXXXXXX 是其中之一IMPORT_IMAGE_DESCRIPTOR.

中的 FirstThunks