4.5 MinHook 挂钩技术
MinHook是一个轻量级的Hooking库,可以在运行时劫持函数调用。它支持钩子API函数和普通函数,并且可以运行在32位和64位Windows操作系统上。其特点包括易于使用、高性能和低内存占用。MinHook使用纯汇编语言实现,在安装和卸载钩子时只需要短暂地锁定目标线程,因此对目标线程的影响非常小。
- GitHub地址: https://github.com/TsudaKageyu/minhook
读者可自行下载对应的库文件,本节所使用的是MinHook_133_lib版本,并配置好对应的包含文件以及库目录,如下图所示;

实现修改弹窗提示
如下一段代码其作用是hook MessageBoxA函数,当程序调用MessageBoxA时,会调用MyMessageBoxA函数代替原来的MessageBoxA函数进行处理,而MyMessageBoxA函数会将调用信息改成Hook Inject。
示例中的SetHook函数用于创建并启用hook,使用MH_Initialize进行MinHook库初始化,然后使用MH_CreateHook创建钩子并保存MessageBoxA原函数指针到fpMessageBoxA中,最后使用MH_EnableHook启用hook。而UnHook函数用于禁用和释放hook,使用MH_DisableHook禁用钩子,然后使用MH_Uninitialize释放MinHook库资源。
在DllMain函数中,如果是DLL进程附加事件,则执行SetHook函数,如果是DLL进程分离事件,则执行UnHook函数禁用和释放钩子。
#include <Windows.h>
#include <MinHook.h>
#pragma comment(lib,"libMinHook-x86-v120-md.lib")
typedef int (WINAPI *OldMessageBox)(HWND, LPCSTR, LPCSTR, UINT);
OldMessageBox fpMessageBoxA = NULL;
// 自定义弹窗
int WINAPI MyMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)
{
int ret = fpMessageBoxA(hWnd, "Hook Inject hello lyshark", lpCaption, uType);
return ret;
}
// 安装钩子
void SetHook()
{
if (MH_Initialize() == MB_OK)
{
MH_CreateHook(&MessageBoxA, &MyMessageBoxA, reinterpret_cast<void**>(&fpMessageBoxA));
MH_EnableHook(&MessageBoxA);
}
}
// 卸载钩子
void UnHook()
{
if (MH_DisableHook(&MessageBoxA) == MB_OK)
{
MH_Uninitialize();
}
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
SetHook();
break;
case DLL_PROCESS_DETACH:
UnHook();
break;
}
return TRUE;
}
编译上述代码,使用注入器将hook.dll注入到特定进程内,此时点击弹窗提示会发现弹窗内容已经被替代了,如下图所示;

实现修改窗口标题
一般来说程序中的修改标题功能都是调用SetWindowTextA来实现的,我们可以Hook这个函数对其进行处理后返回新标题即可,当然也可以钩挂住GetWindowTextA函数,同样可以实现标题的修改。
如下代码通过对SetWindowTextA函数进行挂钩,当读者点击设置标题是则触发自定义fpSetWindowTextA函数,该函数内部通过调用自定义标题修改函数实现了将当前软件标题替换为破解版本,并返回给用户。
#include <Windows.h>
#include <MinHook.h>
#pragma comment(lib,"libMinHook-x86-v120-md.lib")
typedef BOOL(WINAPI *OldSetWindowTextA)(HWND, LPCSTR);
OldSetWindowTextA fpSetWindowTextA = NULL;
BOOL WINAPI MySetWindowTextA(HWND hWnd, LPCSTR lpString)
{
BOOL ret = fpSetWindowTextA(hWnd, "破解版本");
return ret;
}
void SetHook()
{
if (MH_Initialize() == MB_OK)
{
MH_CreateHook(&SetWindowTextA, &MySetWindowTextA, reinterpret_cast<void**>(&fpSetWindowTextA));
MH_EnableHook(&SetWindowTextA);
}
}
void UnHook()
{
if (MH_DisableHook(&SetWindowTextA) == MB_OK)
{
MH_Uninitialize();
}
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
SetHook();
break;
case DLL_PROCESS_DETACH:
UnHook();
break;
}
return TRUE;
}
当读者将hook.dll注入到程序中后,我们再次点击设置标题按钮,此时标题将被修改为破解版本,如下图所示;

