Windows Hook链机制详解

Posted CodeBowl

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Windows Hook链机制详解相关的知识,希望对你有一定的参考价值。

Windows Hook链

本文是Windows hook系列的一文。
上一文:《手把手教你用SetWindowsHookEx做一个键盘记录器》.
是本文hook的实例!

引入

hook是Windows操作系统消息处理机制的一个平台,应用程序可以通过设置Hook对某个进程或窗口进行监视,即对特定事件“挂钩”;

一旦预定义特定事件发生,Windows操作系统即会向钩子hook发送通知消息,这时,应用程序可进行响应。

HOOK的处理主要有以下三个阶段:

阶段1:定义Hook;

阶段2:在Hook链表中传递Hook;

阶段3:卸载Hook。

今天主要学习第二阶段的 HOOK链

HOOK链

我一直以来的方法论,就是学习一个东西,要搞清楚五件事情:

1.它是什么?

2.它的作用是什么?

3.它怎么使用?

Hook链是什么?

每一个Hook都有一个与之相关联的指针列表,称之为钩子链表,由系统来维护。

这个列表的指针指向指定的,应用程序定义的。

Hook链的作用

被Hook子程调用的回调函数,也就是该钩子的各个处理子程。当与指定的Hook类型关联的消息发生时,系统就把这个消息传递到Hook子程。一些Hook子程可以只监视消息,或者修改消息,或者停止消息的前进,避免这些消息传递到下一个Hook子程或者目的窗口。最近安装的钩子放在链的开始,而最早安装的钩子放在最后,也就是后加入的先获得控制权。

Hook链怎么使用

Windows 并不要求钩子子程的卸载顺序一定得和安装顺序相反。每当有一个钩子被卸载,Windows 便释放其占用的内存,并更新整个Hook链表。如果程序安装了钩子,但是在尚未卸载钩子之前就结束了,那么系统会自动为它做卸载钩子的操作。

hook链并不单独使用,需要hook的安装与释放

hook安装

使用API函数SetWindowsHookEx()把一个应用程序定义的钩子子程安装到钩子链表中。SetWindowsHookEx函数总是在Hook链的开头安装Hook子程。当指定类型的Hook监视的事件发生时,系统就调用与这个Hook关联的Hook链的开头的Hook子程。

HHOOK SetWindowsHookEx( 
     int idHook,      // 钩子的类型,即它处理的消息类型
     HOOKPROC lpfn,   // 钩子子程的地址指针。如果dwThreadId参数为0
			   // 或是一个由别的进程创建的线程的标识,
			   // lpfn必须指向DLL中的钩子子程。
			   // 除此以外,lpfn可以指向当前进程的一段钩子子程代码。
			   // 钩子函数的入口地址,当钩子钩到任何消息后便调用这个函数。
     HINSTANCE hMod,  // 应用程序实例的句柄。标识包含lpfn所指的子程的DLL。
			   // 如果dwThreadId 标识当前进程创建的一个线程,
			   // 而且子程代码位于当前进程,hMod必须为NULL。
			   // 可以很简单的设定其为本应用程序的实例句柄。
     DWORD dwThreadId // 与安装的钩子子程相关联的线程的标识符。
			   // 如果为0,钩子子程与所有的线程关联,即为全局钩子。
                 );  

CallNextHookEx()

实现传递Hook,具体解释如下:(MSDN定义链接:CallNextHookEx function

在钩子子程中调用得到控制权的钩子函数在完成对消息的处理后,如果想要该消息继续传递,那么它必须调用另外一个 SDK中的API函数CallNextHookEx来传递它,以执行钩子链表所指的下一个钩子子程。这个函数成功时返回钩子链中下一个钩子过程的返回值, 返回值的类型依赖于钩子的类型。

LRESULT CallNextHookEx
			(
				HHOOK hhk;
				int nCode;
				WPARAM wParam;
				LPARAM lParam;
			 ); 
  • hhk为当前钩子的句柄,由SetWindowsHookEx()函数返回。
  • NCode为传给钩子过程的事件代码。
  • wParam和lParam 分别是传给钩子子程的wParam值,其具体含义与钩子类型有关。

这里留一个问题:如果没有CallNextHookEx(),hook机制会怎么样?

卸载Hook

钩子在使用完之后需要用UnHookWindowsHookEx()卸载,否则会造成麻烦。释放钩子比较简单,UnHookWindowsHookEx()只有一个参数。函数原型如下:

UnHookWindowsHookEx
(
	HHOOK hhk;
);

函数成功返回TRUE,否则返回FALSE。

系统钩子和线程钩子

SetWindowsHookEx()函数的最后一个参数决定了此钩子是系统钩子还是线程钩子。

线程勾子用于监视指定线程的事件消息。线程勾子一般在当前线程或者当前线程派生的线程内。

系统勾子监视系统中的所有线程的事件消息。因为系统勾子会影响系统中所有的应用程序,所以勾子函数必须放在独立的动态链接库(DLL) 中。系统自动将包含"钩子回调函数"的DLL映射到受钩子函数影响的所有进程的地址空间中,即将这个DLL注入了那些进程。

几点说明:

(1)如果对于同一事件(如鼠标消息)既安装了线程勾子又安装了系统勾子,那么系统会自动先调用线程勾子,然后调用系统勾子。

(2)对同一事件消息可安装多个勾子处理过程,这些勾子处理过程形成了勾子链。当前勾子处理结束后应把勾子信息传递给下一个勾子函数。

(3)勾子特别是系统勾子会消耗消息处理时间,降低系统性能。只有在必要的时候才安装勾子,在使用完毕后要及时卸载。

思考题

是否可以根据Hook链的先后顺序,来实现AntiHook,欢迎交流。

以上是关于Windows Hook链机制详解的主要内容,如果未能解决你的问题,请参考以下文章

React(五)深入React-Hooks工作机制,原理

14.VisualVM使用详解15.VisualVM堆查看器使用的内存不足19.class文件--文件结构--魔数20.文件结构--常量池21.文件结构访问标志(2个字节)22.类加载机制概(代码片段

Hook函数三步走(SetWindowsHookExUnhookWindowsHookExCallNextHookEx)

Hook函数三步走(SetWindowsHookExUnhookWindowsHookExCallNextHookEx)

区块链科普:一文详解4种共识机制

Hook(钩子技术)基本知识讲解,原理