钩子函数和键盘记录
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
钩子必备函数
要安装钩子,必须用SetWindowsHookEx函数,函数原型如下:
HHOOK SetWindowsHookEx(int idHook,HOOKPROC lpfn,HINSTANCE hMod,DWORD dwThreadId);
idhook参数指定钩子的类型,钩子的类型如下:
WH_CALLWNDPROC每当调用SendMessage函数时,函数将消息发送给目标窗口时首先调用钩子函数。
WH_CALLWNDPROCRET每当调用SendMessage函数时,函数将消息发送给目标窗口过程后再调用钩子函数。
WH_GETMESSAGE每当调用GetMessage或PeekMessage,函数从消息的队列里获取一个消息后调用钩子函数。
WH_KEYBOARD 每当调用GetMessage或PeekMessage,如果从消息队列中得到是WM_KEYUP或WM_KEYDOWN消息时,则调用钩子函数
WH_MOUSE每当调用GetMessage或PeekMessage时,如果从消息队列中得到的是鼠标消息时,则调用钩子函数。
WH_HARDWARE每当调用GetMessage或PeekMessage时,如果从消息队列中得到的不是鼠标和键盘消息,则调用钩子函数。
WH_MSGFILTER当用户对对话框,菜单和滚动条有所操作时,系统在发送对应的消息之前调用钩子函数,这种钩子只能是局部的。
WH_SYSMSGFILTER,同上,不过是系统范围的
WH_SHELL 当windows shell 程序准备接受一些通知事件前调用钩子函数,如shell被激活
WH_DEBUG用来给其它钩子函数除错。
WH_CBT当基于计算机的训练事件时调用钩子函数。
WH_JOURNALRECORD日志记录钩子,用来记录发送给系统消息队列的所有消息,只能用作全局钩子。
WH_JOURNALPLAYBACK,日志回放钩子,用来回放日志记录钩子记录的事件,只能用作全局钩子。
WH_FOREGROUNDIDLE系统空闲钩子,当系统空闲时调用钩子函数,这样就可以在这里安排一些优先级很低的任务。
Lpfn参数用来传入钩子函数的入口地址。
hInstance参数用来指定钩子回调函数所在DLL的实例句柄,如果安装的是局部钩子的话,由于句柄钩子的回调函数不需要放在DLL中,这个参数就可以用NULL。
DWThreadID是安装钩子后想监控的线程的ID,这个参数可以决定钩子是局部的还是系统范围的。如果参数指定的是自己进程中某个线程的ID,那么该钩子是一个局部钩子,如果指定的是另一个进程中某个线程的ID,那么这个钩子就是一个局部的远程钩子,可以将这个参数设置为NULL,被解释为系统范围的,可以监控所有的进程中的线程。
返回值:如果调用成功,返回的是钩子函数的句柄,否则为NULL,需要指出是这个钩子句柄必须保存下来,因为在回调函数和卸载钩子时还有用这个句柄。
卸载函数:
UnhookWindowsHookEx(HHOOK hhk);
钩子函数编写思路:
下面我们结合WH_JOURNALRECORD类型的钩子,来对键盘记录进行介绍。
LPRESULT CALLB
ACK JournalRecordProc(int code,WPARAM wParam,LPARAM lParam);各类钩子的回调函数的三个参数都是这样三个,但它们的定义各不相同,就像窗口过程在收到各种不同消息的时候,wParam和lParam的定义各不相同,不同钩子函数的回调函数的返回值定义也各不相同。
对于日志记录钩子来说,参数的定义如下:
code-指定如何处理消息,如果是HC_ACTION,标识lParam指向了一个EVENTMSG结构,这个结构中包含了一个从系统消息队列中移除的消息,同时,钩子的处理过程必须通过将这些记录的信息拷贝到缓冲区或文件中,来记录EVENTMSG结构体的内容,如果是HC_SYSMODALOFF,表示一个系统模式对话框已经被销毁,钩子过程必须继续记录,HC_SYSMODALON,表示一个系统模式对话框正在被显现出来,直到对话框被销毁掉,钩子的处理过程才会停止记录。
wParam-这个参数目前没用到,用NULL
lParam-这个参数指向一个EVENTMSG结构体。
来看看EVENTMSG结构体的定义
typedef struct tagEVENTMSG
{
UINT message;
UINT paramL;
UINT paramH;
DWORD time;
HWND hwnd;
}EVENTMSG;
message-指定捕获的消息,如果是针对键盘捕获,那么这个消息就是WM_KEYUP和WM_KEYDOWN消息。另外,这个参数还有可能传递系统的击键消息,如WM_SYSKEYUP,WM_SYSKEYDOWN,WM_SYSCHAR等消息,,不过,我们指定是捕获键盘的字符消息,只关系WM_KEYUP和WM_KEYDOWN就可以了。
paramL-这个要看具体的消息来定,像我们捕获的键盘消息,那么这个参数中将存放按键 的虚拟码。
paramH-这个要看具体的消息来定,像我们捕获的键盘消息,那么这个参数中存放了按键的重复次数,扫描码和标志等数据,不同数据位定义如下:
?位0-15:按键的重复次数
?位16-24:按键的扫描码
?位24:按键是否是扩展键,(F1与F2等Fx键等,小键盘的数字键等),如果此位是1表示按键是扩展键
?位25-28:未定义
?位29:如果ALT键在按下状态,此位设置为1,否则为0
?位30: 按键的原始状态,消息发送前按键是按下的,此位被设置为1,否则为0
?位31:按键的当前动作,如果是按键按下,那么此位被设置为0,按键释放的话被设置为1
对于每个击键动作,回调函数会在按键按下和释放时被调用两次,只需根据lParam位的31中的标志来记录一次,否则得到的是重复信息。
另外,回调函数收到的参数是以按键的扫描码和虚拟码表示,在送给窗口之前应该转换为ACSII码,windows提供了一个APIh函数,专门完成转换
ToAscii(UINT uVirtKey,UINT uScanCode,PBYTE lpKeyState,LPWORD lpChar,UINT uFlags);
各参数的意义如下:
uVirtKey-这个参数要传入按键的虚拟码,在使用时直接使用钩子
回调函数的EVENTMSG中的paramL参数就可以了