实现监控进程创建
要实现监控进程创建,我们可以通过MinHook库来钩住explorer.exe程序,通过劫持程序内的CreateProcessW函数,在Windows操作系统中,大部分进程都是由 explorer.exe 进程派生出来的。explorer.exe 是Windows资源管理器的主进程,负责启动和管理用户界面、任务栏、桌面等。
当用户登录到系统后,explorer.exe 进程会自动启动,并成为用户交互的主要界面。在用户打开应用程序、文件夹或执行其他操作时,explorer.exe 进程会根据用户的请求创建新的进程来运行相应的应用程序或执行相应的任务。
通过对该进程进行挂钩,即可实现监控应用层其他进程创建或销毁的目的,读者可自行使用64位库编译下方代码,并注入到explorer.exe进程中,即可实现监控进程的创建功能。
#include <Windows.h>
#include <MinHook.h>
#pragma comment(lib,"libMinHook-x64-v120-md.lib")
typedef int (WINAPI *OldCreateProcessW)(LPCWSTR, LPWSTR, LPSECURITY_ATTRIBUTES, LPSECURITY_ATTRIBUTES, BOOL,
DWORD, LPVOID, LPCWSTR, LPSTARTUPINFOW, LPPROCESS_INFORMATION);
OldCreateProcessW fpCreateProcessW = NULL;
int WINAPI MyCreateProcessW(LPCWSTR lpApplicationName, LPWSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment,
LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation)
{
MessageBoxW(0, lpApplicationName, 0, 0);
int nRetn = fpCreateProcessW(lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes,
bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation);
return nRetn;
}
void SetHook()
{
if (MH_Initialize() == MB_OK)
{
// 参数一: 函数名称
// 参数二: 自定义函数
// 参数三: 原始函数指针
MH_CreateHook(&CreateProcessW, &MyCreateProcessW, reinterpret_cast<void**>(&fpCreateProcessW));
MH_EnableHook(&CreateProcessW);
}
}
void UnHook()
{
if (MH_DisableHook(&CreateProcessW) == MB_OK)
{
MH_Uninitialize();
}
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
SetHook();
break;
case DLL_PROCESS_DETACH:
UnHook();
break;
}
return TRUE;
}
读者可使用x64模式编译上方代码,并将其注入到explorer.exe文件中,至此当有新进程被加载时则会弹出该进程的详细路径信息,如下图所示;

