c - 如何使用 SetWindowsHookEx 过滤低级按键事件?

标签 c windows hook keylogger

我有这段代码,它为低级事件设置键盘钩子(Hook),然后显示一个消息框。

HHOOK keyboardHook = SetWindowsHookEx (WH_KEYBOARD_LL, HookKey, hInstance, 0);

MessageBox(NULL, L"Click to exit", L"hook test", NULL);

UnhookWindowsHookEx(keyboardHook);

如何在不创建前景窗口的情况下运行应用程序的主循环,以及如何设置 hInstance 来捕获全局事件?

最佳答案

答案都在the MSDN docs page for SetWindowsHookEx上.要试验示例应用程序,请创建一个新解决方案,添加两个项目,一个控制台应用程序和一个 DLL。每个项目只需要一个文件。 DLL 将包含 Hook ,控制台应用程序安装 Hook 。

钩子(Hook)的代码必须存在于 DLL 中,MSDN 文档非常清楚地指出:“如果 dwThreadId 参数为零或指定由不同进程创建的线程的标识符,则lpfn 参数必须指向 DLL 中的 Hook 过程。”实际上, Hook 显然必须位于 DLL 中,否则 shell 如何在另一个应用程序的消息循环中运行代码? DLL 使用其 HINSTANCE 安装 Hook 以识别函数指针所在的位置。

主应用程序运行启动 Hook 并发送消息,再次遵循 MSDN 文档中的说明:“... Hook 应用程序必须继续发送消息,否则它可能会阻止 64 位进程的正常运行”

请注意,这是非常小众的应用程序——您几乎不需要像这样注入(inject) DLL。请,请三思而后行。对于许多应用程序,没有必要捕获低级事件,尽管抑制“开始”菜单的沉浸式应用程序是一个合理的用例。但更重要的是,您很少需要捕获发送到其他应用程序的输入。在使用此代码之前检查您是否确实需要这样做。例如,只需将输入 Hook 到您自己的应用程序窗口,即可录制宏。

main.cpp

#include <windows.h>
#include <tchar.h>

__declspec(dllimport) void (__stdcall runHook)(BOOL startOrStop);
__declspec(dllimport) LRESULT (CALLBACK hookProc)(int code, WPARAM wParam, LPARAM lParam);

int _tmain(int argc, _TCHAR* argv[])
{
  runHook(true);
  MSG Msg;
  while(GetMessage(&Msg, NULL, 0, 0) > 0 && Msg.message != WM_QUIT) {
    TranslateMessage(&Msg);
    DispatchMessage(&Msg);
  }
  runHook(false);
  return 0;
}

动态链接库

#include <assert.h>
#include <windows.h>

static HINSTANCE dllInst = 0;
static HHOOK hookSelf = 0;

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
  dllInst = (HINSTANCE)dllInst;
  return TRUE;
}

__declspec(dllexport) LRESULT (CALLBACK hookProc)(int code, WPARAM wParam, LPARAM lParam)
{
  if (code >= 0) {
    UINT msgType = wParam;
    KBDLLHOOKSTRUCT* msgInfo = (KBDLLHOOKSTRUCT*)lParam;
    // The msgInfo contains the VK_CODE and flags.
  }  
  return hookSelf ? CallNextHookEx(hookSelf, code, wParam, lParam) : 0;
}

__declspec(dllexport) void (__stdcall runHook)(BOOL startOrStop)
{
  assert((bool)hookSelf != (bool)startOrStop);
  if (startOrStop)
    hookSelf = SetWindowsHookEx(WH_KEYBOARD_LL, hookProc, dllInst, 0);
  else {
    UnhookWindowsHookEx(hookSelf);
    hookSelf = 0;
  }
}

关于c - 如何使用 SetWindowsHookEx 过滤低级按键事件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17502485/

相关文章:

c - 在 C/C++ 中使用 realloc 时出错

c++ - 将 WIN32_FIND_DATA 转换为 LPVOID

c++ - 更改带有循环等待图像的进度条

windows - 当路径包含空格时,如何使用通配符从 MS DOS 批处理文件中删除多个文件?

windows - 如何将命令的输出插入批处理文件中的变量?

C++ GUI 和控制台应用程序

windows - 在 C++ 中 Hook IDispatch v 表

python - 我们可以在 conftest.py 之外定义 pytest 钩子(Hook)吗?

c - 无法计算正确的平均值

c - 如何链接 gcc 和 SDL_image 库?