全局键盘钩子问题

zCheng 2009-10-31 02:58:20
Hi 各位大侠,

小弟想通过注入 DLL (到 Winlogon.exe)的方式挂一个全局钩子,但是目前的情况是:
1、成功打开 winlogon.exe,并且成功创建了远程线程。
2、远程线程 LoadLibrary 正确执行,并且返回了正确的值。
3、DllMain 被正确调用并且返回。用 IceSword 可以看见 winlogon.exe 加载了我的 dll。
4、ThreadProc 正常执行,并且正常挂了钩子,返回了一个 Hook ID,用 IceSword 也可以看见这个键盘钩子存在(通过 ID 判断)

问题是:
1、任何键盘操作都没有调用钩子函数……
2、卸载时,会导致死锁。

麻烦各位帮忙分析是什么原因,谢谢了。

kbhook.dll 的代码



LRESULT CALLBACK KeyboardHookProc(int nCode,
WPARAM wParam,
LPARAM lParam
)
{
DebugPrint(_T("KeyboardHookProc(%d,0x%x,0x%x)"), nCode, wParam, lParam);
MessageBeep(0);
if(nCode < 0) {
return CallNextHookEx(hHook, nCode, wParam, lParam);
}

return CallNextHookEx(hHook, nCode, wParam, lParam);
}


DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
BOOL installed = InstallHook();
if(installed)
{
DebugPrint(_T("Hook installation finished, listening keyboard inputs...\r\n"));
}
else
{
DebugPrint(_T("Hook not installed, exiting...\r\n"));
return GetLastError();
}
WaitForSingleObject(hExitEvent, INFINITE);
DebugPrint(_T("UninstallHook() called, exiting...\r\n"));
return 0;
}

VOID InstallHookDelayed()
{
hExitEvent = CreateEvent(NULL, TRUE, FALSE, _T("Can Exit"));
hThread = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
}

BOOL InstallHook()
{
if(hHook != NULL)
{
DebugPrint(_T("Hook already installed.\r\n"));
return TRUE;
}
DebugPrint(_T("Installing hook...\r\n"));
DebugPrint(_T("Updating key state..."));
UpdateKeyState();
DebugPrint(_T("Done.\r\nInstalling keyboard hook..."));
hHook = SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC)KeyboardHookProc, hDllInstance, 0);
if(hHook != NULL)
{
DebugPrint(_T("Done.! Hook ID is 0x%x.\r\n"), hHook);
}
else
{
DebugPrint(_T("Failed ! Error code : %d.\r\n"), GetLastError());
}
return hHook != NULL;
}


BOOL UninstallHook()
{
if(NULL == hHook)
{
return TRUE;
}
SetEvent(hExitEvent);
WaitForSingleObject(hThread, 1000);
CloseHandle(hThread);
CloseHandle(hExitEvent);
hThread = NULL;
DebugPrint(_T("Uninstall hook : 0x%x.\r\n"), hHook);
BOOL bResult = UnhookWindowsHookEx(hHook);
hHook = NULL;
return bResult;
}

BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
hDllInstance = hModule;
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
DebugPrint(_T("Installing dll 0x%x...\r\n"), hDllInstance);
InstallHookDelayed();
//InstallHook();
break;
case DLL_PROCESS_DETACH:
DebugPrint(_T("Uninstalling dll...\r\n"));
UninstallHook();
break;
}
return TRUE;
}


kbhook.exe
注入代码和 Windows 核心编程的相同,注入的目标是 Winlogon.exe,注入完成后 kbhook.exe 退出。
关键代码如下:

// Get the function pointer to LoadLibraryW
PTHREAD_START_ROUTINE pfnLoadLibraryW = (PTHREAD_START_ROUTINE)GetProcAddress(
GetModuleHandle(_T("Kernel32")),
"LoadLibraryW");
if(NULL == pfnLoadLibraryW)
__leave;

DWORD hThreadId = 0;

