HOOK(钩子)

来源:互联网 发布:百马百担c语言编程答案 编辑:程序博客网 时间:2024/06/05 10:52

HOOK

钩子(Hook),是Windows消息处理机制的一个平台,应用程序可以在上面设置子程以监视指定窗口的某种消息,而且所监视的窗口可以是其他进程所创建的。当消息到达后,在目标窗口处理函数之前处理它。钩子机制允许应用程序截获处理window消息或特定事件。
钩子实际上是一个处理消息的程序段,通过系统调用,把它挂入系统。每当特定的消息发出,在没有到达目的窗口前,钩子程序就先捕获该消息,亦即钩子函数先得到控制权。这时钩子函数即可以加工处理(改变)该消息,也可以不作处理而继续传递该消息,还可以强制结束消息的传递。


HOOK的原理

windows一直都是有自己处理各种消息的函数,Hook其实就能够做到程序员自己处理自己感兴趣的事情。这样说,假设Windows的消息就是马路上的车辆,一般情况下是Windows自己派人在检查,然后呢,Hook是拥有这个能力能在Windows自己安排的检查站之前也进行抽查,Hook根据程序员的需求可以变化,比如我就感兴趣100万以上的车(可能是走私的(^__^)),Hook就能在检查的时候专门找100万以上的车,至于其他不上档次的车Hook就放行,交还给Windows自己的检查站。同样Hook可以“为所欲为”,可以擅自设立一个检查站,也可以两个,三个···换成程序来说,钩子函数的工作原理是:当我们创建一个钩子时,WINDOWS会先在内存中创建一个数据结构,该数据结构包含了钩子的相关信息,然后把该结构体加到已经存在的钩子链表中去。新的钩子将加到老的前面。当一个事件发生时,如果我们安装的是一个局部钩子(下面有解释,暂时理解为你程序本身中的),我们进程中的钩子函数将被调用。

HOOK链表和函数

每一个Hook都有一个与之相关联的指针列表,称之为钩子链表,由系统来维护。被Hook子程调用的回调函数,也就是该钩子的各个处理子程。当与指定的Hook类型关联的消息发生时,系统就把这个消息传递到Hook子程。一些Hook子程可以只监视消息,或者修改消息,或者停止消息的前进,避免这些消息传递到下一个Hook子程或者目的窗口。最近安装的钩子放在链的开始,而最早安装的钩子放在最后,也就是后加入的先获得控制权。钩子子程是一个应用程序定义的回调函数(CALLBACKFunction),不能定义成某个类的成员函数,只能定义为普通的C函数。用以监视系统或某一特定类型的事件,这些事件可以是与某一特定线程关联的,也可以是系统中所有线程的事件。

钩子子程必须按照以下的语法:

LRESULT CALLBACK HookProc(int nCode, //指定是否需要处理该消息 WPARAM wParam, LPARAM lParam //包含该消息的附加消息 ,);

这个回调函数的名字可以随你取,但形式可一定要满足以上要求,其实钩子的回调函数和Windows的差不多一个德行。看看钩子函数的返回值,若是返回非0值,表示我们已经自己处理了该消息,则消息就不被传递到目标窗口过程。
看看

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

这个函数把钩子信息传递给下一个钩子函数,也就是可以理解成把车辆放行到下一个检查站,这个可以根据自己的需要进行调用。若是我们只设定了一个钩子函数,那么我们假设把钩子消息用CallNextHookEx传给下个钩子函数,因为不存在所以就传递回了目标窗口函数。

HOOK的安装和释放

调用SetWindowHookEx函数,该函数的原型如下:

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

返回值是一个hook的句柄。
第一个参数:idHook,是我们感兴趣的消息类型,比如我们对鼠标消息感兴趣就是WH_MOUSE,再者比如键盘消息WH_KEYBOARD,我们可以通过查找Win32 API使用手册来找到自己感兴趣的消息。
第二个参数:钩子函数的地址,这里就有两种情况:其实钩子有两种,一种是局部钩子,这种钩子只能关注自己所在的进程的事件,另一种钩子叫做远程钩子,这里又有两种:
1.基于线程的它将捕获其它进程中某一特定线程的事件。简言之,就是可以用来观察其它进程中的某一特定线程将发生的事件。
2.系统范围的将捕捉系统中所有进程将发生的事件消息。
看上去局部钩子的功能没有远程钩子的给力,但是凡事都是要付出代价的,远程钩子会影响系统的性能,特别是监视系统范围的钩子,因为要监视系统范围的消息,明显就会影响系统的速度。
第三个参数和第四个参数相关,所以一起解释。
如果第四个参数是NULL,则说明是全局钩子,那么就是钩子子程与所有的线程关联,此时第三个参数是程序实例句柄
如果第三个参数是NULL,则说明钩子是局部钩子,说明子程代码位于当前进程,这时候第四个参数就是当前进程的ID,可以用GetCurrentThreadID()填充,或者可以保存实例来填充,再做介绍···
再看看钩子函数的卸载,用UnHookWindowsHookEx(HHOOK hhk);参数就是SetWindowsHookEx返回的句柄。

实例

下面是是一个小程序,大概的功能就是实现在所在进程内的鼠标消息和键盘消息的截获,一旦点击了“LockMouse”那么就在目标窗口截获了所以鼠标的消息,这里实现的是屏蔽鼠标消息,只能通过按回车键恢复鼠标功能。若是点击了“LockKeyBoard”按钮,那么只能在编辑框输入0或者1,但是在没有点击的情况下是正常的编辑框。这点可是比窗口子类化更加简单。

    import pythoncom import pyHook    def onMouseEvent(event):    # 监听鼠标事件        print "MessageName:",event.MessageName        print "Message:", event.Message        print "Time:", event.Time        print "Window:", event.Window        print "WindowName:", event.WindowName        print "Position:", event.Position        print "Wheel:", event.Wheel        print "Injected:", event.Injected              print"---"   # 返回 True 以便将事件传给其它处理程序        # 注意,这儿如果返回 False ,则鼠标事件将被全部拦截        # 也就是说你的鼠标看起来会僵在那儿,似乎失去响应了        return Truedef onKeyboardEvent(event):  # 监听键盘事件        print "MessageName:", event.MessageName        print "Message:", event.Message        print "Time:", event.Time        print "Window:", event.Window        print "WindowName:", event.WindowName        print "Ascii:", event.Ascii, chr(event.Ascii)        print "Key:", event.Key        print "KeyID:", event.KeyID        print "ScanCode:", event.ScanCode        print "Extended:", event.Extended        print "Injected:", event.Injected        print "Alt", event.Alt        print "Transition", event.Transition        print "---"         # 同鼠标事件监听函数的返回值        return True def main():        # 创建一个“钩子”管理对象        hm = pyHook.HookManager()         # 监听所有键盘事件        hm.KeyDown = onKeyboardEvent        # 设置键盘“钩子”        hm.HookKeyboard()         # 监听所有鼠标事件        hm.MouseAll = onMouseEvent        # 设置鼠标“钩子”        hm.HookMouse()         # 进入循环,如不手动关闭,程序将一直处于监听状态        pythoncom.PumpMessages() if __name__ == "__main__":        main()

运行结果

hook代码运行结果

附录

脚本运行错误:
no module named pythoncom
no module named pyHook
解决办法:
通过下载安装包进行安装:
pythoncom:http://sourceforge.net/projects/pywin32/files/pywin32/Build%20219/pywin32-219.win32-py2.7.exe/download
pyHook:http://nchc.dl.sourceforge.net/project/pyhook/pyhook/1.5.1/pyHook-1.5.1.win32-py2.7.exe

0 0