4.1 应用层Hook挂钩原理分析
InlineHook 是一种计算机安全编程技术,其原理是在计算机程序执行期间进行拦截、修改、增强现有函数功能。它使用钩子函数(也可以称为回调函数)来截获程序执行的各种事件,并在事件发生前或后进行自定义处理,从而控制或增强程序行为。Hook技术常被用于系统加速、功能增强、外挂开发等领域。本章将重点讲解Hook是如何实现的,并手动封装实现自己的Hook挂钩模板。
首先我们来探索一下Hook技术是如何实现的,如下图所示是一个简单的弹窗程序,当读者点击测试弹窗按钮时则会弹出一个MessageBox提示窗口,本次实现目标很简单,通过向目标内注入一个DLL库,实现Hook挂钩住MessageBox弹窗,从而实现去除弹窗的目的;

我们先来看看如何实现Hook思路;
- 1.调用
GetModuleHandle函数来获取到user32.dll模块的基址 - 2.调用
GetProcAddress函数获取到MessageBoxA弹窗的基址 - 3.调用
VirtualProtect来修改MessageBoxA前5个字节内存属性 - 4.计算
Dest - MsgBox - 5重定位跳转地址,并写入JMP跳转指令 - 5.计算
Dest + Offset + 5 = MsgBox +5得到需要跳转回RET的位置 - 6.最后调用
VirtualProtect来将内存属性修改为原始状态
我们载入带有MessageBoxA弹窗的程序,然后在x64dbg上按下Ctrl+G输入MessageBoxA找到我们需要Hook的位置(或者说替换),如下图所示为了完成弹窗转向功能,只需要在函数开头写入jmp无条件跳转指令即可,在32位系统中JMP指令默认占用5个字节,前三条指令恰好5个字节,为了能够保持堆栈平衡,我们需要记下前三条指令,并在自己的中转函数中对其进行补齐。

此外,我们还需要计算出程序的返回地址,使用0x76600BE5 - 0x76600BA0 = 0x45从而得出返回地址就是基址加上0x45,这里的返回地址其实就是返回到原MessageBoxA弹窗的RET 0x10的位置76600BE6,从这里可以看出屏蔽弹窗的原理就是通过中转函数跳过了原始弹窗函数的执行。
由于开头位置被替换为了我们自己的Transfer()函数,当程序中弹窗被调用时默认会路由到我们自己的函数内,首先执行补齐原函数的替换部分,并执行自定义功能区中的增加内容,当执行结束后则通过jmp ebx的方式跳转回原函数的ret 0x10的位置处,从而实现增加功能的目的。这里读者需要注意__declspec(naked)的意思是不添加任何的汇编修饰,当使用了此修饰符时则编译器会只编译我们自己的汇编指令,并不会增加默认的函数开场或离场原语。
__declspec(naked) void Transfer()
{
__asm{
mov edi, edi
push ebp
mov ebp, esp
// 自定义功能区
mov ebx, jump // 取出跳转地址
jmp ebx // 无条件转向
}
}
通过应用上述案例中的知识点我们能很容易的实现对弹窗的替换功能,以下代码中实现了对MessageBoxA弹窗的屏蔽功能,也就是通过跳过弹窗实现流程实现的一种劫持方法,读者可自行编译这段DLL程序,但需要注意一点,读者在编译DLL时应该关闭DLL的DEP以及ASLR模式,否则会出现无法定位的问题。
#include <Windows.h>
#include <stdio.h>
DWORD jump = 0;
// 不添加任何的汇编修饰
__declspec(naked) void Transfer()
{
__asm
{
mov edi, edi
push ebp
mov ebp, esp
mov ebx, jump // 取出跳转地址
jmp ebx // 无条件转向
}
}
// DLL程序入口地址
bool APIENTRY DllMain(HANDLE handle, DWORD dword, LPVOID lpvoid)
{
// 取进程内模块基址
HMODULE hwnd = GetModuleHandle(TEXT("user32.dll"));
DWORD base = (DWORD)GetProcAddress(hwnd, "MessageBoxA");
DWORD oldProtect = 0;
// 将内存设置为可读可写可执行状态,并将原属性保存在oldProtect方便恢复
if (VirtualProtect((LPVOID)base, 5, PAGE_EXECUTE_READWRITE, &oldProtect))
{
DWORD value = (DWORD)Transfer - base - 5; // 计算出需要Hook的地址
jump = base + 0x45; // 计算出返回地址
// 替换头部汇编代码
__asm
{
mov eax, base
mov byte ptr[eax], 0xe9 // e9 = jmp 指令机器码
inc eax // 递增指针
mov ebx, value // 需要跳转到的地址
mov dword ptr[eax], ebx
}
// 恢复内存的原始属性
VirtualProtect((LPVOID)base, 5, oldProtect, &oldProtect);
}
return true;
}
读者可通过注入软件将hook.dll动态链接库注入到进程内,此时我们可以再次观察0x76600BA0位置处的代码片段,读者应该能看到已经被JMP替换,如下图所示;

