Windows中Hook的使用——Hook函数篇
提起HOOK,已经不是什么新的话题了。在Windows的进程监控和消息监控等方面,HOOK机制都给予了强有力的支持,使得上述应用变得易于实现。本文旨在介绍一下HOOK函数的使用方法,函数的说明主要译自MSDN,也部分参考了网上的其它文章,希望与大家共勉!。
HOOK函数是系统消息处理机制的一个入口点,通过它应用程序可以安装一个例程,来监视系统的消息传递路线,对某种特定的消息在传递到目标窗口之前进行响应。
(1)钩子函数的安装 ——SetWindowsHookEx
SetWindowsHookEx 函数用于安装一个应用程序定义的钩子例程到钩子链中,你可以安装一个钩子例程来监视系统中的某些事件,这些事件既可以与某一特定的线程有关,也可以与系统中的所有线程有关。
HHOOK SetWindowsHookEx(
int idHook,//要安装的钩子类型
HOOKPROC lpfn,//钩子例程的入口地址
HINSTANCE hMod,//应用程序的事例句柄
DWORD dwThreadId //安装钩子的线程标识
);
参数:
idHook
指定要安装的钩子类型,这个参数可以是下列值
值描述
WH_CALLWNDPROC 安装一个钩子例程监视传递给目标窗口例程之前的消息。WH_CALLWNDPROCRET 安装一个钩子例程监视已被目标窗口例程处理之的消息。
WH_CBT 安装一个钩子例程接受与计算机训练有关的消息
WH_DEBUG 安装一个钩子例程用于调试其他钩子例程
WH_FOREGROUNDIDLE 安装一个钩子例程用于当应用程序前台线程空闲时被调用,这个钩子对于在系统空闲时运行一些低优先权的任务特别有用。
WH_GETMESSAGE 安装一个钩子例程用于监视加入到消息队列中的消息。
WH_JOURNALPLAYBACK 安装一个钩子例程用于投递先前被WH_JOURNALRECORD 钩子记录的消息
WH_JOURNALRECORD 安装一个钩子例程用于记录投递系统消息队列的输入消息,这个钩子对于记录宏特别有用。
WH_KEYBOARD 安装一个钩子例程用于监视键盘击打消息。
WH_KEYBOARD_LL Windows NT: 安装一个钩子例程用于监视低级别的键盘输入事件。
WH_MOUSE 安装一个钩子例程用于监视鼠标消息。
WH_MOUSE_LL Windows NT: 安装一个钩子例程用于监视低级别的鼠标输入事件。
WH_MSGFILTER 安装一个钩子例程用于监视由对话框消息框菜单或者滚动条输入事件产生的消息。
WH_SHELL 安装一个钩子例程用于接受对外壳应用程序有用的通知消息。
WH_SYSMSGFILTER 安装一个钩子例程用于监视由对话框消息框菜单或者滚动条输入事件产生的消息,这个钩子将监视系统同中所有的应用程序中的所有消息。
lpfn
钩子例程的指针. 如果线程dwThreadId 参数为零或者为不同进程产生的线程识
别码,lpfn 参数必须为指向动态连接库(.dll )中的钩子例程的指针。 否则,
lpfn 则可指向当前进程有关的代码中的钩子例程。
hMod
包含由lpfn 参数指定的内含钩子例程的动态连接库的柄。如果dwThreadId 指
定了当前进程产生的线程标示码,或者钩子例程在当前进程的代码范围内,此
值必须为空(NULL)
dwThreadId
指定与钩子函数有关的线程识别码,如果此值为零,那么钩子函数降与所有存
在线程有关。
返回值
如果执行成功将返回钩子例程的柄。
否则,将返回NULL 值,可以通过GetLastError()获得扩展的错误信息。
钩子使用的范围依赖钩子的类型,一些钩子只能在系统的范围内,而另一些既可以在
系统的范围内又可以在线程范围内。先列表如下
钩子类型 使用范围
WH_CALLWNDPROC 系统或线程
WH_CALLWNDPROCRET 系统或线程
WH_CBT 系统或线程
WH_DEBUG 系统或线程
WH_FOREGROUNDIDLE 系统或线程
WH_GETMESSAGE 系统或线程
WH_JOURNALPLAYBACK 系统
WH_JOURNALRECORD 系统
WH_KEYBOARD 系统或线程
WH_KEYBOARD_LL 系统或线程
WH_MOUSE 系统或线程
WH_MOUSE_LL 系统或线程
WH_MSGFILTER 系统或线程
WH_SHELL 系统或线程
WH_SYSMSGFILTER 系统
(2)卸载钩子例程——UnhookWindowsHookEx
UnhookWindowsHookEx 函数用于卸载由SetWindowsHookEx 函数创建的钩子链例程
BOOL UnhookWindowsHookEx(
HHOOK hhk //要去除的钩子例程的柄
);
参数
hhk
要去除的钩子例程的柄. 这个参数通过先前调用SetWindowsHookEx. 获得。
返回值
成功返回非零。
失败返回零值 可通过GetLastError.()获得错误信息。
(3 )调用钩子函数链中的下一个钩子函数 ——CallNextHookEx:
CallNextHookEx 函数用于向当前钩子链下一个钩子例程传递钩子信息,一个钩子例程既可以在钩子信息处理前也可以在钩子信息处理后点用这个函数。
LRESULT CallNextHookEx(
HHOOK hhk,//当前钩子的柄
int nCode,//传递到钩子例程的钩子代码
WPARAM wParam,//传递给钩子例程的值
LPARAM lParam //传递给钩子例程的值
);
参数:
hhk
当前钩子的柄. 应用程序接受这个柄,作为先前调用 SetWindowsHookEx 函数的结果
nCode
指定传递到当前钩子例程的钩子代码,下一个钩子例程使用这个代码以此决定如何处理钩子信息
wParam
指定传递给钩子例程的wParam 参数值 ,参数值的具体含义与当前钩子链的挂接的钩子类型有关
lParam
指定传递给钩子例程的wParam 参数值 ,参数值的具体含义与当前钩子链的挂接的钩子类型有关
返回值:
返回值是链中下一个钩子例程返回的值,当前钩子例程必须返回这个值,返回值的具体含义与挂接的钩子类型有关,详细信息请参看具体的钩子例程描述。
调用CallNextHookEx 函数是可选的,是系统强烈推荐你调用这个函数,否则,一
些安装钩子的其它应用程序将因为无法收到钩子信息导致无法正常运行,你应该调用这个函数除非你不想让其他应用程序收到通知消息。
(4)回调函数
回调函数依据钩子类型不同而不同,下面以对应WH_CALLWNDPROC类型的回调函数CallWndProc举例说明一下。 CallWndProc钩子例程是应用程序定义的或者动态连接库用SetWindowsHookEx 定义的回调函数。当 SendMessage 函数被调用时,系统将调用着这个例程。在消息传递个目标窗口之前,系统先将消息传递给钩子例程,钩子例程可以检查这个消息,但不能修改它。
LRESULT CALLBACK CallWndProc(
int nCode,//钩子代码
WPARAM wParam,//当前进程标志
LPARAM lParam //带有消息数据的结构地址
);
参数:
nCode
指明钩子例程是否必须处理消息。如果nCode值为HC_ACTION,钩子例程必须处理消息,若nCode 值小于零,钩子例程必须传递消息给CallNextHookEx 函数,而不能做进一步的处理,而且必须由CallNextHookEx 函数返回值。
wParam
确定消息是否已被当前线程发送,若已被当前线程发送,此值为非零,否则为
零。
lParam
包含消息细节的 CWPSTRUCT 结构指针
返回值:如果nCode 小于零,钩子例程必须由CallNextHookEx 函数返回值。如果
nCode 大于等于零,推荐你调用CallNextHookEx 返回它返回的值。否则其它安装了
WH_CALLWNDPROC 钩子的应用程序将无法收到钩子的通知消息而无法正常运行。
如果钩子不调用CallNextHookEx 函数,此值应该为零。
应用程序通过调用SetWindowsHookEx 函数安装指定WH_CALLWNDPPROC 类
型,安装钩子例程。