SetWindowsHookEx()方法的代码失败。1428 - dll注入

问题描述 投票:0回答:1

我有以下代码。

LRESULT __stdcall HookCallback(int code,
    WPARAM wParam,
    LPARAM lParam)
{
    ...

    return CallNextHookEx(_hook, code, wParam, lParam);
}

void SetHook()
{
    HMODULE hmod = GetModuleHandle(0);

    if (!(_hook = SetWindowsHookEx(WH_CALLWNDPROCRET, HookCallback, hmod, 0)))
    {
        OutputDebugString(TEXT("Failed to Install hook"));
    }

    OutputDebugString(TEXT("Exiting SETHOOK METHOD"));
}

void ReleaseHook()
{
    UnhookWindowsHookEx(_hook);
}

BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD  ul_reason_for_call,
    LPVOID lpReserved
)
{
    OutputDebugString(TEXT("Entered DLL"));

    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        SetHook();
        break;
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
        break;
    case DLL_PROCESS_DETACH:
        ReleaseHook();
        break;
    }

    return TRUE;
}

我想设置一个钩子来对窗口操作做出反应。我对c++没有经验,所以在调试应用程序和理解我做错了什么的时候非常困难。

在我的 SetHook() 方法的SetWindowHookEx方法总是以代码1428失败。所以Callback方法(这里没有显示)从未被调用。

我到底做错了什么?

PS: 我使用registry:Path将.dll注入到进程中。Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows 名称。AppInit_DLLS

据我所知,这是有效果的,因为我得到了 "Failed to Install hook "和 "Exiting SETHOOK METHOD "的调试信息。

c++ windows winapi hook
1个回答
2
投票

你将0(也就是NULL)传给了 GetModuleHandle(),所以你要检索的是 HMODULE 你的DLL被加载到的EXE文件的进程中。

进程的EXE文件的名称:参数

lpModuleName

被加载的模块名称(可以是.dll或.exe文件)......

如果这个参数为NULL,GetModuleHandle将返回一个用于创建调用进程的文件(.exe文件)的句柄。

你不能使用这个 HMODULE 安装 SetWindowsHookEx() 钩子回调的DLL中。 你需要使用DLL中自己的 HMODULE 本身,即作为输入参数提供给您的 DllMain(),例如

HHOOK _hook = NULL;

LRESULT __stdcall HookCallback(int code,
    WPARAM wParam,
    LPARAM lParam)
{
    ...

    return CallNextHookEx(_hook, code, wParam, lParam);
}

void SetHook(HMODULE hModule) // <-- ADD THIS PARAM
{
    if (!_hook)
    {
        _hook = SetWindowsHookEx(WH_CALLWNDPROCRET, HookCallback, hModule, 0); // <-- USE IT HERE
        if (!_hook)
        {
            OutputDebugString(TEXT("Failed to Install hook"));
        }
    }

    OutputDebugString(TEXT("Exiting SETHOOK METHOD"));
}

void ReleaseHook()
{
    if (_hook)
    {
        UnhookWindowsHookEx(_hook);
        _hook = NULL;
    }
}

BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD  ul_reason_for_call,
    LPVOID lpReserved
)
{
    OutputDebugString(TEXT("Entered DLL"));

    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        DisableThreadLibraryCalls(hModule);
        SetHook(hModule); // <-- PASS IT HERE
        break;
    case DLL_PROCESS_DETACH:
        ReleaseHook();
        break;
    }

    return TRUE;
}

也就是说,你想在全局范围内安装一个钩子(hMod != NULLdwThreadId == 0),所以你只需要调用一次 SetWindowsHookEx(),它没有意义的调用它在 每一 进程,将您的DLL加载到该进程中。 你应该创建你自己的EXE,将你的DLL加载到内存中并调用 SetWindowsHookEx() 1次,例如。

HMODULE _hmod = NULL;
HHOOK _hook = NULL;

// be sure to export your hook functions from the DLL..

LRESULT __stdcall HookCallback(int code,
    WPARAM wParam,
    LPARAM lParam)
{
    ...

    return CallNextHookEx(_hook, code, wParam, lParam);
}

void SetHook()
{
    if (!_hook)
    {
        _hook = SetWindowsHookEx(WH_CALLWNDPROCRET, HookCallback, _hmod, 0);
        if (!_hook)
        {
            OutputDebugString(TEXT("Failed to Install hook"));
        }
    }

    OutputDebugString(TEXT("Exiting SETHOOK METHOD"));
}

void ReleaseHook()
{
    if (_hook)
    {
        UnhookWindowsHookEx(_hook);
        _hook = NULL;
    }
}

BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD  ul_reason_for_call,
    LPVOID lpReserved
)
{
    _hmod = hModule;

    OutputDebugString(TEXT("Entered DLL"));

    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        DisableThreadLibraryCalls(hModule);
        break;
    }

    return TRUE;
}
typedef void (*LPFN_SH)();
typedef void (*LPFN_RH)();

HMODULE hMod = LoadLibrary("my.dll");
LPFN_SH SetHook = (LPFN_SH) GetProcAddress(hMod, "SetHook");
LPFN_RH ReleaseHook = (LPFN_RH) GetProcAddress(hMod, "ReleaseHook");
...
SetHook();
...
ReleaseHook();
FreeLibrary(hMod);

你的DLL将被自动注入到每一个与你的DLL位数相匹配的运行进程中(这意味着你需要单独的DLL来钩住32位和64位进程),在你的EXE进程的生命周期内。 不需要使用 AppInit_DLLS 注册表键根本。


否则,如果你真的想使用 AppInit_DLLS 将你的 DLL 注入到每一个比特度匹配进程中,那么最好让 DLL 调用 SetWindowsHookEx() 以每线程为单位 (hMod == NULLdwThreadId != 0)而不是在全局的基础上,例如。

__declspec(thread) HHOOK _hook = NULL;

LRESULT __stdcall HookCallback(int code,
    WPARAM wParam,
    LPARAM lParam)
{
    ...

    return CallNextHookEx(_hook, code, wParam, lParam);
}

void SetHook()
{
    if (!_hook)
    {
        DWORD dwThreadId = GetCurrentThreadId();

        _hook = SetWindowsHookEx(WH_CALLWNDPROCRET, HookCallback, NULL, dwThreadId);
        if (!_hook)
        {
            OutputDebugString(TEXT("Failed to Install hook"));
        }
    }

    OutputDebugString(TEXT("Exiting SETHOOK METHOD"));
}

void ReleaseHook()
{
    if (_hook)
    {
        UnhookWindowsHookEx(_hook);
        _hook = NULL;
    }
}

BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD  ul_reason_for_call,
    LPVOID lpReserved
)
{
    OutputDebugString(TEXT("Entered DLL"));

    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
        SetHook();
        break;
    case DLL_PROCESS_DETACH:
    case DLL_THREAD_DETACH:
        ReleaseHook();
        break;
    }

    return TRUE;
}

那么就不需要使用单独的EXE加载器了。

© www.soinside.com 2019 - 2024. All rights reserved.