// Create a remoate thread that calls LoadLibrary(pszLibraryPathRemote);
hThread = CreateRemoteThread(
hProcess,
NULL,
0,
pfnLoadLibraryW,
pszLibraryPathRemote,
0,
&hThreadId);

if(NULL == hThread)
__leave;

// Wait untill the library is loaded.
WaitForSingleObject(hThread, INFINITE);
...全文
214 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
zCheng 2009-11-07
  • 打赏
  • 举报
回复
……最终创建了一个 Dialog,然后在 DialogProc 处理 WM_INITDIALOG 时设置钩子成功了。不过通过这个方法还是无法拦截 Ctrl + Alt + Del。

结贴,谢谢大家的帮助
zCheng 2009-11-02
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 firsthym 的回复:]
你要挂全局钩子,不需要注入到winlogon吧,直接在你注入外壳exe程序里面SetWindowsHookEx(...,0)就可以了,不过要封装到dll里面调用。
[/Quote]

我是希望这个钩子可以随系统启动而启动,随系统消亡而消亡的。如果要在我自己的程序里 SetWindowsHookEx 的话,那么不就露馅了么?

另外,悲剧又发生了,WH_GETMESSAGE 拦截到的都是 0x004c 的消息,而这个消息码在 winuser.h 里面没有定义……
firsthym 2009-10-31
  • 打赏
  • 举报
回复
你要挂全局钩子,不需要注入到winlogon吧,直接在你注入外壳exe程序里面SetWindowsHookEx(...,0)就可以了,不过要封装到dll里面调用。
mstlq 2009-10-31
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 loaden 的回复:]
hHook = SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC)KeyboardHookProc, hDllInstance, 0);
[/Quote]

嗯……
hook游戏程序的时候,我都用WH_KEYBOARD_LL……
zCheng 2009-10-31
  • 打赏
  • 举报
回复
WH_GETMESSAGE 是可以的,但是把我的虚拟机弄死了(疏忽了……Windows 消息可是接连不断的)

WH_KEYBOARD_LL 依然不行,难道只能用 WH_GETMESSAGE 然后分析 MSG 结构的内容,拦截 WM_KEYUP、WM_KEYDOWN 之类的消息??

但是这样会吧整个系统拖慢吧?
zCheng 2009-10-31
  • 打赏
  • 举报
回复
假了吧,要挂低级键盘钩子……此刻泪流满面(话说这是我的第一反映),找时间试试。
老邓 2009-10-31
  • 打赏
  • 举报
回复
老邓 2009-10-31
  • 打赏
  • 举报
回复
hHook = SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC)KeyboardHookProc, hDllInstance, 0);
老邓 2009-10-31
  • 打赏
  • 举报
回复
WH_KEYBOARD不行,用WH_KEYBOARD_LL
lori227 2009-10-31
  • 打赏
  • 举报
回复
hHook = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)KeyboardHookProc, hDllInstance, 0);
lori227 2009-10-31
  • 打赏
  • 举报
回复
换成 WH_GETMESSAGE 这个类型看看~~
zCheng 2009-10-31
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 lori227 的回复:]
挂到进程以后 还要hook到相应得函数才能做你想做的事~~ 你应该仅仅是把dll注入了而已~!
[/Quote]

我在 DllMain 里面有启动另外的线程去调 SetWindowsHookEx 来设置键盘钩子(当然在 DllMain 里直接设置也试过,没成功)。

当前我比较希望的是挂一个全局键盘钩子来监听键盘或者鼠标事件,而不是去 Hook 系统的 API。
lori227 2009-10-31
  • 打赏
  • 举报
回复
windows 核心编程 代码里面应该有一个 CAPIHook 类 用来hook api的 你看看吧~~
lori227 2009-10-31
  • 打赏
  • 举报
回复
挂到进程以后 还要hook到相应得函数才能做你想做的事~~ 你应该仅仅是把dll注入了而已~!

64,682

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