Windows核心编程 HOOK

目录

HOOK概述

HOOK API

SetWindowsHookExA 函数(winuser.h)

UnhookWindowsHookEx 函数(winuser.h)

NextHookEx 函数(winuser.h)

局部钩子

全局钩子

为什么全局钩子需要用dll作为过程函数?


HOOK概述

本质:Windows消系统的消息过滤器。

全局钩子原理:将自己的dll注入到别的进程。并不是一开始就注入所有程序。

钩子种类:

  • 局部钩子:仅仅在当前进程下有效
  • 全局钩子:又称为系统钩子,在WIndows所有的进程都有效。

不用种类的钩子有自己的不同的回调函数。

钩子原理:回调函数,操作系统先发给我们,然后在发送给窗口。

系统给w2的消息;正常情况下我们w1是获取不到的,但是可以使用hook技术,将原来的消息先勾到我们(w1)这里,然后再回给系统,系统再重新转发给w2;这样w1就可以看到w2的消息;

HOOK作为注入的技术手段之一,可以利用hook技术,往对方的进程里面注入代码,获取进程相关的信息;作监控的东西,eg:spy++

HOOK API

SetWindowsHookExA 函数(winuser.h)

将应用程序定义的钩子子程安装到钩子链中。您将安装一个钩子子程来监视系统的某些类型的事件。这些事件或者与特定的线程相关联,或者与调用线程在同一桌面中的所有线程相关联。

