本文主要介绍了windows的钩子机制,对于初学者进一步理解钩子在Windows编程中的原理和应用有很大的帮助。有需要的朋友可以参考一下。
一、概述:
了解windows程序设计的人都知道,Windows系统程序的运行是基于消息传递机制,几乎所有的程序活动都是由消息驱动的。钩子机制可以看作是一个消息中转站,控制着系统发送消息的处理和传输。通过钩子,我们可以拦截系统发送给应用程序的消息,并在处理后决定是否将消息发送给下一个应用程序。利用钩子的这个特性,我们可以创建一个监控程序来收集和控制系统发送的消息。
二、Windows钩子程序的编制
要编译Windows的hook程序,需要用到SDK中的几个API函数。下面列出了这些函数的原型和描述:
HHOOK SetWindowsHookEx(int id HOOK,HOOK_PROC lpfn,HINSTANCE hMod,DWORD dwThreadID);
参数描述:
IdHook:钩子的类型
Lpfn:钩子处理程序的地址
HMod:包含钩子函数的模块句柄
DwThreadID:钩子的监视线程
功能描述:
该函数将在系统中挂起一个由idHook指定类型的钩子来监视和处理相应的特定消息。
BOOL unhook windowshookex(HHOOK hhk);
函数描述:该函数将撤销hhk指定的钩子。
LRESULT CallNextHookEx( HHOOK hhk,int nCode,WPARAM wParam,LPARAM LPARAM);
函数描述:函数向下传递消息,下一个钩子处理会拦截这个消息。
因为钩子处理涉及到模块和进程之间的数据地址,所以一般的处理是将钩子集成到一个动态链接库(DLL)中,并设置一个全局数据共享数据段来存储一些全局变量,保存最后一个钩子消息事件的状态。全局共享数据段可以按以下格式定义:
#pragma data_seg(PublicData )
HHOOK hhook=NULL//全局共享数据
#pragma data_seg()
在本文附带的示例程序中,它演示了如何编写一个鼠标钩子(WH _鼠标)。这个程序监视Windows系统的鼠标消息。在监控期间,程序可以检查用户点击鼠标左键的次数。其他类型的钩子程序以类似于示例程序的方式编写。
三、范例程序的建立与代码分析
如上所述,钩子处理需要在钩子程序建立时集成到动态链接库中,所以在例程中需要建立两个项目。
1、建立钩子处理动态链接库:
(1)选择MFC AppWizard(DLL)创建一个新项目,命名为 Spy ;
(2)选择MFC扩展DLL类型
(3)创建一个名为“Hook.h”的新头文件,并修改其代码,如下所示
extern C LRESULT回调MouseProc(int代码,
WPARAM wParam,LPARAM LPARAM);//挂钩处理程序
extern C BOOL WINAPI start hook();//启动钩子函数
extern C BOOL WINAPI stop hook();//撤销钩子函数
extern C int WINAPI GetResult();//获取鼠标点击的功能
(4)修改Spy.cpp文件的代码如下(粗体部分为添加内容)
#include stdafx.h
#包含afxdllx.h
#包含“spyhook.h”
…//省略一些机器生成的代码
# pragma data _ seg( public data )//定义全局数据段
HHOOK hhook=NULL//挂钩句柄
h instance pin instance=NULL;//挂钩模块句柄
UINT mouse click=0;//记录鼠标点击次数的变量
#pragma data_seg()
…//省略一些机器生成的代码
extern C int APIENTRY
DllMain(HINSTANCE hInstance,DWORD dwReason,LPVOID lpReserved)
{ if(dw reason==DLL _ PROCESS _ ATTACH)
{…//省略一些机器生成的代码。
新建CDynLinkLibrary(SpyDLL);
pInstance=hInstance//获取模块句柄
}
else if(dw reason==DLL _ PROCESS _ DETACH)
{ TRACE0(SPY。DLL正在终止! n’);
AfxTermExtensionModule(SpyDLL);
}
返回1;
}
extern C LRESULT回调MouseProc(int代码,WPARAM wParam,
AML param)//挂钩处理程序
{if (code 0) //如果code 0,直接调用CallNextHookEx返回
返回CallNextHookEx(hhook,code,wParam,lParam);
if(wParam==WM_LBUTTONDOWN)
{ MouseClick//记录鼠标点击的次数
}
返回CallNextHookEx(hhook,code,wParam,lParam);
}
extern c bool WinAPI Start hook()//启动钩子函数
{ hhook=SetWindowsHookEx(WH _ MOUSE,MouseProc,pInstance,0);//挂机
如果(hhook!=空)
返回TRUE
否则返回FALSE
}
extern c bool WinAPI stop hook()//撤消挂钩函数
{ return unhook windowshookex(hhook);//撤消挂钩
}
exter c int winapi getresult()//返回鼠标点击的次数
{ return MouseClick
}
(5)修改Spy.def文件如下
图书馆“间谍”
描述间谍窗口动态链接库
出口
StartHook @1
止动钩@2
GetResult @3
(6)编译生成Spy.dll文件和间谍项目。Lib文件。
2、建立使用钩子的应用程序
生成单个文档的可执行文件(EXE)的项目
修改资源中的主菜单,增加一个菜单项‘监控’,有三个子菜单项,分别是‘开始’、‘取消’、‘外卖’。
加间谍。Lib文件和Hook.h文件到项目中。
分别修改“开始”、“取消”和“取出”菜单项的命令响应功能,如下所示:
#包含“hook.h”
…//省略一些机器生成的代码
voicmainframe:onstartspy()//开始菜单项的响应函数
{ start hook();
}
VoicmainFrame:on release Spy()//撤销菜单项的响应函数
{ stop hook();
}
Void CMainFrame:OnGet() //取出菜单项的响应函数
{ int Result=get Result();
充电缓冲器[40];
Wsprintf(buffer,你在程序运行过程中点击了鼠标%d次,Result);
* MessageBox(this-m _ hWnd,buffer, Message ,MB _ OK);
}
编译这个项目,把Spy.dll放在生成的可执行文件的目录下,然后就可以运行程序了。运行时,选择‘监控’菜单中的‘开始’菜单项,钩子将开始工作,监控鼠标活动;选择‘取消’菜单项,系统将取消挂钩;选择“取出”菜单项,程序将报告在监控期间用户点击鼠标左键的次数。