引言

  Windows操作系统是建立在事件驱动机制之上的,系统各部分之间的沟通也都是通过消息的相互传递而实现的。但在通常情况下,应用程序只能处理来自进程内部的消息或是从其他进程发过来的消息,如果需要对在进程外传递的消息进行拦截处理就必须采取一种被称为HOOK(钩子)的技术。钩子是Windows操作系统中非常重要的一种系统接口,用它可以轻松截获并处理在其他应用程序之间传递的消息,并由此可以完成一些普通应用程序难以实现的特殊功能。基于钩子在消息拦截处理中的强大功能,本文即以VC++ 6.0为编程背景对钩子的基本概念及其实现过程展开讨论。为方便理解,在文章最后还给出了一个简单的有关鼠标钩子的应用示例。

钩子的基本原理

  钩子的本质是一段用以处理系统消息的程序,通过系统调用,将其挂入到系统。钩子的种类有很多,每一种钩子负责截获并处理相应的消息。钩子机制允许应用程序截获并处理发往指定窗口的消息或特定事件,其监视的窗口即可以是本进程内的也可以是由其他进程所创建的。在特定的消息发出,并在到达目的窗口之前,钩子程序先行截获此消息并得到对其的控制权。此时在钩子函数中就可以对截获的消息进行各种修改处理,甚至强行终止该消息的继续传递。

  任何一个钩子都由系统来维护一个指针列表(钩子链表),其指针指向钩子的各个处理函数。最近安装的钩子放在链的开始,最早安装的钩子则放在最后,当钩子监视的消息出现时,操作系统调用链表开始处的第一个钩子处理函数进行处理,也就是说最后加入的钩子优先获得控制权。在这里提到的钩子处理函数必须是一个回调函数(callback function),而且不能定义为类成员函数,必须定义为普通的C函数。在使用钩子时可以根据其监视范围的不同将其分为全局钩子和线程钩子两大类,其中线程钩子只能监视某个线程,而全局钩子则可对在当前系统下运行的所有线程进行监视。显然,线程钩子可以看作是全局钩子的一个子集,全局钩子虽然功能强大但同时实现起来也比较烦琐:其钩子函数的实现必须封装在动态链接库中才可以使用。

钩子的安装与卸载

  由于全局钩子具有相当的广泛性而且在功能上完全覆盖了线程钩子,因此下面就主要对应用较多的全局钩子的安装与使用进行讨论。前面已经提过,操作系统是通过调用钩子链表开始处的第一个钩子处理函数而进行消息拦截处理的。因此,为了设置钩子,只需将回调函数放置于链首即可,操作系统会使其首先被调用。在具体实现时由函数SetWindowsHookEx()负责将回调函数放置于钩子链表的开始位置。 SetWindowsHookEx()函数原型声明如下:

  HHOOK SetWindowsHookEx(int idHook;

  HOOKPROC lpfn;

  HINSTANCE hMod;

  DWORD dwThreadId);

  其中:参数idHook 指定了钩子的类型,总共有如下13种:

  WH_CALLWNDPROC 系统将消息发送到指定窗口之前的"钩子"

  WH_CALLWNDPROCRET 消息已经在窗口中处理的"钩子"

  WH_CBT 基于计算机培训的"钩子"

  WH_DEBUG 差错"钩子"

  WH_FOREGROUNDIDLE 前台空闲窗口"钩子"

  WH_GETMESSAGE 接收消息投递的"钩子"

  WH_JOURNALPLAYBACK 回放以前通过WH_JOURNALRECORD"钩子"记录的输入消息

  WH_JOURNALRECORD 输入消息记录"钩子"

  WH_KEYBOARD 键盘消息"钩子"

  WH_MOUSE 鼠标消息"钩子"

  WH_MSGFILTER 对话框、消息框、菜单或滚动条输入消息"钩子"

  WH_SHELL 外壳"钩子"

  WH_SYSMSGFILTER 系统消息"钩子"

  参数lpfn为指向钩子处理函数的指针,即回调函数的首地址;参数hMod则标识了钩子处理函数所处模块的句柄;第四个参数dwThreadId 指定被监视的线程,如果明确指定了某个线程的ID就只监视该线程,此时的钩子即为线程钩子;如果该参数被设置为0,则表示此钩子为监视系统所有线程的全局钩子。此函数在执行完后将返回一个钩子句柄。

虽然对于线程钩子并不要求其象全局钩子一样必须放置于动态链接库中,但是推荐其也在动态链接库中实现。因为这样的处理不仅可使钩子可为系统内的多个进程访问,也可以在系统中被直接调用,而且对于一个只供单进程访问的钩子,还可以将其钩子处理过程放在安装钩子的同一个线程内,此时SetWindowsHookEx()函数的第三个参数也就是该线程的实例句柄。

  在SetWindowsHookEx()函数完成对钩子的安装后,如果被监视的事件发生,系统马上会调用位于相应钩子链表开始处的钩子处理函数进行处理,每一个钩子处理函数在进行相应的处理时都要考虑是否需要把事件传递给下一个钩子处理函数。如果要传递,就通过函数CallNestHookEx()来解决。尽管如此,在实际使用时还是强烈推荐无论是否需要事件传递而都在过程的最后调用一次 CallNextHookEx( )函数,否则将会引起一些无法预知的系统行为或是系统锁定。该函数将返回位于钩子链表中的下一个钩子处理过程的地址,至于具体的返回值类型则要视所设置的钩子类型而定。该函数的原型声明如下:

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

  其中,参数hhk为由SetWindowsHookEx()函数返回的当前钩子句柄;参数nCode为传给钩子过程的事件代码;参数wParam和lParam 则为传给钩子处理函数的参数值,其具体含义同设置的钩子类型有关。

  最后,由于安装钩子对系统的性能有一定的影响,所以在钩子使用完毕后应及时将其卸载以释放其所占资源。释放钩子的函数为UnhookWindowsHookEx(),该函数比较简单只有一个参数用于指定此前由SetWindowsHookEx()函数所返回的钩子句柄,原型声明如下:

  BOOL UnhookWindowsHookEx(HHOOK hhk);

