__imp_ 符号的语义

rwa*_*ace 4 windows dll linker reverse-engineering portable-executable

调用 DLL 函数涉及链接器生成存根,除非函数被声明,__declspec(dllimport)在这种情况下存根可以被绕过,以支持直接对导入表的间接调用,这样效率更高,例如

__declspec(dllimport) void ExitProcess(int);
ExitProcess(0);
Run Code Online (Sandbox Code Playgroud)

产生

call qword ptr [__imp_ExitProcess]
Run Code Online (Sandbox Code Playgroud)

where__imp_ExitProcess解析为可执行文件中导入表中的一个位置。

我试图弄清楚究竟是如何__imp_ExitProcess解决的。可以肯定的是,它作为 kernel32.lib 中的一个符号出现,但该符号具有存储类IMAGE_SYM_CLASS_EXTERNAL、段号零和值零,这相当于只是说“这将在其他地方定义”而没有实际定义它。

__imp_前缀是否具有特殊含义,即链接器是否注意到该前缀并将其作为将符号解析为名称已删除该前缀的 DLL 函数的导入表条目的指令?还是有其他事情发生?

小智 5

链接器向您的程序添加了一个函数,如:

void (*__imp_ExitProcess)(int) = ...;

void ExitProcess(int n)
{
    return (*__imp_ExitProcess)(n);
}
Run Code Online (Sandbox Code Playgroud)

其中 __imp_ExitProcess 指向 KERNEL32.DLL 中的“真实”ExitProcess。

在您的代码中声明:

__declspec(dllimport) void ExitProcess(int);
Run Code Online (Sandbox Code Playgroud)

相当于:

extern void (*__imp_ExitProcess)(int);

#define ExitProcess (*__imp_ExitProcess)
Run Code Online (Sandbox Code Playgroud)

除了 __declspec(dllimport) 由编译器处理,而不是由预处理器处理。