Windows HOOK钩子技术_系统钩子-程序员宅基地

技术标签: c++  MFC笔记  

Windows HooK钩子技术是指基于Windows中窗口的程序的消息处理机制,对系统或者进程中的消息进行截获和处理,并将截获和处理的消息在重新处理和发送,使其可以实现不同的功能。

钩子技术分为系统钩子技术和线程钩子技术
系统钩子:是用于监视系统中的消息的钩子技术,因为系统钩子会影响系统中所有的应用程序,所以钩子函数必须放在独立的动态链接库(DLL) 中。做好之后使用其他程序将钩子挂载到系统的进程中。
线程钩子:指的是对指定线程进行监视。

钩子原理
在使用钩子技术的时候,WINDOWS会先在内存中创建一个数据结构,该数据结构包含了钩子的相关信息,然后把该结构体加到已经存在的钩子链表中去。新的钩子将加到老的前面。当系统触发产生一个消息时,如果安装的是一个线程钩子,您进程中的钩子函数将被调用。如果是一个系统钩子,系统就必须把钩子函数插入到其它进程的地址空间,要做到这一点要求钩子函数必须在一个动态链接库中,所以如果您想要使用系统钩子,就必须把该钩子函数放到动态链接库中去。
当然有两个例外:工作日志钩子和工作日志回放钩子。这两个钩子的钩子函数必须在安装钩子的线程中。原因是:这两个钩子是用来监控比较底层的硬件事件的,既然是记录和回放,所有的事件就当然都是有先后次序的。所以如果把回调函数放在DLL中,输入的事件被放在几个线程中记录,所以我们无法保证得到正确的次序。故解决的办法是:把钩子函数放到单个的线程中,譬如安装钩子的线程。
几点需要说明的地方:
  (1) 如果对于同一消息同时安装了线程钩子和系统钩子,那么系统会自动先调用线程钩子,然后调用系统钩子。
  (2) 对同一消息可安装多个钩子处理过程,这些钩子处理过程形成了钩子链。当前钩子处理结束后应把钩子信息传递给下一个钩子函数。而且最近安装的钩子放在链的开始,而最早安装的钩子放在最后,也就是后加入的先获得控制权。
  (3) 钩子特别是系统钩子会消耗消息处理时间,降低系统性能。只有在必要的时候才安装钩子,在使用完毕后要及时卸载。
在这里插入图片描述

钩子类型:

WH_CALLWNDPROC 监视到达窗口前的消息
WH_CALLWNDPROCRET 监视窗口处理后的消息
WH_DEBUG 监视系统调用其他HOOK关联的HOOK子程
WH_GETMESSAGE 监视发送到窗体消息队列里的消息
WH_JOURNALPLAYBACK 全局HOOK,可以插入消息到消息队列
WH_JOURNALRECORD 全局HOOK,监视输入事件(键盘、鼠标等)
WH_KEYBOARD 键盘钩子
WH_MOUSE 鼠标钩子
WH_MSGFILTER 监视菜单、滚动条、消息框、对话框消息和切换窗口的组合键 (Alt+Tab等)
WH_SHELL 接收系统中重要的通知(如窗口被产生、摧毁等)

使用的函数:

1、SetWindowsHookEx()安装钩子
SetWindowsHookEx函数是微软提供给程序开发人员进行消息拦截的一个API。不过,他的功能不仅可以用作消息拦截,还可以进行DLL注入。
SetWindowsHookEx原型声明如下:


HHOOK  SetWindowsHookEx(
		int idHook, 
		HOOKPROC lpfn, 
		HINSTANCE hmod,
		DWORD dwThreadId
		);
  • idHook:指示将要安装的挂钩处理过程的类型。例如,idHook为“WH_CALLWNDPROC”时代表安装一个挂钩处理过程,在系统将消息发送至目标窗口处理过程之前对该消息进行监视。
  • lpfn:指向相应的挂钩处理过程(钩子函数)。例:LRESULT CALLBACK GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam)
  • hmod:指示了一个DLL句柄。该DLL包含参数lpfn所指向的挂钩处理过程
  • dwThreadId:指示了一个线程标示符,挂钩处理过程与线程相关。若此参数值为0,则该挂钩处理过程与所有现存的线程相关。
    如果去掉消息钩子,可以用UnhookWindowsHookEx函数
  • 返回值:若此函数执行成功,则返回值就是该挂钩处理过程的句柄;若此函数执行失败,则返回值为NULL(0).若想获得更多错误信息,请调用GetLastError函数.

