无法使用GetProcAddress()从DLL加载某些函数

Unable to load some functions from DLL with GetProcAddress()

本文关键字:加载 DLL 函数 GetProcAddress      更新时间:2023-10-16

我试图建立一个DLL,我想稍后使用SetWindowsHookEx()函数注入一些进程。奇怪的是,当我尝试加载DLL并尝试使用GetProcAddress来获取包含在其中的过程的地址时,如果我试图获取CBT消息处理过程的地址,它将返回NULL,但它适用于其他功能。

这是代码。

DLL头文件(.h)

#include <windows.h>
extern "C" {
    __declspec(dllexport) LRESULT CALLBACK hookProc(int code, WPARAM wParam, LPARAM lParam);
    __declspec(dllexport) int add(int a, int b);
}
DLL FILE (.cpp)
#include "SimpleHook.h"
extern "C" {
    __declspec(dllexport) LRESULT CALLBACK hookProc(int code, WPARAM wParam, LPARAM lParam) {
        return CallNextHookEx(0, code, wParam, lParam);
    }
    __declspec(dllexport) int add(int a, int b) {
        return a + b;
    }
}

主文件

#include <iostream>
#include <windows.h>
#include <tchar.h>
int main(int argc, char* argv[]) {
    HINSTANCE dllHandle = LoadLibrary(_T("SimpleHook.dll"));
    if (dllHandle) {
        // returns the correct address
        cout << "add address: " << GetProcAddress(dllHandle, "add") << endl;
        // returns NULL
        cout << "hookProc address: " << GetProcAddress(dllHandle, "hookProc") << endl;
    }
}

如果我使用GetLastError(),我得到127错误代码的含义:

ERROR_PROC_NOT_FOUND:指定的过程不能被找到。

奇怪的是,来自同一文件的其他函数被正确加载。任何帮助都非常感谢!

调用约定改变了名称混淆。__stdcall函数的名称总是以_为前缀,并且以其他方式进行了修改,因此链接失败,但__cdecl函数没有修改,因此找到了它。

要从您使用__declspec(dllexport)构建的DLL导入,您应该始终在您想要导入的所有内容上包含__declspec(dllimport)的头,并链接您从构建DLL中获得的库。这将保证所有的函数都能正确链接,而不必使用兼容c的链接。

你不应该使用GetProcAddress,也不应该将extern "C"__declspec(dllexport)结合使用。

头:

#include <windows.h>
#ifndef MAIN
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif
DLL_API LRESULT CALLBACK hookProc(int code, WPARAM wParam, LPARAM lParam);
DLL_API int add(int a, int b);

DLL .cpp文件:

#include "SimpleHook.h"
DLL_API LRESULT CALLBACK hookProc(int code, WPARAM wParam, LPARAM lParam) {
    return CallNextHookEx(0, code, wParam, lParam);
}
DLL_API int add(int a, int b) {
    return a + b;
}

主。cpp文件:

#define MAIN
#include "SimpleHook.h"
int main(int argc, char* argv[]) {
    if (dllHandle) {
        // returns the correct address
        cout << "add address: " << add << endl;
        // returns NULL
        cout << "hookProc address: " << hookProc << endl;
    }
}

不要忘记将库添加到链接器

CALLBACK宏解析为__stdcall。因此,必须在函数名后面加上一个下划线字符,并将参数的大小附加到函数名后面:

cout << "hookProc address: " << GetProcAddress(dllHandle, "_hookProc@12")
     << endl;

您必须使用dumpbin或Dependency Walker之类的工具来了解混乱的名称。

或者您可以在链接时使用DEF文件,将您选择的名称放在导出表中。