继续跟进则读者能看到,在跳转指令的下方则是我们自己补齐的汇编指令,此处由于没有做任何事就被返回了,这就导致当读者再次点击弹窗时,弹窗失效;

当我们需要替换程序标题时同样可是使用该方式实现,一般来说程序设置标题会调用SetWindowTextA函数,我们可以拦截这个函数,并传入自定义的窗口名称,从而实现修改指定窗口的标题的目的,代码只是在上面代码的基础上稍微改一下就能实现效果,只要程序使用了该函数设置标题,则可以实现替换的目的;
#include <Windows.h>
#include <stdio.h>
DWORD jump = 0;
// 汇编中转函数
__declspec(naked) bool _stdcall Transfer(HWND hwnd, LPCSTR lpString)
{
__asm
{
mov edi, edi
push ebp
mov ebp, esp
mov ebx, jump
jmp ebx
}
}
// 自己的设置窗体标题函数
bool __stdcall MySetWindowTextA(HWND hwnd, LPCSTR lpString)
{
char * lpText = "LyShark 修改版";
return Transfer(hwnd, lpText);
}
// DLL程序入口地址
bool APIENTRY DllMain(HANDLE handle, DWORD dword, LPVOID lpvoid)
{
HMODULE hwnd = GetModuleHandle(TEXT("user32.dll"));
DWORD base = (DWORD)GetProcAddress(hwnd, "SetWindowTextA");
DWORD oldProtect = 0;
if (VirtualProtect((LPVOID)base, 5, PAGE_EXECUTE_READWRITE, &oldProtect))
{
DWORD value = (DWORD)MySetWindowTextA - base - 5;
jump = base + 5;
__asm
{
mov eax, base
mov byte ptr[eax], 0xe9
inc eax
mov ebx, value
mov dword ptr[eax], ebx
}
VirtualProtect((LPVOID)base, 5, oldProtect, &oldProtect);
}
return true;
}
本文作者: 王瑞
本文链接: https://www.lyshark.com/post/f695c6c3.html
版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
4.1 应用层Hook挂钩原理分析的更多相关文章
- android脱壳之DexExtractor原理分析[zhuan]
http://www.cnblogs.com/jiaoxiake/p/6818786.html内容如下 导语: 上一篇我们分析android脱壳使用对dvmDexFileOpenPartial下断点的 ...
- android脱壳之DexExtractor原理分析
导语: 上一篇我们分析android脱壳使用对dvmDexFileOpenPartial下断点的原理,使用这种方法脱壳的有2个缺点: 1. 需要动态调试 2. 对抗反调试方案 为了提高工作效率, ...
- 阿里系产品Xposed Hook检测机制原理分析
阿里系产品Xposed Hook检测机制原理分析 导语: 在逆向分析android App过程中,我们时常用的用的Java层hook框架就是Xposed Hook框架了.一些应用程序厂商为了保护自家a ...
- IAT Hook 原理分析与代码编写
Ring 3层的 IAT HOOK 和 EAT HOOK 其原理是通过替换IAT表中函数的原始地址从而实现Hook的,与普通的 InlineHook 不太一样 IAT Hook 需要充分理解PE文件的 ...
- Xposed 框架 hook 简介 原理 案例 MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
- 老李推荐:第5章5节《MonkeyRunner源码剖析》Monkey原理分析-启动运行: 获取系统服务引用
老李推荐:第5章5节<MonkeyRunner源码剖析>Monkey原理分析-启动运行: 获取系统服务引用 上一节我们描述了monkey的命令处理入口函数run是如何调用optionP ...
- 消息队列NetMQ 原理分析4-Socket、Session、Option和Pipe
消息队列NetMQ 原理分析4-Socket.Session.Option和Pipe 前言 介绍 目的 Socket 接口实现 内部结构 Session Option Pipe YPipe Msg Y ...
- Wordpress解析系列之PHP编写hook钩子原理简单实例
Wordpress作为全球应用最广泛的个人博客建站工具,有很多的技术架构值得我们学习推敲.其中,最著名最经典的编码技术架构就是采用了hook的机制. hook翻译成中文是钩子的意思,单独看这个词我们难 ...
- 实验八 应用层协议Ⅱ-FTP协议分析
实验八 应用层协议Ⅱ-FTP协议分析 一.实验目的 1.掌握FTP协议的实现原理. 2.了解控制通道和数据通道. 二.实验内容 用WareShark追踪ftp连接. 1.三次握手 2.ftp服务器回发 ...
- Hessian 原理分析
Hessian 原理分析 一.远程通讯协议的基本原理 网络通信需要做的就是将流从一台计算机传输到另外一台计算机,基于传输协议和网络 IO 来实现,其中传输协议比较出名的有 http . tcp . u ...
随机推荐
- C端用户体验度量实战篇-京东快递小程序体验度量全面升级
本文通过介绍体验度量模型升级研究过程.研究方法及研究结果等内容,结合实际C端产品应用,观测新模型运行周期的表现,验证了其在高速发展的业务形态和日益变化的用户需求上的适用性和有效性.我们从体验价值为导向 ...
- PHP sprintf函数 bug
sprintf() 定义和用法 format参数 可能的格式值: %% - 返回一个百分号 % %b - 二进制数 %c - ASCII 值对应的字符 %d - 包含正负号的十进制数(负数.0.正数) ...
- 之江实验室: 如何基于 JuiceFS 为超异构算力集群构建存储层 ?
今天,高性能计算结合人工智能技术正在推动科研创新.例如通过破解水稻基因密码推动作物育种从"试验选优"向"计算选优"发展,在医药领域快速分析分子与蛋白之间的相互作 ...
- 软件开发架构及OSI七层协议
软件开发架构 规定了程序的请求逻辑.功能分块 1.C/S架构 Client:客户端 Server: 服务端 """ 我们使用计算机下载下俩的一个个app本质是各大互联网公 ...
- JUC同步锁原理源码解析二--ReentrantReadWriteLock
JUC同步锁原理源码解析二----ReentrantReadWriteLock 1.读写锁的来源 在开发场景下,对于写操作我们为了保证原子性所以需要上锁,但是对于读操作,由于其不改变数据,只是单纯 ...
- 二分查找法upper版(找大于某个值的最小下标)递归+非递归版
需求:比如说查询一个班级大于60分的最低分等等. 思路与二分法基本相同,只不过是对比的逻辑发生了一些小变化,这里所说的上界就是指大于某个值的最小下标. 当mid < target :说明 tar ...
- BOM和DOM相关API
一.DOM相关API 1. DOM API DOM(Document Object Model)文档对象模型得树形结构 文档对象模型就是一个树形结构,类似于家谱树 html标签里面包裹了所有的文档内容 ...
- quarkus实战之六:配置
欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 本文是<quarkus实战>系列 ...
- 使用gulp.js打包layuiAdmin
安装nvm 在nvm目录下,找到settings.txt,追加以下两行加速nvm(淘宝镜像)node_mirror: https://npm.taobao.org/mirrors/node/npm_m ...
- 利用pytorch准备数据集、构建与训练、保存与加载CNN模型
本文的主要内容是利用pytorch框架与torchvision工具箱,进行准备数据集.构建CNN网络模型.训练模型.保存和加载自定义模型等工作.本文若有疏漏.需更正.改进的地方,望读者予以指正,如果本 ...