windows 编程钩子技术初尝(hook)

摘要:
最近,我在学习钩子。作为一个Windows新手,我真的花了一些时间研究它。这里有两个用别人的代码编写的鼠标钩子的例子。1.定义钩子LRESULTCALLBACKHookProc;我们首先在钩子函数中实现用户定义的函数,然后调用函数CallNextHookEx将钩子信息传递给钩子链中的下一个钩子函数。NCode、wParam和lParam是钩子函数。2.当程序初始化时,安装挂钩调用函数SetWindowsHookEx来安装挂钩。只需调用函数BOOLUnhookWindowsHookEx。

最近在研究hook这个东西,作为一个windows菜鸟,研究这个还真花了点时间,下面分享下今天按照别人代码写出的两个鼠标钩子实例。

第一个是针对线程的钩子

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

第一个程序,用一个文档显示当前鼠标的位置,我们知道鼠标的位置信息是,移动鼠标形成鼠标中断--OS发送中断调用驱动--驱动将鼠标的移动信息发给OS--OS进行计算处理得到当前坐标--OS将坐标发给图形界面系统

那么我们的钩子就是在最后OS将坐标发给gwes.exe(也就是图形系统进程的时候),先截取消息,处理完后再发给gwes.exe。

首先我们新建工程MFC  基于单文档的exe

编写钩子程序的步骤分为三步:定义钩子函数安装钩子卸载钩子

1.定义钩子

LRESULT CALLBACK HookProc(int nCode ,WPARAM wParam,LPARAM lParam) ;

我们先在钩子函数中实现自定义的功能,然后调用函数 CallNextHookEx.把钩子信息传递给钩子链的下一个钩子函数。

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

参数 hhk是钩子句柄。nCode、wParam和lParam 是钩子函数。 
当然也可以通过直接返回TRUE来丢弃该消息,就阻止了该消息的传递。

2.安装钩子
在程序初始化的时候,调用函数SetWindowsHookEx安装钩子。
其函数原型为: 
HHOOK SetWindowsHookEx( int idHook,HOOKPROC lpfn, INSTANCE hMod,DWORD dwThreadId ) 
      参数idHook表示钩子类型,它是和钩子函数类型一一对应的。比如,WH_KEYBOARD表示安装的是键盘钩子,WH_MOUSE表示是鼠标钩子等等。
  Lpfn是钩子函数的地址。
  HMod是钩子函数所在的实例的句柄。对于线程钩子,该参数为NULL;对于系统钩子,该参数为钩子函数所在的DLL句柄。
  dwThreadId 指定钩子所监视的线程的线程号。对于全局钩子,该参数为NULL。
  SetWindowsHookEx返回所安装的钩子句柄。
  
 3.卸载钩子

当不再使用钩子时,必须及时卸载。简单地调用函数 BOOL UnhookWindowsHookEx( HHOOK hhk)即可。

值得注意的是线程钩子和系统钩子的钩子函数的位置有很大的差别。线程钩子一般在当前线程或者当前线程派生的线程内,而系统钩子必须放在独立的动态链接库中,实现起来要麻烦一些。

代码:

HHOOK hHook;//鼠标钩子句柄
CPoint point;//鼠标位置信息
CChildView *pView;//实例化

CChildView::CChildView()
{
 pView=this;//获得输出窗口指针
 hHook=SetWindowsHookEx(WH_MOUSE,MouseProc,0,GetCurrentThreadId());

}//在构造函数中创建一个钩子函数

CChildView::~CChildView()
{
 if(hHook)
 UnhookWindowsHookEx(hHook);

}//析构函数中释放钩子函数

//下面是获取消息后的处理函数

