HOOK钩子机制

       最近在看一些编程相关的书籍和资料,知识碰见了,就想把它记下来,以便日后能用的上,也可能只是浅显的概念!可能有错,但是有值得参考的地方,慢慢充电吧!

       一、 理解:钩子,顾名思义就是钩东西的,来一个比喻吧。当我们在钓鱼的时候,只要你扔出有诱饵的鱼钩( 设置线程钩子或系统钩子),此后你可能会漫长的等待( HOOK等待消息或者信号的来临),但是一旦这条不幸的鱼上钩了( 有消息传递,截获住了消息),它就跑不了了,这条鱼就任凭我们处置,我们可以选择放生或者报餐一顿等等( 对截获的消息进行处理,调用函数,阻止消息的发送,改变消息都可以,要是被黑客利用感觉好危险啊)!虽然有些残忍,但是没办法,达尔文进化论,物竞天择,优胜劣汰,原谅自私贪婪好吃的人类吧!这就是钩子。
       钩子(hook)就是一个Windows消息的拦截机制。你可以是拦截单个线程的消息 (线程钩子);也可以拦截所有进程的消息( 系统钩子);然后对拦截的消息进行自定义的处理。
      因为windows系统是建立在 事件驱动的机制上,整个系统是通过消息的传递来实现的,例如只有我们在点击鼠标或者按下某个键时,系统才会执行相应的功能,点击鼠标和按键都是一种消息机制通知windows来做某件事(HOOKS)就是一种特殊的消息处理机制,HOOK可以监视系统的各种事件消息,截获发往目标窗口的消息进行处理。这样我们就可以在系统中安装自定义的钩子,监视系统中特定事情的发生,完成相应的功能。
      或者 钩子实际上是一个处理消息的程序段,通过系统调用,把它挂入系统。每当特定的消息发出,在没有到达目的窗口 ,钩子程序就先捕获该消息,也就是钩子程序 得到控制权,钩子函数可以对该消息进行改变 继续传递,或者强制结束传递。
      钩子的种类有很多,每种钩子可以截获并处理相应的消息,如键盘钩子,外壳钩子可以截取、启动和关闭应用程序的消息。钩子可以分为:线程钩子和系统钩子线程钩子监视指定线程的事件消息;系统钩子监视系统中的所有线程的时间消息,因为系统钩子会影响系统中所有的应用程序,所以钩子函数必须放在独立的动态链接库中;
       Windows消息带了一些程序有用的信息,比如Mouse类信息,就带有鼠标所在窗体句柄、鼠标位置等信息(具体可参考相应的消息定义文档),拦截了这些消息,就可以做出例如金山词霸一类的屏幕取词功能。
二、钩子的工作原理
       在正确使用钩子函数前,我们先讲解钩子函数的工作原理。当您创建一个钩子时,WINDOWS会先在内存中创建一个数据结构,该数据结构包含了钩子的相关信息,然后把该结构体加到已经存在的钩子链表中去,成为钩子链表,由系统维护。新的钩子将加到老的前面。当一个事件发生时,如果您安装的是一个进程钩子,您进程中的钩子函数将被调用。如果是一个系统钩子,系统就必须把钩子函数插入到其它进程的地址空间,要做到这一点要求钩子函数必须在一个动态链接库中,所以 如果您想要使用系统钩子,就必须把该钩子函数放到动态链接库中去一般钩子程序和回调函数配合使用,在接收到某一消息时调用某一函数进行相应的操作。
       当然有两个例外:工作日志钩子和工作日志回放钩子。这两个钩子的钩子函数必须在安装钩子的线程中,也就是必须监视每个线程的先后顺序。

       原因是:这两个钩子是用来监控比较底层的硬件事件的,既然是记录和回放,所有的事件就当然都是有先后次序的。所以如果把回调函数放在DLL中,输入的事件被放在几个线程中记录,所以我们无法保证得到正确的次序。故解决的办法是:把钩子函数放到单个的线程中,譬如安装钩子的线程。

三、值得注意的是: 

        (1) 如果对于同一事件(如鼠标消息)既安装了线程钩子又安装了系统钩子,那么系统会自动先调用线程钩子,然后调用系统钩子。 
        (2) 对同一事件消息可安装多个钩子处理过程,这些钩子处理过程形成了钩子链。当前钩子处理结束后应把钩子信息传递给下一个钩子函数。
而且最近安装的钩子放在链的开始,而最早安装的钩子放在最后,也就是后加入的先获得控制权,有点儿栈的意思。 
        (3) 钩子特别是系统钩子会消耗消息处理时间,降低系统性能。只有在必要的时候才安装钩子,在使用完毕后要及时卸载。

四、建立钩子程序的一般步骤
    1、建立钩子函数,函数中通过CallNextHookEx传递消息
    在钩子函数中使用,将钩子信息传递给钩子链的下一个钩子函数。原型如下: 
   LRESULT CallNextHookEx( HHOOK hhk, int nCode, WPARAM wParam, LPARAM lParam ) 
   参数说明:
   hhk -- 钩子句柄。
   nCode、wParam和lParam 是钩子函数对应的入参。
   2、调用SetWindowsHookEx创建钩子
   创建新的钩子函数加入到钩子链中,一般在钩子程序初始化时使用.
   HHOOK SetWindowsHookEx( int idHook,HOOKPROC lpfn, INSTANCE hMod,DWORD dwThreadId)
   返回值:
   HHOOK -- 钩子句柄,需要保留,等不使用钩子时通过UnhookWindowsHookEx函数卸载钩子
   参数说明:
   idHook -- 钩子的拦截消息类型,选择钩子程序的拦截范围,具体值参考文章结尾的消息类型
   lpfn -- 消息的回调函数地址,一般是填函数名
   hMod -- 钩子函数所在的实例的句柄。对于线程钩子,该参数为NULL;对于系统钩子,该参数为钩子函数所在的DLL句柄。在dll中可通过AfxInitExtensionModule(MousehookDLL, hInstance)获得DLL句柄。
   dwThreadId -- 钩子所监视的线程的线程号,可通过GetCurrentThreadId()获得线程号。对于全局钩子,该参数为NULL(或0)。
   3、通过UnhookWindowsHookEx卸载钩子
 当不再使用钩子时,必须及时卸载。简单地调用函数 BOOL UnhookWindowsHookEx( HHOOK hhk)即可。
  最后:钩子拦截消息类型
     WH_CALLWNDPROC :拦截系统发向目标窗体的消息,在目标窗体处理消息前;
     WH_CALLWNDPROCRET :在目标窗体处理完系统发送的消息后,拦截该消息,消息中包含处理返回结果;
     WH_CBT :在以下事件之前,系统都会调用WH_CBT Hook子程,这些事件包括: 
           (1). 激活,建立,销毁,最小化,最大化,移动,改变尺寸等窗口事件; 
           (2). 完成系统指令; 
           (3). 来自系统消息队列中的移动鼠标,键盘事件; 
           (4).  设置输入焦点事件; 
           (5). 同步系统消息队列事件。 

        钩子函数的返回值确定系统是否允许或者防止这些操作中的一个。



其他资料参考:

http://blog.csdn.net/astraylinux/article/details/8223256

http://blog.csdn.net/mingojiang/article/details/7908818

在此感谢博主的分享!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值