WINUSERAPI HHOOK WINAPI SetWindowsHookEx(//钩子类型_In_ int idHook,//回调函数地址_In_ HOOKPROC lpfn,//实例句柄(包含有钩子函数)_In_opt_ HINSTANCE hmod,//线程ID,欲勾住的线程(为0则不指定,全局)_In_ DWORD dwThreadId);
  1. 参数1 int idHook:钩子类型 
  2. 参数2 HOOKPROC lpfn:回调函数,每个类型的钩子需匹配各自对应的回调函数
  3. 参数3 HINSTANCE hMod:实例句柄,局部钩子填NULL;全局钩子填dll的模块句柄(钩子的回调函数会填入dll)。使用 GetModuleHandle("Dll1")  获取
  4. 参数4 DWORD dwThreadId:线程ID,局部钩子填自己窗口的线程ID(UI主线程);全局钩子填0会钩系统范围内所有窗口的消息。

参数一:idHook的选项:

价值意义
WH_CALLWNDPROC安装一个钩子子程,在系统将消息发送到目标窗口过程之前监视消息。
WH_CALLWNDPROCRET安装一个钩子子程,在消息被目标窗口过程处理后监视消息。
WH CBT安装一个钩子子程来接收对CBT应用程序有用的通知。
WH_DEBUG安装一个钩子子程,用于调试其他钩子子程。
WH _FOREGROUNDIDLEz安装一个钩子子程,当应用程序的前台线程即将空闲时,将调用这个钩子子程。这个挂钩对于在空闲时间执行低优先级任务很有用。
WH_GETMESSAGE安装一个钩子子程来监视发送到消息队列的消息。
WH_JOURNALPLAYBACK安装一个钩子子程,该钩子子程发送WH日志
WH_JOURNALRECORD安装一个钩子子程,记录发送到系统消息队列的输入消息。这个钩子对于记录宏很有用。
WH_KEYBOARD安装一个钩子子程来监视击键消息。
WH_KEYBOARD_LL安装一个钩子子程来监视低级键盘输入事件。
WH_MOUSE安装一个钩子子程来监视鼠标消息。
WH_MOUSE_LL安装一个钩子子程来监视低级别的鼠标输入事件。
WH_MSGFILTER安装一个钩子子程,监视对话框、消息框、菜单或滚动条中的输入事件所生成的消息。
WH_SHELL安装一个钩子子程来接收对shell应用程序有用的通知。
WH_SYSMSGFILTER安装一个钩子子程,监视对话框、消息框、菜单或滚动条中的输入事件所生成的消息。钩子子程在与调用线程相同的桌面中为所有应用程序监视这些消息。

参数二:lpfn

类型:函数指针
回调函数,钩子拿到这些信息怎么给你,通过回调函数把信息交给你;需要注意,不同钩子的回调函数不一样,可以通过msdn查看;
钩子子程的指针。如果_dwThreadId_参数为零或指定由不同进程创建的线程的标识符,则_lpfn_参数必须指向DLL中的钩子子程。否则,_lpfn_可以指向与当前进程关联的代码中的钩子子程。

参数三:hmod

类型:实例句柄
局部钩子填写NULL;全局钩子填窗口所在模块的句柄,(全局程序会卡)DLL的句柄

参数四:dwThreadId

类型:双字节值
钩子子程要关联的线程的id,要钩的窗口所在的线程所在的id,每个进程的主线程id;

类型:钩子的句柄
如果函数成功,返回值是钩子子程的句柄。
如果函数失败,返回值为NULL。若要获取扩展的错误信息,请调用错误码.


 

UnhookWindowsHookEx 函数(winuser.h)

移除安装在钩子链中的钩子子程钩子函数功能。

BOOL UnhookWindowsHookEx([in] HHOOK hhk
);

参数:[in] hhk
类型:钩子的句柄
要移除的钩子的句柄,SetWindowsHookExA的返回值。此参数是通过以前调用钩子函数

返回值:类型:布尔
如果函数成功,返回值是非零的。
如果函数失败,返回值为零。若要获取扩展的错误信息,请调用错误码

NextHookEx 函数(winuser.h)

将钩子信息传递给当前钩子链中的下一个钩子子程。钩子子程可以在处理钩子信息之前或之后调用这个函数

LRESULT CallNextHookEx([in, optional] HHOOK  hhk,[in]           int    nCode,[in]           WPARAM wParam,[in]           LPARAM lParam
);

参数

[in, optional] hhk
类型:钩子的句柄
该参数被忽略。

[in] nCode
类型:(同Internationalorganizations)国际组织
传递给当前钩子子程的钩子代码。下一个钩子子程使用这个代码来决定如何处理钩子信息。

[in] wParam
类型:WPARAM
这_参数_传递给当前钩子子程的值。此参数的含义取决于与当前挂钩链相关联的挂钩类型。

[in] lParam
类型:参数
这_参数_传递给当前钩子子程的值。此参数的含义取决于与当前挂钩链相关联的挂钩类型。

返回值
类型:LRESULT
该值由链中的下一个钩子子程返回。当前钩子子程也必须返回这个值。返回值的含义取决于钩子的类型。

局部钩子

只能钩自己的窗口

// MFC基于对话框项目
HHOOK g_hHook;
// 键盘回调函数
LRESULT CALLBACK KeyboardProc(_In_ int    code,_In_ WPARAM wParam,_In_ LPARAM lParam
)
{// 特殊检查if (code < 0){return	CallNextHookEx(g_hHook, code, wParam, lParam);}CString strFmt;strFmt.Format("HT:%c", wParam);OutputDebugString(strFmt);return	CallNextHookEx(g_hHook, code, wParam, lParam);
}// 局部Hook 安装
void CHookTestDlg::OnBnClickedButton1()
{// 设置钩子g_hHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, NULL, GetCurrentThreadId());if (g_hHook == NULL){AfxMessageBox("局部钩子安装失败");}
}// 局部Hook 卸载
void CHookTestDlg::OnBnClickedButton3()
{UnhookWindowsHookEx(g_hHook);	// 卸载钩子
}
执行结果

全局钩子

钩子的回调函数会填入DLL,以便按需注入

// 动态链接库项目 HookDll.cpp代码
HHOOK g_hHook;
LRESULT CALLBACK MyKeyboardProc(int code,       // hook codeWPARAM wParam,  // virtual-key codeLPARAM lParam   // keystroke-message information
)
{if (code < 0){return CallNextHookEx(g_hHook, code, wParam, lParam);}char szBufff[MAXBYTE];wsprintf(szBufff, "HT:%c pid:%d", wParam, GetCurrentProcessId());OutputDebugString(szBufff);return CallNextHookEx(g_hHook, code, wParam, lParam);
}__declspec(dllexport) BOOL InstallHook()
{g_hHook = SetWindowsHookEx(WH_KEYBOARD,MyKeyboardProc,GetModuleHandle("HookDll"),0);if (g_hHook != NULL){return TRUE;}return FALSE;
}__declspec(dllexport) VOID UnInstallHook()
{UnhookWindowsHookEx(g_hHook);
}
// 使用dll的MFC对话框项目代码
__declspec(dllimport) BOOL InstallHook();
__declspec(dllimport) VOID UnInstallHook();
#pragma comment(lib, "./Debug/HookDll.lib")
// 安装全局钩子
void CHookTestDlg::OnBnClickedButton2()
{if (!InstallHook()){AfxMessageBox("安装全局钩子失败");}
}
// 卸载全局钩子
void CHookTestDlg::OnBnClickedButton4()
{UnInstallHook();
}

或者填写def文件

为什么全局钩子需要用dll作为过程函数?

在别的程序运行过程函数监听消息。

全局钩子在安装钩子后,如果安装钩子的程序关闭,目标进程的dll也会自动卸载。

  1. 安装了同一时间的全局钩子和局部钩子,系统优先调用局部钩子,然后调用全局钩子。
  2. 安装多个钩子处理过程,形成钩子链。当钩子结束后赢吧钩子信息传递给下一个钩子函数。钩子链式栈结构,最后安装的,最先获得控制权。
  3. 全局钩子会消耗消息处理的时间,降低系统性能,所以全局钩子并不是全部注入到所有程序中,而是在发生消息事件的时候,才将dll注入到目标程序中安装钩子。
  4. 安装的钩子需要释放,安装钩子的主程序关闭,其他程序的钩子也会自动释放。
  5. 在键盘钩子回调函数中,修改wparam的值不会影响目标进程的值。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/233747.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【BSP开发经验】uboot gpl框架开发经验

文章目录 uboot_gpl 隔离 的目的uboot_gpl 隔离基本原理uboot_gpl 基本框架uboot_gpl 适配新平台的方式uboot 添加hikcmd功能适配调试步骤 链接脚本语法链接脚本的格式链接脚本的简单示例设置入口点&#xff08;entry&#xff09;设置输出文件名处理目标文件格式的命令uboot_gp…

数据库应用:MongoDB 文档与索引管理

目录 一、理论 1.MongoDB文档管理 2.MongoDB索引管理 二、实验 1.MongoDB文档管理 2.MongoDB索引管理&#xff08;索引添加与删除&#xff09; 3.MongoDB索引管理&#xff08;全文索引&#xff09; 4.MongoDB索引管理&#xff08;多列索引&#xff09; 5.MongoDB索引管…

教育企业CRM选择技巧

教育行业的发展一波三折&#xff0c;要想在激烈的赛道脱颖而出&#xff0c;就需要有一套有效的CRM系统&#xff0c;来帮助教育机构提升招生效率、增加学员留存、提高教学质量。下面说说&#xff0c;教育企业选择CRM系统要具备的四大功能。 1、招生管理功能 教育机构的首要目标…

珠宝模具3d仿真沉浸式交互展示更易分享传播

3D云展会经过近几年的蓬勃发展&#xff0c;迅速受到参展企业和客户的多方认可和支持&#xff0c;那么随着市场再度恢复&#xff0c;各种展会络绎不绝&#xff0c;想要快速打造一个逼真的线上3D云展会成为企业刚需。3D云展会线上搭建平台是web3d开发公司深圳华锐视点根据领先的三…

蓝桥杯每日一题2023.11.29

题目描述 #include <stdio.h> #include <string.h>void StringInGrid(int width, int height, const char* s) {int i,k;char buf[1000];strcpy(buf, s);if(strlen(s)>width-2) buf[width-2]0;printf("");for(i0;i<width-2;i) printf("-"…

socket.io介绍

1. 使用的技术 Socket.IO 是一个封装了 Websocket、基于 Node 的 JavaScript 框架&#xff0c;包含 client 的 JavaScript 和 server 的 Node。其屏蔽了所有底层细节&#xff0c;让顶层调用非常简单。 另外&#xff0c;Socket.IO 还有一个非常重要的好处。其不仅支持 WebSocket…

STM32 外部中断配置与中断函数设计

单片机学习 目录 文章目录 一、外部中断配置步骤 1.1配置RCC 1.2配置GPIO 1.3配置AFIO 1.4配置EXTI 1.5配置NVIC 二、中断函数设计 总结 一、外部中断配置步骤 第一步&#xff1a;配置RCC&#xff0c;把涉及外设的时钟打开。第二步&#xff1a;配置GPIO&#xff0c;选择…

Linux | Ubuntu设置 netstat(网络状态)

netstat命令用于显示与IP、TCP、UDP和ICMP协议相关的统计数据&#xff0c;一般用于检验本机各端口的网络连接情况。netstat是在内核中访问网络及相关信息的程序&#xff0c;它能提供TCP连接&#xff0c;TCP和UDP监听&#xff0c;进程内存管理的相关报告。 1.netstat的安装 搜…

选择合适的企业邮箱供应商的策略与技巧

如果您的公司是一个业务遍布全球的组织&#xff0c;选择合适的企业邮箱供应商将是一个重要的决策。 以下是在选择全球适用的企业邮箱供应商时应考虑的关键因素&#xff1a; 全球覆盖和数据中心位置&#xff1a;确保企业邮箱供应商在您业务遍及的国家和地区均具备良好的服务覆盖…

原来字节跳动这么容易就能进····

“字节是大企业&#xff0c;是不是很难进去啊&#xff1f;” “在字节做软件测试&#xff0c;能得到很好的发展吗&#xff1f; 一进去就有12.5K&#xff0c;其实也没有想的那么难” 直到现在&#xff0c;心情都还是无比激动&#xff01; 本人211非科班&#xff0c;之前在字节…

基于Java SSM框架+Vue实现垃圾分类网站系统项目【项目源码+论文说明】计算机毕业设计

基于java的SSM框架Vue实现垃圾分类网站系统演示 摘要 本论文主要论述了如何使用JAVA语言开发一个垃圾分类网站 &#xff0c;本系统将严格按照软件开发流程进行各个阶段的工作&#xff0c;采用B/S架构&#xff0c;面向对象编程思想进行项目开发。在引言中&#xff0c;作者将论述…

三、Linux高级命令

目录 1、重定向命令 1.1 重定向 > 1.2 重定向 >> 该章节的所有操作都在/export/data/shell目录进行&#xff0c;请提前创建该目录。 mkdir -p /export/data/ 1、重定向命令 1.1 重定向 > Linux 允许将命令执行结果重定向到一个文件&#xff0c;本应显示在…