2、UnhookWindowsHookEx(卸载钩子函数)

BOOL WINAPI UnhookWindowsHookEx( HHOOK hhk);
  • hhk要删除的钩子的句柄。这个参数是上一个函数SetWindowsHookEx的返回值.
  • 返回值 类型: BOOL 如果函数成功,返回值为非零值。 如果函数失败,返回值为零。
    要获得更多的错误信息,调用GetLastError函数.

3、CallNextHookEx()
将钩子信息传递到当前钩子链中的下一个子程,一个钩子程序可以调用这个函数之前或之后处理钩子信息

LRESULT WINAPI CallNextHookEx(
	HHOOK hhk, 
	int nCode, 
	WPARAM wParam, 
	LPARAM lParam); 
  • hhk:当前钩子的句柄此参数将被忽略。
  • nCode [in]说明:钩子代码;
    就是给下一个钩子要交待的钩传递给当前Hook过程的代码。下一个钩子程序使用此代码,以确定如何处理钩的信息。
  • wParam[in] 说明:要传递的参数;
    由钩子类型决定是什么参数wParam参数值传递给当前Hook过程。此参数的含义取决于当前的钩链与钩的类型。
  • lParam[in]说明:要传递的参数;
    由钩子类型决定是什么参数lParam的值传递给当前Hook过程。此参数的含义取决于当前的钩链与钩的类型。
  • 返回值类型:LRESULT
    返回这个值链中的下一个钩子程序。当前Hook过程也必须返回该值。返回值的含义取决于钩型。有关详细信息,请参阅个人钩子程序的描述

钩子技术的实现例程

线程钩子

  • 定义变量
HHOOK g_hGetMsgHooK;//定义一个钩子句柄,在使用安装钩子函数之后,
  • 1、创建钩子函数
LRESULT CALLBACK GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    
	MSG* pMsg = (MSG*)lParam;
	if (pMsg->message == WM_KEYDOWN || pMsg->message == WM_KEYUP)
	{
    
		if (pMsg->wParam == 0x41)
		{
    
			pMsg->wParam = 0x42;
		}
	}
	return CallNextHookEx(g_hGetMsgHooK,nCode,wParam,lParam);
}
  • 2、安装钩子
void C钩子技术_局部Dlg::OnBnClickedInstall()
{
    
	//安装钩子
	g_hGetMsgHooK = SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, NULL, GetCurrentThreadId());
}

  • 3、卸载钩子
void C钩子技术_局部Dlg::OnBnClickedRemove()
{
    
	// 取消钩子
	UnhookWindowsHookEx(g_hGetMsgHooK);
}

系统钩子

  • 1、创建钩子DLL连接库
#include <Windows.h>
#include "kbh.h"
#include <stdio.h>

static HINSTANCE  hInst;//定义一个全局的变量
static FILE *f1;
static HHOOK hhook;
//这是一个dll动态链接库的入口
int WINAPI DllMain(HINSTANCE hInstance ,DWORD fdwReason,PVOID pvReserved)
{
    
	switch (fdwReason)
	{
    
	case DLL_PROCESS_ATTACH:
		hInst = hInstance;
		break;
	}
	return TRUE;
}

//钩子函数
LRESULT CALLBACK KeyboardProc(int nCode,WPARAM wParam,LPARAM lParam)
{
    
	char ch;
	WORD w;
	UINT scan = 0;

	if (((DWORD)lParam & 0x40000000) && (HC_ACTION == nCode))
	{
    
		if ((wParam == VK_SPACE) || (wParam == VK_RETURN) || (wParam >= 0x2f) && (wParam <= 0x100))
		{
    
			f1 = fopen("D:\\export.txt","a+");
			if (wParam == VK_RETURN)
			{
    
				ch = '\n';
				fwrite(&ch,1,1,f1);
			}
			else
			{
    
				BYTE ks[256];
				GetKeyboardState(ks);
				ToAscii(wParam,scan,ks,&w,0);
				ch = (char)w;
				fwrite(&ch,1,1,f1);
			}
			fclose(f1);
		}
	}
	return CallNextHookEx(hhook, nCode, wParam, lParam);
}
EXPORT void SetKbHookyxd(void)
{
    
	hhook = SetWindowsHookEx(WH_KEYBOARD,(HOOKPROC)KeyboardProc,hInst,(DWORD)NULL);
}
  • 2、创建安装函数
