【发布时间】:2020-05-04 18:16:09
【问题描述】:
简短的问题。
当我这样做时:
#include <windows.h>
CreateProcess(..)
头文件如何知道将我连接到正确的dll?
在这些头文件中是否有一个字典将每个win32api函数映射到相关的dll?
【问题讨论】:
标签: c winapi reverse-engineering
简短的问题。
当我这样做时:
#include <windows.h>
CreateProcess(..)
头文件如何知道将我连接到正确的dll?
在这些头文件中是否有一个字典将每个win32api函数映射到相关的dll?
【问题讨论】:
标签: c winapi reverse-engineering
标头仅包含 API 函数的声明,而不是它们的定义。通过链接适当的库可以找到定义。
例如,将以下内容复制到.c 文件中:
#include <Windows.h>
int main()
{
MessageBoxW(NULL, L"Hello World", L"", MB_OK);
return 0;
}
尝试在 Visual Studio 命令提示符上使用命令 cl example.c 编译它。您将看到错误消息:
example.obj : error LNK2019: unresolved external symbol __imp__MessageBoxW@16 referenced in function _main
注意编译本身实际上是成功的;抱怨缺少函数定义的是链接器。
如果您改为使用cl example.c /link user32.lib 编译它,链接器将找到MessageBox 的定义。你也可以link example.obj user32.lib。
所以,回答您的问题:头文件不需要知道函数在哪些 DLL 中,因为项目需要提供适当的库引用。幸运的是,Windows API 函数的 MSDN 文档会告诉您该函数在哪个 DLL 中以及要链接哪个库。
【讨论】:
GetProcAddress() 动态导入 DLL 函数,那就完全不同了(不需要 lib 文件)。
简答:头文件不知道实现这些功能的 DLL。
通常,您会将这些 DLL 指定给链接器。
或者,您可以使用#pragma comment(lib, “XXX”) 为您执行此操作。
【讨论】:
.dll (/DELAYLOAD) 你需要GetModuleHandle GetProcAddress
头文件不知道也不关心函数的位置。头文件只是简单地声明函数。当您在代码中调用函数时,编译器只是在目标文件中发出引用,指出正在调用的函数。
编译器完成后,链接器将所有目标文件放在一起并更新函数引用以指向实际实现,无论它们是否位于 DLL 中。所以你必须为链接器而不是编译器提供必要的信息,它需要知道哪些目标文件和 DLL 导入文件来查看函数的位置。
大多数通用编译器/链接器工具链的项目生成文件通常会包含一组默认的 DLL 导入文件,供链接器查看,例如 kernel32.lib(可以从中解析 CreateProcess(A|W))、user32.lib 等.
【讨论】:
为了静态链接到 DLL(是的,静态链接),您链接到声明要导入的函数的 .lib 库。
VS 编译器支持#pragma,它告诉链接器使用特定的.lib 文件(使用特定的路径解析规则)。这样的#pragma 存在于 Windows 头文件中。
现在在加载时,系统使用特定的路径解析规则查找在 .lib 文件中命名的 DLL 文件,并将导入的原型与 DLL 导出的函数进行匹配。
因此,将函数映射到 DLL 的字典实际上是由每个 DLL 的头文件引用的 .lib 文件组成的。
【讨论】: