为什么直接获取导出函数的指针 return 同一个模块中的地址?
Why does getting an exported function's pointer directly return an address in the same module?
我正在使用经典设置来挂接 d3d9 函数:注入 DLL,然后获取目标函数地址并使用 JMP 指令修补它们。
但是我 运行 遇到了一些我不太明白的事情。考虑我将注入目标进程的 DLL 中的以下片段:
HMODULE ModuleBasedOnGetAPI = NULL;
HMODULE ModuleBasedOnAddress = NULL;
ModuleBasedOnGetAPI = GetModuleHandleA("d3d9.dll");
D3D9Create_Original = (t_D3D9Create)GetProcAddress(ModuleBasedOnGetAPI,
"Direct3DCreate9");
D3D9Create_Original2 = &Direct3DCreate9;
GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
(LPCSTR)D3D9Create_Original2, &ModuleBasedOnAddress);
char ModuleBasedOnGetAPI_path[_MAX_PATH];
GetModuleFileNameA(ModuleBasedOnGetAPI, ModuleBasedOnGetAPI_path, _MAX_PATH);
char ModuleBasedOnAddress_path[_MAX_PATH];
GetModuleFileNameA(ModuleBasedOnAddress, ModuleBasedOnAddress_path,
_MAX_PATH);
其中D3D9Create_Original和D3D9Create_Original2是函数指针类型:
IDirect3D9*(__stdcall *)(UINT)
基本上我进行了通常的 GetModuleHandle 调用并获取了该文件的名称。然后我得到函数指针并使用 GetModuleHandleEx
和 GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
来基本上确定该地址来自哪个 DLL。
所以ModuleBasedOnGetAPI_path
是d3d9.dll文件的实际路径。
虽然 ModuleBasedOnAddress_path
似乎是从中获取此代码段的我的 DLL 的路径。
那是为什么呢?为什么 Direct3DCreate9
函数同时存在于我的 DLL 和 d3d9.dll 中?这与我在构建 DLL 时链接 d3d9.lib 有什么关系吗?
您的构建配置是什么(即调试或发布)?看起来编译器的优化在这里也很重要。
对于发布版本,我无法重现该问题 - 两个地址相同。
对于调试版本,您的假设是正确的。这是因为当你在代码中直接引用Direct3DCreate9
时,你是在调用自己模块中的存根代码,它会进一步从Import Address Table中获取真正的Direct3DCreate9
地址。
为了更好地说明这个概念:
请注意Visual Studio已经告诉你这两个地址来自不同的模块。
我们来看看地址0x008f1249
:
不过是一个jmp
。进一步看0x08FCFAD
:
再跳一次。最后 0x0913220
:
请记住 D3D9Create_Original
的值 - 这是与 D3D9Create_Original
相同的真实地址。
我正在使用经典设置来挂接 d3d9 函数:注入 DLL,然后获取目标函数地址并使用 JMP 指令修补它们。
但是我 运行 遇到了一些我不太明白的事情。考虑我将注入目标进程的 DLL 中的以下片段:
HMODULE ModuleBasedOnGetAPI = NULL;
HMODULE ModuleBasedOnAddress = NULL;
ModuleBasedOnGetAPI = GetModuleHandleA("d3d9.dll");
D3D9Create_Original = (t_D3D9Create)GetProcAddress(ModuleBasedOnGetAPI,
"Direct3DCreate9");
D3D9Create_Original2 = &Direct3DCreate9;
GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
(LPCSTR)D3D9Create_Original2, &ModuleBasedOnAddress);
char ModuleBasedOnGetAPI_path[_MAX_PATH];
GetModuleFileNameA(ModuleBasedOnGetAPI, ModuleBasedOnGetAPI_path, _MAX_PATH);
char ModuleBasedOnAddress_path[_MAX_PATH];
GetModuleFileNameA(ModuleBasedOnAddress, ModuleBasedOnAddress_path,
_MAX_PATH);
其中D3D9Create_Original和D3D9Create_Original2是函数指针类型:
IDirect3D9*(__stdcall *)(UINT)
基本上我进行了通常的 GetModuleHandle 调用并获取了该文件的名称。然后我得到函数指针并使用 GetModuleHandleEx
和 GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
来基本上确定该地址来自哪个 DLL。
所以ModuleBasedOnGetAPI_path
是d3d9.dll文件的实际路径。
虽然 ModuleBasedOnAddress_path
似乎是从中获取此代码段的我的 DLL 的路径。
那是为什么呢?为什么 Direct3DCreate9
函数同时存在于我的 DLL 和 d3d9.dll 中?这与我在构建 DLL 时链接 d3d9.lib 有什么关系吗?
您的构建配置是什么(即调试或发布)?看起来编译器的优化在这里也很重要。
对于发布版本,我无法重现该问题 - 两个地址相同。
对于调试版本,您的假设是正确的。这是因为当你在代码中直接引用Direct3DCreate9
时,你是在调用自己模块中的存根代码,它会进一步从Import Address Table中获取真正的Direct3DCreate9
地址。
为了更好地说明这个概念:
请注意Visual Studio已经告诉你这两个地址来自不同的模块。
我们来看看地址0x008f1249
:
不过是一个jmp
。进一步看0x08FCFAD
:
再跳一次。最后 0x0913220
:
请记住 D3D9Create_Original
的值 - 这是与 D3D9Create_Original
相同的真实地址。