// Start_HOOK.cpp : 定义应用程序的入口点。
//

#include "stdafx.h"
#include "Start_HOOK.h"
#include "kbh.h"
#pragma comment(lib,"KBH.lib")

int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPTSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    
	
 	// TODO:  在此放置代码。
	MSG msg;
	SetKbHookyxd();
	// 主消息循环: 
	while (GetMessage(&msg, NULL, 0, 0))
	{
    
		
			TranslateMessage(&msg);
			DispatchMessage(&msg);
	}

	return (int) msg.wParam;
}


版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_43812868/article/details/109275872

智能推荐

Maven安装配置及在idea中配置_maven安装到c盘-程序员宅基地

文章浏览阅读189次。一、什么是 Maven1. Maven是Apache下的一个纯java开发的开源项目,它是一个项目管理工具,使用maven对java项目进行构建、依赖管理。2. 通俗的来说Maven就是一款帮助程序员构建项目的工具,我们只需要告诉Maven需要哪些Jar 包,它会帮助我们下载所有的Jar,极大提升开发效率二、Maven安装及配置1. Maven本地安装选择二进制的压缩包下载完成后,解压到D盘这是我的路径D:\localRepository\apache-ma..._maven安装到c盘

Java核心技术卷一笔记(二)Java 的基本程序设计结构-程序员宅基地

文章浏览阅读46次。Java命名规范1.区别大小。2.命名必须以字母开头,后面可以跟数字或字母或者下划线的任意长度的组合,但是不能使用Java保留字。3.命名采用驼峰原则:类名或接口名:开头大写,之后的每个单词首字母大写方法名和变量名:第二个单词开始首字母大写常量名:常量名全部字母都大写注释...

升级java1.8及ssh版本中碰到的问题(三)_升级jdk1.8加密数组越界-程序员宅基地

文章浏览阅读916次。……再接前文六、Not an managed type: class java.lang.Object。解决方法:自己定义的泛型非实现的Dao类前,加@NoRepositoryBean这个是参考了下面这篇贴子:http://stackoverflow.com/questions/23812458/spring-data-not-an-managed-type-class-java-la_升级jdk1.8加密数组越界

Nginx 配置详解 | 宝塔面板配置静态资源服务器 配置小游戏远程资源服务器_微信小游戏开启静态资源服务器-程序员宅基地

文章浏览阅读4.5k次。获取更多笔记和源码公众号:CocosCreator笔记导读安装宝塔安装 Nginx配置Nginx配置H5 游戏配置小游戏远程资源1准备云服务器腾讯云:https://url.cn/53X4QsE阿里云:https://www.aliyun.com/sale-season/2..._微信小游戏开启静态资源服务器

图像纠正技术的发展:从光影纠正到三维纠正-程序员宅基地

文章浏览阅读828次,点赞24次,收藏19次。1.背景介绍图像纠正技术是计算机视觉领域的一个重要研究方向,主要关注于对图像中的噪声、光影、椒盐噪声等不良信息进行处理,以提高图像的质量和可用性。随着计算机视觉技术的不断发展,图像纠正技术也不断发展和进步,从初期的光影纠正、噪声纠正等,逐渐发展到了三维纠正等高级应用。本文将从以下六个方面进行全面的介绍和分析:背景介绍、核心概念与联系、核心算法原理和具体操作步骤以及数学模型公式详细讲解、具体代码...

buck电路尖峰电压分析_DC-DC电路介绍之buck电路-程序员宅基地