VC里面的钩子程序HOOK相关推荐

  1. [C++]键盘钩子程序

    实现适时监视键盘,并将按键信息保存在TXT文件中的程序 Windows系统是建立在事件驱动的机制上的,说穿了就是整个系统都是通过消息的传递来实现的.而钩子是Windows系统中非常重要的系统接口,用它 ...

  2. svn钩子程序上传文件中文文件导致报错的处理办法

    2019独角兽企业重金招聘Python工程师标准>>> 报错信息 错误: post-commit hook failed (exit code 1) with output:   错 ...

  3. Python【WINAPI】钩子程序获取账号密码等键盘输入信息

    Python2.7.x版本 chr(lParam[0])会出现下面的类型转换错误,造成溢出的异常,在Python2.X版本的int是无限大,而C语言的长度有限制,所以就会出现这种溢出错误 hooked ...

  4. 创建钩子(Hook)

    创建钩子(Hook) 什么是Hook(钩子) 钩子(Hook),是Windows消息处理机制的一个平台,应用程序可以在上面设置子程以监视指定窗口的某种消息,而且所监视的窗口可以是其他进程所创建的.当消 ...

  5. 微信公众号抓取研究----使用xposed程序hook

    前言: 最近在学习点安卓的知识,发现了Xposed的安卓程序,想着之前搞个微信公众号抓取的研究,所有的聊天记录都会保存在手机本地,每接收或者发送一条消息,都要通过程序代码写入到本地的数据库文件里,要想 ...

  6. 做一个检测钩子程序的工具

    一.引言 Windows系统是建立在事件驱动的机制上的,每一个事件就是一个消息,每个运行中的程序,也就是所谓的进程,都维护者一个或多个消息队列,消息队列的个数取决于进程内包含的线程的个数.由于一个进程 ...

  7. 什么是钩子(Hook)

    钩子(Hook)是Windows提供的一种消息处理机制平台,是指在程序正常运行中接受信息之前预先启动的函数,用来检查和修改传给该程序的信息,(钩子)实际上是一个处理消息的程序段,通过系统调用,把它挂入 ...

  8. 一个简单的键盘钩子程序(ZZZ)

    一个简单的键盘钩子程序 从哪儿抄来的忘了,不过写的很简单明了 实现适时监视键盘,并将按键信息保存在TXT文件中的程序         Windows系统是建立在事件驱动的机制上的,说穿了就是整个系统都 ...

  9. 自己写一个键盘钩子程序来监视键盘输入

    "钩子是Windows的消息监视点,应用程序可以在这里安装一个监视子程序,这样就可以在系统中的消息流到达目的窗口过程前监控它们" 上面就是WIN32API手册中对钩子的描述.大概就 ...

  10. 一个简单的键盘钩子程序

    Windows系统是建立在事件驱动的机制上的,说穿了就是整个系统都是通过消息的传递来实现的.而钩子是Windows系统中非常重要的系统接口,用它可以截获并处理送给其他应用程序的消息,来完成普通应用程序 ...

最新文章

  1. Build Tree
  2. [基础题] * 9.(*)设计一个Student接口,以一维数组存储一个班级的学生姓名。
  3. 计算机网络上网时间,电脑怎么限制上网时间
  4. @async方法不调用了_在Spring中使用Future对象调用Async方法调用
  5. c 语言 abs 库函数,absread,abswirte - C 语言库函数手册
  6. [ubuntu 16.04]如何在新建的Anaconda环境中打开jupyter notebook
  7. python代码示例-Python3 实例
  8. 七月算法机器学习3 矩阵分析与应用
  9. MySQL创建企业信息表,基于数据库mysql创建学生信息表(简易版)
  10. Linux原生日志系统Rsyslog详解
  11. Markdown编辑器使用教程_被迫流浪者的博客
  12. android 扫描动画效果图,RadarView之自定义雷达扫描动画效果。
  13. cocos creator之自定义事件
  14. 3dmax材质编辑器模糊字有重影怎么解决?
  15. SpringMVC添加登录页面以及首页实现跳转
  16. linux系统怎么安装office软件,如何在Linux上安装Microsoft Office | MOS86
  17. u3d学习:helloworld
  18. PMI2016大会最全资料集合
  19. 微信小程序开发深入解读
  20. 一款模拟养成类游戏的策划大纲

热门文章

  1. 冰点文库下载安装及使用教程
  2. 使用WPF设计类似Visio的简单绘图软件
  3. JavaScript笔记
  4. web大作业:基于html+css+javascript+jquery实现智能分控网站
  5. Python解运筹学问题
  6. VC++程序设计与应用--MFC应用程序概述
  7. Vue使用js读取Excel数据
  8. Linux可执行文件
  9. Python实现四阶龙格库塔法求解Ricatti方程
  10. 论文阅读(4) 游泳水母对被动能量再捕获的广泛利用(2018)