WH_DEBUG为调试钩子,用来给钩子函数除错。在系统调用系统中与其他Hook关联的Hook钩子例程之前,系统会调用WH_DEBUG Hook钩子例程。你可以使用这个Hook来决定是否允许系统调用与其他Hook关联的Hook钩子例程。WH_DEBUG调用DebugProc钩子例程。
DebugProc语法:
- LRESULT CALLBACK DebugProc(
- int nCode,
- WPARAM wParam,
- LPARAM lParam
- )
nCode消息处理标识。如果nCode<0,钩子函数不能处理这个消息,需要使用CallNextHookEx函数继续传递消息,并且返回CallNextHookEx的返回值。
wParam指示当前即将被调用的钩子的类型,如WH_MOUSE,WH_KEYBOARD 参数,可支持除了低级鼠标低级键盘钩子的所有钩子。
lParam 指向DEBUGHOOKINFO 结构。
- typedef struct
- {
- DWORD idThread;
- DWORD idThreadInstaller;
- LPARAM lParam;
- WPARAM wParam;
- int code;
- } DEBUGHOOKINFO, *PDEBUGHOOKINFO;
idThread 安装WH_DEBUG钩子的线程ID。
idThreadInstaller 当前即将被调用的钩子所在的线程ID。
lParam 当前即将被调用的钩子的lParam参数。
wParam 当前即将被调用的钩子的wParam参数。
Code 当前即将被调用的钩子的nCode参数。
返回值:当你已经处理了该钩子并且不希望即将被调用的钩子继续执行,则必须返回非0值 否则请返回CallNextHookEx的值。
这里顺便提下钩子回调函数的调用线程。可以在一个全局钩子中打印下GetCurrentThreadID看看返回值,可以看到得到的是一样的值,证明都是安装钩子所在的进程中的调用SetWindowsHookEx所在的线程,所以进行程序自身反HOOK时只要知道判断idThread和idThreadInstaller是否相等就可了。如果相等,说明即将被调用的钩子是自己线程中钩子;如果不等,说明是其它线程中的钩子,只要返回非0值就可以了,这时即将被调用的钩子就不会执行了。但是要去屏蔽其他程序的钩子时,就需要写个DLL来注入了,不过这个貌似没用处吧。。。。不清楚
- #include "stdafx.h"
-
- HHOOK hDebug=NULL;
- HINSTANCE hDllInst=NULL;
- BOOL APIENTRY DllMain( HMODULE hModule,
- DWORD ul_reason_for_call,
- LPVOID lpReserved
- )
- {
- switch (ul_reason_for_call)
- {
- case DLL_PROCESS_ATTACH:
- hDllInst=hModule;
- case DLL_THREAD_ATTACH:
- case DLL_THREAD_DETACH:
- case DLL_PROCESS_DETACH:
- break;
- }
- return TRUE;
- }
-
- LRESULT CALLBACK DebugProc( int nCode,
- WPARAM wParam,
- LPARAM lParam
- )
- {
- if (nCode==HC_ACTION)
- {
- PDEBUGHOOKINFO pDebugHookInfo=(PDEBUGHOOKINFO)lParam;
- switch (wParam)
- {
- case WH_KEYBOARD:
- {
- if (pDebugHookInfo->idThread!=pDebugHookInfo->idThreadInstaller)
- {
- return 1;
- }
- return 1;
- }
- break;
- }
- return CallNextHookEx(hDebug,nCode,wParam,lParam);
- }
- }
-
- BOOL SetHook(BOOL isInstall)
- {
- if (isInstall&&!hDebug)
- {
- hDebug=SetWindowsHookEx(WH_DEBUG,DebugProc,hDllInst,0);
- if (!hDebug)
- {
- return FALSE;
- }
- }
- if (!isInstall&&hDebug)
- {
- BOOL bRet=UnhookWindowsHookEx(hDebug);
- hDebug=NULL;
- return bRet;
- }
- return TRUE;
- }
当然,有矛就有盾捏,比如你要用HOOK进行键盘拦截时,在安装WH_KEYBOARD时,同时安装一个WH_DEBUG钩子。这时你自己的WH_DEBUG钩子将拦截到你自己的WH_KEYBOARD,DEBUGHOOKINFO 结构中的lParam存放的是WH_KEYBOARD的lParam,wParam存放的是WH_KEYBOARD的wParam,只要在这里处理WH_KEYBOARD就可以了。因为HOOK链是按照后进先出的顺序执行的,所以你只要在反HOOK的WH_DEBUG之后安装WH_DEBUG,就可以在它之前进行处理了,目前一些简单的游戏或是即时通讯软件就是简单的安装个WH_DEBUG钩子来屏蔽一些键盘钩子,但是这很屎的,低级键盘钩子都躲不过。
顺便再提下低级键盘钩子,不需要DLL,直接这样安装SetWindowsHookEx(WH_KEYBOARD_LL,LowLevelKeyboardProc,GetModuleHandle(NULL),0);
全局有效,调试钩子屏蔽不了,想要记录某个特定程序键盘输入信息回调函数中判断最前端窗口是否为目标窗口就可以。