我是靠谱客的博主 优美溪流,最近开发中收集的这篇文章主要介绍HOOK(钩子,挂钩),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

HOOK(钩子,挂钩)是一种实现Windows平台下类似于中断的机制。HOOK机制允许应用程序拦截并处理Windows消息或指定事件,当指定的消息发出后,HOOK程序就可以在消息到达目标窗口之前将其捕获,从而得到对消息的控制权,进而可以对该消息进行处理或修改,加入我们所需的功能。钩子按使用范围分,可分为线程钩子和系统钩子,其中,系统钩子具有相当大的功能,几乎可以实现对所有Windows消息的拦截、处理和监控。这项技术涉及到两个重要的API,

一个是SetWindowsHookEx,安装钩子;

另一个是UnHookWindowsHookEx,卸载钩子

Windows 有两种钩子,一种是特定线程钩子(Thread specific hooks),一种是全局系统钩子 (Systemwide hooks)。特定线程钩子只是监视指定的线程,而全局系统钩子则可以监视系统中所有的线程。无论是特定线程钩子,还是全局系统 钩子,都是通过 SetWindowsHookEx ()来设置钩子的。对于特定线程钩子,钩子的函数既可以是包含在一个.exe也可以是一个.dll。 但是对于一个全局系统钩子,钩子函数必须包含在独立的 dll中,

编写钩子程序的步骤分为3步:定义钩子函数、安装钩子和卸载钩子。

2.1 定义钩子函数

钩子函数是一种特殊的回调函数。钩子监视的特定事件发生后,系统会调用钩子函数进行处理。不同事件的钩子函数的形式是各不相同的。下面以鼠标钩子函数举例说明钩子函数的原型:

LRESULT CALLBACK HookProc(int nCode ,WPARAM wParam,LPARAM lParam)

参数wParam和 lParam包含所钩消息的信息,比如鼠标位置、状态,键盘按键等。nCode包含有关消息本身的信息,比如是否从消息队列中移出。我们先在钩子函数中实现自定义的功能,然后调用函数 CallNextHookEx.把钩子信息传递给钩子链的下一个钩子函数。CallNextHookEx.的原型如下:

LRESULT CallNextHookEx( HHOOK hhk, int nCode, WPARAM wParam, LPARAM lParam )

参数 hhk是钩子句柄。nCode、wParam和lParam 是钩子函数。当然也可以通过直接返回TRUE来丢弃该消息,就阻止了该消息的传递。

2.2 安装钩子

在程序初始化的时候,调用函数SetWindowsHookEx安装钩子。其函数原型为:

HHOOK SetWindowsHookEx( int idHook,HOOKPROC lpfn, INSTANCE hMod,DWORD dwThreadId )

参数idHook表示钩子类型,它是和钩子函数类型一一对应的。比如,WH_KEYBOARD表示安装的是键盘钩子,WH_MOUSE表示是鼠标钩子等等。

#define WH_JOURNALRECORD    0
#define WH_JOURNALPLAYBACK  1    //使应用程序可以插入消息到系统消息队列。可以使用这个Hook回放通过使用WH_JOURNALRECORD Hook记录下来的连续的鼠标和键盘事件
#define WH_KEYBOARD         2      //用来监视WM_KEYDOWN 和 WM_KEYUP消息,这些消息通过GetMessage 或者 PeekMessage 函数返回。
#define WH_GETMESSAGE       3    //应用程序使用WH_GETMESSAGE Hook来监视从GetMessage or PeekMessage函数返回的消息。你可以使用WH_GETMESSAGE Hook去监视鼠标和键盘输入,以及其他发送到消息队列中的消息。
#define WH_CALLWNDPROC      4   //使你可以监视发送到窗口过程的消息
#define WH_CBT              5    //在以下事件之前,系统都会调用WH_CBT Hook子程,这些事件包括:1. 激活,建立,销毁,最小化,最大化,移动,改变尺寸等窗口事件;2. 完成系统指令;3. 来自系统消息队列中的移动鼠标,键盘事件;4. 设置输入焦点事件;5. 同步系统消息队列事件。

#define WH_SYSMSGFILTER     6
#define WH_MOUSE            7     //监视从GetMessage 或者 PeekMessage 函数返回的鼠标消息

#if defined(_WIN32_WINDOWS)
#define WH_HARDWARE         8
#endif
#define WH_DEBUG            9
#define WH_SHELL           10
#define WH_FOREGROUNDIDLE  11
#if(WINVER >= 0x0400)
#define WH_CALLWNDPROCRET  12
#endif /* WINVER >= 0x0400 */

#if (_WIN32_WINNT >= 0x0400)
#define WH_KEYBOARD_LL     13
#define WH_MOUSE_LL        14

Lpfn是钩子函数的地址。//即回调函数

HMod是钩子函数所在的实例的句柄。对于线程钩子,该参数为NULL;对于系统钩子,该参数为钩子函数所在的DLL句柄。

dwThreadId 指定钩子所监视的线程的线程号。对于全局钩子,该参数为NULL。

SetWindowsHookEx返回所安装的钩子句柄。

2.3 卸载钩子

当不再使用钩子时,必须及时卸载。简单地调用函数:

BOOL UnhookWindowsHookEx( HHOOK hhk)即可。

通常是把“钩子”做成动态链接库DLL,这样的好处是可以在系统内的每个进程中访问

 

 

 

其实在CWnd::Create函数中也会先调

1.CWnd::Create -> CWnd::CreateEx-> PreCreateWindow ->AfxEndDeferRegisterClass ->AfxRegisterClass 进行窗口类注册

2. CWnd::Create -> CWnd::CreateEx -> AfxHookWindowCreate -> ::SetWindowsHookEx(WH_CBT, _AfxCbtFilterHook, NULL, ::GetCurrentThreadId()); ->CALLBACK _AfxCbtFilterHook -> AfxGetAfxWndProc ->CALLBACK AfxWndProc ->AfxCallWndProc

->WindowProc                  所以可以在cwnd类的虚函数WindowProc 重写实现对应的功能

3.最后调用CreateWindowEx进行真正创建窗口,创建成功后,指向一个值的指针,该值传递给窗口WM_CREATE消息。该值通过在lParam参数中的CREATESTRUCT结构传递。如果应用程序调用CreateWindow创建一个MDI客户窗口,则lpParam必须指向一个CLIENTCREATESTRUCT结构。简单一句话产生WM_CREATE消息,响应afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);

 

在MFC 单文档或者多文档模式CMainFrame::Create是通过CMainFrame::LoadFrame调用起来的。而LoadFrame是在应用程序类winapp的InitInstance函数被调用。

所以在整个CMainFrame类的执行先后顺序是:LoadFrame -> Create ->PreCreateWindow -> WindowProc -> OnCreate   

 

上面这些函数被执行完后,回到winapp的InitInstance,执行下面的ShowWindow和UpdateWindow。

InitInstance执行完后,回到afxwinmain。执行run,进入消息循环。

 

 

最后

以上就是优美溪流为你收集整理的HOOK(钩子,挂钩)的全部内容,希望文章能够帮你解决HOOK(钩子,挂钩)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(53)

评论列表共有 0 条评论

立即
投稿
返回
顶部