LRESULT CALLBACK MouseProc (int nCode, WPARAM wParam, LPARAM lParam)
{//是鼠标移动消息
 if((wParam == WM_MOUSEMOVE)||(wParam == WM_NCMOUSEMOVE))
 {
  point=((MOUSEHOOKSTRUCT *)lParam)->pt;
  //取鼠标信息
  pView->Invalidate(); //窗口重画
 }
 return CallNextHookEx(hHook,nCode,wParam,lParam);
 //传递钩子信息 ,如果直接return true 那么消息就不会往下继续发送
}

这样一个简单的针对线程的钩子应用就OK,移动鼠标就可以看见鼠标的坐标参数。

下面是针对系统的hook应用了:

 这时必须用扩展DLL的方式来实现,为什么呢,因为要对整个系统起作用,要对系统的每个进程起作用,就必须修改他们公用的库,

而这个动态库是可以扩展的,我们可以把钩子的处理通过DLL加入进去。这样,鼠标的信息不管在哪都会通过扩展DLL截下来

然后通过调用该扩展DLL来进行消息的处理。

mark 一下,未完待续

首先建立DLL工程:

建立时选择 共享DLL

免责声明:文章转载自《windows 编程钩子技术初尝(hook)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇用友GRP-u8 注入-RCE漏洞复现supervisor 介绍与安装下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

轻量级锁,偏向锁,重量级锁

轻量级锁,偏向锁,重量级锁 参考视频:https://www.bilibili.com/video/BV16J411h7Rd 对象头信息: normal,正常对象,使用markwork的最后3bits来标记,001就表示正常对象 Biased,偏向锁标记,使用markwork的最后3bits来标记,跟正常对象虽然有区别,但区别不大,101就表示偏向锁...

C# 消息处理机制及自定义过滤方式

一、消息概述 Windows 下应用程序的执行是通过消息驱动的。消息是整个应用程序的工作引擎,我们需要理解掌握我们使用的编程语言是如何封装消息的原理。 1. 什么是消息(Message) 消息就是通知和命令。在.NET框架类库中的System.Windows.Forms命名空间中微软采用面对对象的方式重新定义了Message。新的消息(Message)结构...

多进程浏览器、多线程页面渲染与js的单线程

线程与进程 说到单线程,就得从操作系统进程开始说起。在早期的操作系统中并没有线程的概念,进程是能拥有资源和独立运行的最小单位,也是程序执行的最小单位。任务调度采用的是时间片轮转的抢占式调度方式,而进程是任务调度的最小单位,每个进程有各自独立的一块内存,使得各个进程之间内存地址相互隔离。后来,随着计算机的发展,对CPU的要求越来越高,进程之间的切换开销较大,...

RocketMQ事务消费和顺序消费详解

一、RocketMq有3中消息类型 1.普通消费 2. 顺序消费 3.事务消费 顺序消费场景 在网购的时候,我们需要下单,那么下单需要假如有三个顺序,第一、创建订单 ,第二:订单付款,第三:订单完成。也就是这个三个环节要有顺序,这个订单才有意义。RocketMQ可以保证顺序消费。 rocketMq实现顺序消费的原理  produce在发送消息的时候,把消息...

windows10 中微信(UWP)版本不显示通知消息

前言: 前段时间笔者更换了升级了WINDOWS10系统,从应用商店安装微信后,使用期间不会推送消息通知,右下角的通知栏也无法添加微信图标。搜索百度和Google后,发现很多人都是这样,这是微信(UWP)版本所存在的缺陷。 解决办法: 更换成:微信For Windows版本即可 总结: 下边是一些微信 (UWP)所没有的用户常用功能。 ◆ 缺乏最受用户关注...

详解linux进程间通信-消息队列

前言:前面讨论了信号、管道的进程间通信方式,接下来将讨论消息队列。   一、系统V IPC 三种系统V IPC:消息队列、信号量以及共享内存(共享存储器)之间有很多相似之处。 每个内核中的 I P C结构(消息队列、信号量或共享存储段)都用一个非负整数的标识符( i d e n t i f i e r )加以引用。 无论何时创建I P C结构(调用m s...