【问题标题】:Hook from SetWindowsHookEx freezes process and don't get executed来自 SetWindowsHookEx 的钩子会冻结进程并且不会被执行
【发布时间】:2016-06-03 15:35:35
【问题描述】:

我试图钩住一个进程的键盘,但是当我按下任意键时,钩子代码不会被执行并且进程会冻结。 我的代码基于以下帖子:How to hook external process with SetWindowsHookEx and WH_KEYBOARD

这是我的 dll 代码:

#include <windows.h>
#include <iostream>
#include <stdio.h>

HINSTANCE hinst = NULL;
#pragma data_seg(".shared")
HHOOK hhk = NULL;
#pragma data_seg()
#pragma comment(linker, "/SECTION:.shared,RWS")

LRESULT CALLBACK wireKeyboardProc(int code, WPARAM wParam, LPARAM lParam) {
    return CallNextHookEx(hhk, code, wParam, lParam);
}

extern "C" __declspec(dllexport) void install(unsigned long threadID) {
    hhk = SetWindowsHookEx(WH_KEYBOARD, wireKeyboardProc, hinst, threadID);
}

BOOL WINAPI DllMain(__in HINSTANCE hinstDLL, __in  DWORD fdwReason, __in  LPVOID lpvReserved) {
    hinst = hinstDLL;
    return TRUE;
}

编辑: 加载 dll 后,我执行函数 install(),它会自动创建钩子,但由于某种原因,当按下键并且进程冻结时,函数 wireKeyboardProc 不会被执行。知道为什么会这样吗?

编辑 2: 这里也是我的 exe 代码:

unsigned long threadID = GetWindowThreadProcessId(hWnd, &ProcessId);

    HINSTANCE hinst;
    hinst = LoadLibrary(_T("hookKbd32.dll"));

    if (hinst) {
        typedef void(*Install)(unsigned long);
        Install install = (Install)GetProcAddress(hinst, "install");
        install(threadID);
    }

【问题讨论】:

  • 如果它“冻结”,那么你有很好的证据表明这个钩子确实有效。这段代码无法为任何人重现问题,这往往可以解释为它不是真正的代码,因为它没有做任何事情,或者您的反恶意软件产品不重视键盘记录器。
  • @HansPassant 我认为不存在这个问题,因为我没有使用任何反恶意软件产品,而且我尝试将 cout 放在那里,但它没有产生任何输出。我认为函数 wireKeyboardProc 没有出于任何原因执行。
  • 您没有显示任何使用这些函数的代码。鉴于您发布的代码,none 您的函数会被调用。另请参阅:minimal reproducible example
  • @theB 我试图编辑我的帖子以使其更清晰。感谢帮助。 :)
  • “注入DLL后”这句话让我很担心。如果我理解正确,SetWindowsHookEx 会为您将 DLL 加载到目标进程中——您不应该注入它。但是您确定在使用发布的代码时会崩溃吗?例如,如果您的真实代码调用了cout,则可能会导致崩溃。无论如何,发布的代码似乎没有任何问题,所以问题可能出在调用 install() 的代码上,请发布整个程序。

标签: c++ windows hook freeze setwindowshookex


【解决方案1】:

我在尝试向 nox 播放器(android 模拟器)添加挂钩时遇到了同样的问题。我已经用另一个模拟器尝试了相同的代码,它运行良好。

在此之后,我确信 nox 包含一个反钩子系统……可能与您的程序相同。在 SetWindowsHookExA 之后,Nox 看起来冻结或退出,根本没有捕获事件。

已编辑。我知道为什么经过几个小时的检查...... 64 位应用程序需要 64 位 dll,而 32 位应用程序需要 32 位 dll。

来自:https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowshookexa

SetWindowsHookEx 可用于将 DLL 注入另一个进程。一种 32位DLL不能注入64位进程,64位DLL 不能注入到 32 位进程中。如果应用程序需要 在其他进程中使用钩子,需要一个 32 位的 应用程序调用 SetWindowsHookEx 将 32 位 DLL 注入 32 位 进程,以及一个 64 位应用程序调用 SetWindowsHookEx 来注入一个 将 64 位 DLL 转换为 64 位进程。 32 位和 64 位 DLL 必须具有 不同的名字。

因为钩子在应用程序的上下文中运行,它们必须匹配 应用程序的“位数”。如果 32 位应用程序安装了 64 位 Windows 上的全局钩子,32 位钩子被注入到每个 32 位进程(通常的安全边界适用)。在 64 位 进程中,线程仍被标记为“已挂钩”。然而,因为一个 32位应用程序必须运行钩子代码,系统执行 在钩子应用程序的上下文中钩子;具体来说,在线程上 称为 SetWindowsHookEx。这意味着挂钩应用程序必须 继续泵送​​消息,否则可能会阻止正常运行 64 位进程。如果 64 位应用程序安装了全局挂钩 在 64 位 Windows 上,将 64 位挂钩注入每个 64 位 进程,而所有 32 位进程都使用挂钩回调 应用。

挂钩 64 位 Windows 桌面上的所有应用程序 安装,安装一个32位全局钩子和一个64位全局钩子, 每个都来自适当的流程,并确保不断发送消息 在挂钩应用程序中,以避免阻塞正常运行。如果 您已经有一个 32 位全局挂钩应用程序,但它没有 需要在每个应用程序的上下文中运行,您可能不需要创建 64 位版本。

https://docs.microsoft.com/en-us/windows/win32/winprog64/process-interoperability

您可以在 64 位 Windows 上运行基于 Win32 的应用程序,使用 仿真层。 ARM 上的 Windows 10 包括 x86-on-ARM64 仿真 层。有关详细信息,请参阅运行 32 位应用程序。

在 64 位 Windows 上,64 位进程无法加载 32 位动态链接 库(DLL)。此外,32 位进程无法加载 64 位 动态链接库。但是,64 位 Windows 支持远程过程调用 (RPC) 在 64 位和 32 位进程之间(都在同一台计算机上和 跨计算机)。在 64 位 Windows 上,进程外 32 位 COM 服务器可以与 64 位客户端和进程外通信 64 位 COM 服务器可以与 32 位客户端通信。因此,如果 你有一个不支持 COM 的 32 位 DLL,你可以把它包装在一个 进程外 COM 服务器并使用 COM 编组与 64 位进程。

【讨论】:

    猜你喜欢
    • 2019-06-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-23
    • 2014-06-26
    • 2014-05-12
    • 1970-01-01
    • 2021-04-18
    • 2011-09-08
    相关资源
    最近更新 更多