4.5 MinHook 挂钩技术的更多相关文章
- Windows Hook技术
0x01 简介 有人称它为“钩子”,有人称它为“挂钩”技术.谈到钩子,很容易让人联想到在钓东西,比如鱼钩就用于钓鱼.编程技术的钩子也是在等待捕获系统中的某个消息或者动作.钩子的应用范围非常广泛,比如输 ...
- PE格式: 分析IatHook并实现
Ring 3层的 IAT HOOK 和 EAT HOOK 其原理是通过替换IAT表中函数的原始地址从而实现Hook的,与普通的 InlineHook 不太一样 IAT Hook 需要充分理解PE文件的 ...
- 浅谈Hybrid技术的设计与实现第二弹
前言 浅谈Hybrid技术的设计与实现 浅谈Hybrid技术的设计与实现第二弹 浅谈Hybrid技术的设计与实现第三弹——落地篇 接上文:浅谈Hybrid技术的设计与实现(阅读本文前,建议阅读这个先) ...
- EntityFramework Core技术线路(EF7已经更名为EF Core,并于2016年6月底发布)
官方文档英文地址:https://github.com/aspnet/EntityFramework/wiki/Roadmap 历经延期和更名,新版本的实体框架终于要和大家见面了,虽然还有点害羞.请大 ...
- Hook技术
hook钩子: 使用技术手段在运行时动态的将额外代码依附现进程,从而实现替换现有处理逻辑或插入额外功能的目的. 它的技术实现要点有两个: 1)如何注入代码(如何将额外代码依附于现有代码中). 2)如何 ...
- 构建通过 Database.com 提供技术支持的 PhoneGap 应用程序
要求 其他必要产品 Database.com account 用户级别 全部 必需产品 PhoneGap Build 范例文件 Database.Com-PhoneGap-Sample 在这篇文章中, ...
- JIT(动态编译)和AOT(静态编译)编译技术比较
Java 应用程序的性能经常成为开发社区中的讨论热点.因为该语言的设计初衷是使用解释的方式支持应用程序的可移植性目标,早期 Java 运行时所提供的性能级别远低于 C 和 C++ 之类的编译语言.尽管 ...
- API HOOK技术
API HOOK技术是一种用于改变API执行结果的技术,Microsoft 自身也在Windows操作系统里面使用了这个技术,如Windows兼容模式等. API HOOK 技术并不是计算机病毒专有技 ...
- 【Hook技术】实现从"任务管理器"中保护进程不被关闭 + 附带源码 + 进程保护知识扩展
[Hook技术]实现从"任务管理器"中保护进程不被关闭 + 附带源码 + 进程保护知识扩展 公司有个监控程序涉及到进程的保护问题,需要避免用户通过任务管理器结束掉监控进程,这里使用 ...
- 转:Web 测试的创作与调试技术
摘要:学习有关 Visual Studio 2005 Web 测试的更多知识,包括 Web 测试引擎和记录器如何工作,以及如何创建有效的 Web 测试. 本页内容 读者 简介 记录一个 Web 测试 ...
随机推荐
- 【第三方库】从编译到运行,轻松学会gflags库
gflags是Google开源的一个库,可以很方便地定义一些全局变量,并且可以从命令行设置他们的值,广泛应用于各个项目中以及自己平时的开发中.本期参考gflags的官方文档,简单直接介绍下怎么使用这个 ...
- JSP标准标签库(JSTL)个人使用指南
前排提示,本篇仅涉及 JSTL 的配置和简要介绍 JSTL 的 Core 和 Functions 标签库中几个常用的标签.更加详细的内容,博主会贴相应超链接. 注意:本教程使用的 JSTL 1.2,如 ...
- UVA - 12096 :The SetStack Computer
题目大意 用集合模拟计算机操作.每执行完一个操作,输出栈顶的集合大小,操作如下: PUSH:空集合压栈 DUP:将栈顶元素再次压栈 UNION:依次弹栈得a,b,求并集后压栈 INTERSECT:依次 ...
- 畅捷通的 Serverless 探索实践之路
作者:计缘 畅捷通介绍 畅捷通是中国领先的小微企业财税及业务云服务提供商,成立于2010年.畅捷通在2021年中国小微企业云财税市场份额排名第一,在产品前瞻性及行业全覆盖方面领跑市场,位居中国小微企业 ...
- sprint-boot 存储图片的base64
需求:将前端上传的图片转换成base64码发送到后端存储到数据库中(oracle或者mysql) 问题:当图片大小比较大(大概是超过1M)后端接收到的数据就会有错误. 解决方法: sprint-bo ...
- Spring的@Async使用防坑
很多人会直接只用@Async来执行异步操作.但是这里面有一个问题,如果都是用spring的默认实现,是有坑的. 当我们开启 EnableAsync 只有就使用Async来执行异步操作了. 走JDK的动 ...
- 深度学习基础课:使用交叉熵损失函数和Softmax激活函数(下)
大家好~本课程为"深度学习基础班"的线上课程,带领同学从0开始学习全连接和卷积神经网络,进行数学推导,并且实现可以运行的Demo程序 线上课程资料: 本节课录像回放 加QQ群,获得 ...
- Vue tinymce富文本编辑器整合
最近再弄一个后台管理系统,挑选了不少的编辑器,最终选择了tinymce,UI精美,功能模块多,可按需加载配置 vue cli 3 + tinymce5.0版本整合参考:https://liubing. ...
- Java 21新特性-虚拟线程 审核中
本文翻译自国外论坛 medium,原文地址:https://medium.com/@benweidig/looking-at-java-21-virtual-threads-0ddda4ac1be1 ...
- Liunx运维(一)-命令行
一.命令行的开启与推出 1.exit 2.logout 3.ctrl+d 二.命令行提示符 1.#root用户 2.$普通用户 3.~当前用户所在的路径 4.全局配置文件: /etc/profil ...