文章浏览阅读2.5k次。在开关稳压电源中,直流变换器中的功率晶体管工作在开关状态。目前开关电源的工作频率在几百kHz,甚至已到了MHz量级。下图是DC-DC开关电源变换器的原理图:开关电源有很多种,这里介绍最传统的脉宽调制(PWM)技术,具体介绍绍Buck,Boost, Buck-Boost, Cuk这几种DC-DC变换的原理。PWM是一种功率控制方式,不同占空比的脉冲具有不同的直流分量,所以负载变化时,根据调整输出脉冲..._dc/dc模块开关电输出有尖峰电压

随便推点

关于面向对象、面向过程区别,我的看法_我觉得面向-程序员宅基地

文章浏览阅读2k次,点赞25次,收藏21次。表示你把一个概念学懂了、了解透彻了的最简单检验标准就是—你能不能让一个门外汉也听懂个60%?为了尝试给出最简单的解释,让门外汉听懂,我和同事采用各种表述,最终都不太满意。后来无意间看到网络上有人回答“面向对象就是面向空间,面向过程就是面向时间”,我当时觉得惊为天人。(不过对不起我当时太兴奋了,没有及时记录下来出处,要不然一定留下您的署名)我自己再总结一下,“面向对象就是面向空间,注重整体架构;面向过程就是面向时间,注重各个时间点具体任务”→我觉得这句话很精髓,外行也能大致懂个七七八八吧,不知道大家觉得呢_我觉得面向

使用ASIHTTPRequest和ASIDownloadCache实现本地缓存-程序员宅基地

文章浏览阅读404次。为了节约流量,同时也是为了更好的用户体验,目前很多应用都使用本地缓存机制,其中以网易新闻的缓存功能最为出色。我自己的应用也想加入本地缓存的功能,于是我从网上查阅了相关的资料,发现总体上说有两种方法。一种是自己写缓存的处理,一种是采用ASIHTTPRequest中的ASIDownloadCache。根据我目前的技术水平和时间花费,我果断选择了后者,事实证明效果也很不错。下面说一下实现方法:

容器的end()方法-程序员宅基地

文章浏览阅读195次。容器的end()方法,返回一个迭代器,需要注意:这个迭代器不指向实际的元素,而是表示末端元素的下一个元素,这个迭代器起一个哨兵的作用,表示已经处理完所有的元素。因此,在查找的时候,返回的迭代器,不等于end(),说明找到了目标。等于end(),说明检查了所有元素,没有找到目标。转载于:https://www.cnblogs.com/nzbbody/p/3409317.html..._容器非实例化end

数据库(Database)介绍_数据库(database),简而言之可视为电子化的文件柜——存储电子文件的处所,用户可以-程序员宅基地

文章浏览阅读2.7k次。什么是数据库? 数据库,简而言之可视为电子化的文件柜——存储电子文件的处所,用户可以对文件中的数据运行新增、截取、更新、删除等操作。 所谓“数据库”系以一定方式储存在一起、能予多个用户共享、具有尽可能小的冗余度、与应用程序彼此独立的数据集合。什么是数据库管理系统? 数据库管理系统(英语:Database Management System,简称DBMS)是为管理数据库而设计的电脑软件系统,一般具有存储、截取、安全保障、备份等基础功能。数据库管理系统可以依据..._数据库(database),简而言之可视为电子化的文件柜——存储电子文件的处所,用户可以

anaconda创建、删除、退出环境_删除annacond下环境-程序员宅基地

文章浏览阅读3.3w次,点赞10次,收藏46次。Anaconda创建环境:// 下面是创建python=3.7版本的环境,取名叫py37conda create -n py36 python=3.7删除环境conda remove -n py36 --all激活环境//下面这个py37是个环境名activate py37退出环境deactivate..._删除annacond下环境

element ui 日期的可选范围禁用_element ui 时间组件 指定日期范围内的可用 其他禁用-程序员宅基地

文章浏览阅读305次。<el-date-picker v-model="value" type="daterange" start-placeholder="开始日期" :picker-options="pickerOptions" end-placeholder="结束日期"> </el-date-picker>data() { var vu_element ui 时间组件 指定日期范围内的可用 其他禁用

推荐文章

热门文章

相关标签