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挂钩原理分析的更多相关文章

  1. android脱壳之DexExtractor原理分析[zhuan]

    http://www.cnblogs.com/jiaoxiake/p/6818786.html内容如下 导语: 上一篇我们分析android脱壳使用对dvmDexFileOpenPartial下断点的 ...

  2. android脱壳之DexExtractor原理分析

    导语: 上一篇我们分析android脱壳使用对dvmDexFileOpenPartial下断点的原理,使用这种方法脱壳的有2个缺点: 1.  需要动态调试 2.  对抗反调试方案 为了提高工作效率, ...

  3. 阿里系产品Xposed Hook检测机制原理分析

    阿里系产品Xposed Hook检测机制原理分析 导语: 在逆向分析android App过程中,我们时常用的用的Java层hook框架就是Xposed Hook框架了.一些应用程序厂商为了保护自家a ...

  4. IAT Hook 原理分析与代码编写

    Ring 3层的 IAT HOOK 和 EAT HOOK 其原理是通过替换IAT表中函数的原始地址从而实现Hook的,与普通的 InlineHook 不太一样 IAT Hook 需要充分理解PE文件的 ...

  5. Xposed 框架 hook 简介 原理 案例 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  6. 老李推荐:第5章5节《MonkeyRunner源码剖析》Monkey原理分析-启动运行: 获取系统服务引用

    老李推荐:第5章5节<MonkeyRunner源码剖析>Monkey原理分析-启动运行: 获取系统服务引用   上一节我们描述了monkey的命令处理入口函数run是如何调用optionP ...

  7. 消息队列NetMQ 原理分析4-Socket、Session、Option和Pipe

    消息队列NetMQ 原理分析4-Socket.Session.Option和Pipe 前言 介绍 目的 Socket 接口实现 内部结构 Session Option Pipe YPipe Msg Y ...

  8. Wordpress解析系列之PHP编写hook钩子原理简单实例

    Wordpress作为全球应用最广泛的个人博客建站工具,有很多的技术架构值得我们学习推敲.其中,最著名最经典的编码技术架构就是采用了hook的机制. hook翻译成中文是钩子的意思,单独看这个词我们难 ...

  9. 实验八 应用层协议Ⅱ-FTP协议分析

    实验八 应用层协议Ⅱ-FTP协议分析 一.实验目的 1.掌握FTP协议的实现原理. 2.了解控制通道和数据通道. 二.实验内容 用WareShark追踪ftp连接. 1.三次握手 2.ftp服务器回发 ...

  10. Hessian 原理分析

    Hessian 原理分析 一.远程通讯协议的基本原理 网络通信需要做的就是将流从一台计算机传输到另外一台计算机,基于传输协议和网络 IO 来实现,其中传输协议比较出名的有 http . tcp . u ...

随机推荐

  1. CHS、LAB地址

    CHS地址 CHS地址指的是柱面(Cylinder).磁头(Head).扇区(Sector)三个参数组成的地址,是用来表示磁盘上每个扇区位置的一种方式. 物理扇区号 = ((柱面号×磁头数) + 磁头 ...

  2. k8s实战案例之部署redis单机和redis cluster

    1.在k8s上部署redis单机 1.1.redis简介 redis是一款基于BSD协议,开源的非关系型数据库(nosql数据库),作者是意大利开发者Salvatore Sanfilippo在2009 ...

  3. Vue3从入门到精通(二)

    vue3 侦听器 在Vue3中,侦听器的使用方式与Vue2相同,可以使用watch选项或$watch方法来创建侦听器.不同之处在于,Vue3中取消了immediate选项,同时提供了新的选项和API. ...

  4. JUC同步锁原理源码解析六----Exchanger

    JUC同步锁原理源码解析六----Exchanger Exchanger Exchanger的来源 A synchronization point at which threads can pair ...

  5. 数据库varchar和tinyint和int和java实体属性的对应关系的学习

    大家好,最近做项目碰到群里小伙伴的对于项目中用到的这几个类型,自己的java实体类属性该用什么类型干到困惑,于是乎,我决定为大家解密! 相信我,绝对干货,看完了,工资+200~哈哈哈,扯远了,闲话不对 ...

  6. 重新初始化k8s集群

    执行如下命令,所有节点都执行 kubeadm reset 初始化集群,仅在master(centos01)上执行 [root@centos01 opt]# kubeadm init --apiserv ...

  7. Java版人脸跟踪三部曲之二:开发设计

    如何开发Java版人脸跟踪应用?本篇给出了设计大纲,并解释了相关的重要知识点 欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599 ...

  8. 简约版八股文(day1)

    Java基础 面向对象的三大基本特征 封装:将一些数据和对这些数据的操作封装在一起,形成一个独立的实体.隐藏内部的操作细节,并向外提供一些接口,来暴露对象的功能. 继承:继承是指子类继承父类,子类获得 ...

  9. mac Typora最新版逆向破解

    0x00 Typora是一款强大的markdown编辑器,它可以让你轻松地写出美观的文档.但是其一直是不开源的,而且现在也已经开始收费了.所以本着学习探索的精神去逆向看看- 0x01 众所周知Typo ...

  10. [Spring+SpringMVC+Mybatis]框架学习笔记(六):Spring_AspectJ实现AOP

    第6章 Spring_AspectJ实现AOP 6.1 什么是AspectJ 对于AOP的这种编程思想,有很多框架或者组件进行了实现,spring实现AOP就是其中的一种. AspectJ也实现了AO ...