x64 InlineHook 黑魔法

网上x64 InlineHook资料挺少的,我翻阅文章找到个不错的x64 InlineHook方法,在此整理成笔记如有错误欢迎指正。

为什么不能用X86 的HOOK方式?

像32位JMP跳转只需要5字节即可,但是在64位进程中情况确截然不同。

32位进程寻址能力为4字节,而64位进程寻址能力变成了8字节,然而64位汇编中所有的跳转直接寻址只支持4字节。

原理:jmp + rip 进行寻址6字节方式跳转

在64位程序中. 可以使用rip寄存器了. 而32位不可以.32位下想要改变 eip的值. 无非就是 jmp + call才可以改变.64位可以使用下面

;其核心方法类似
jmp qword ptr [rip] ;//机器码0xFF 0x25 0x00 0x00 0x00 0x00

在上面可以看到他有固定的机器码,0xFF,0x25.而后面的内容都是0他就会自动定位到rip也就是下一句的地址,那么我们就可以来构造,0xFF,0x25,0x00,0x00,0x00,0x00.把这个0x00 4字节替换成我们的一块空内存地址,然后再空内存地址里面写入8字节地址(目标地址)就能实现一个远跳转了,下面是jmp rip的整个流程。

偏移 = 临时地址x - 源地址 - 6
0xFF 0x25 偏移(4字节)
临时地址x(内容) = 目标地址
;比32位HOOK 多出了一个临时地址x而已,其他目的地址,源地址都差不多所以可以构造Inline Hook

只不过我们不能直接把目标函数地址写到rip里面,需要一系列手段来计算出来,大概分下面几个步骤:

  • 找一块空的内存(或者全局变量)
  • 计算偏移:空的内存地址 - 需要HOOK处位置地址 - 6
  • 修改需要HOOK位置处的汇编代码jmp qword ptr [] //6字节
  • 将空的内存处写入字节码,(你的HOOK函数地址)//8字节

手动InlineHook

知道原理后我们就可以来构造了,一共分这4个东西。

  • 临时地址x
  • 计算偏移
  • 源地址(内容 )= jmp + rip + 偏移
  • 临时地址x(内容) = 目标地址

临时地址x(找一块空内存)

打开x64dbg 然后随便载入一个64位程序,接着ctrl+b输入很多0然后点击确定,跳转到0的地址处,然后记下地址0x00007FF7094B7674

计算偏移

我们先找到我们想要hook的地址,这里随便这一个就假如是下面这位置吧,然后记一下地址0x00007FF7094B63DE

计算偏移:0x00007FF7094B7674 - 0x00007FF7094B63DE - 6= 0x1290,记下偏移。

源地址(内容 )= jmp + rip + 偏移(HOOK代码)

修改成如下格式jmp qword ptr [rip +x]的格式,注意你不能直接汇编改[偏移],要不然会变成下面这种情况。

改成这样子是不对的,起不到任何效果。

我们说过我们是要改rip,而改rip有固定机器码,所以我们得根据上面讲过的0xFF 0x25的方式来修改我们的rip。

改为后他会自动变成jmp qword ptr ds:[0x7FF7094B7674],而这个0x7FF7094B7674就是我们之前找的空内存的地址。

临时地址x(内容) = 目标地址

最后一步才是真正的改rip,也就是利用rip [0+x]的寻址方式,x处的地址机器码要改成我们想要把之前HOOK处的函数改成自己想要让他执行处地址的。

废话不多说,我们先随便找一处想让程序跳到的地址0x00007FF7094B644E,我们想让程序知道到hook处的地方后直接跳到pop rbp这位置。

ctrl +g 跳转到空内存的地址处0x7FF7094B7674

修改二进制,改成0x00007FF7094B644E这个地址(想让hook处的地方跳到这里的地址),注意大小端转换

最终效果

当我们点击hook处的地方,从这个流程图箭头处我们就能看到效果,他会直接jmp到我们想要改变他流程后的地址,即pop rbp

代码InlineHook

例子说明

这里来下一个demo,大概程序运行后会把本来的my_func函数内容替换成fake_func函数内容来测试HOOK效果。

int fake_func()
{
MessageBox(NULL, L"fake function!", NULL, NULL);
return 0;
} int my_func()
{
MessageBox(NULL, L"Hello,World!", NULL, NULL);
return 1;
}

构造InlineHook

Inline HOOK代码的构造

临时地址x = 自己定义一个全局变量x
源地址 = my_func
目标地址 = fake_func
偏移 = 临时地址x - 源地址 - 6
HOOK代码 = 0xFF 0x25 偏移(4字节)
临时地址x(地址处内容) = 目标地址(8字节)

Inline HOOK代码

DWORD64 tmpx = 0;
void x64_InlineHook(DWORD64 qwHookAddr, LPVOID pFuncAddr)
{
//1.将HOOK处的位置改为 jmp qword ptr [rip + x]的方式
DWORD Offset = (DWORD64)&tmpx - qwHookAddr - 6;
byte hook_code[6] = { 0xFF, 0x25 };
*(DWORD*)(hook_code + 2) = Offset;
WriteProcessMemory((void*)-1, (void*)qwHookAddr, hook_code, sizeof(hook_code), NULL); //2.将目标地址写到临时地址x(字节码)
byte dest_address_opcode[8] = { 0 };
*(DWORD64*)dest_address_opcode = (DWORD64)pFuncAddr;
WriteProcessMemory((void*)-1, (void*)&tmpx, dest_address_opcode, sizeof(dest_address_opcode), NULL); //3.完成
}
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
x64_InlineHook((DWORD64)&my_func, fake_func); //测试Inline HOOK
my_func();
}

最终运行程序的效果

x64 InlineHook 黑魔法的更多相关文章

  1. C# inline-hook / api-hook

    我查阅了一下相关C#方面的资料,却没有发现有提供过关于api-hook方面的资 料包括应用库由此本人编写一套inline-hook的库用于支持x64.x86上的基于在 clr的公共语言,如: c#.c ...

  2. Win64 驱动内核编程-23.Ring0 InLineHook 和UnHook

    Ring0 InLineHook 和UnHook 如果是要在R0里hook,作者的建议是InLine HOOK,毕竟SSDT HOOK 和 SHADOW SSDT HOOK比较麻烦,不好修改.目前R3 ...

  3. HOOK技术之SSDT hook(x86/x64)

    x86 SSDT Hook 32位下进行SSDT Hook比较简单,通过修改SSDT表中需要hook的系统服务为自己的函数,在自己的函数中进行过滤判断达到hook的目的. 获取KeServiceDes ...

  4. X86和X86_64和X64有什么区别?

    x86是指intel的开发的一种32位指令集,从386开始时代开始的,一直沿用至今,是一种cisc指令集,所有intel早期的cpu,amd早期的cpu都支持这种指令集,ntel官方文档里面称为&qu ...

  5. VisualStudio 2015 开启IIS Express可以调试X64项目

    现在项目开发时总有时需要在X64下开发,这样我们就需要IIS Express中调试.不要总是放在IIS中,在Attach这样好慢.   如果不设置直接调试X64的程序,我们有可能会受到以下类似的错误 ...

  6. Win7(x64)升级到Win10

    北京时间7月29日零点起,微软正式开始向包含中国在内的全球用户推送Windows 10正式版安装包,Win7.Win8正版用户从29日零点起就可以免费升级到Win 10. 如果你的C盘里边有“$Win ...

  7. 数据库管理工具GUI - PremiumSoft Navicat Premium Enterprise 11.2.15 x86/x64 KEY

    转载自: 数据库管理工具GUI - PremiumSoft Navicat Premium Enterprise 11.2.15 x86/x64 KEY Navicat Premium(数据库管理工具 ...

  8. 在Ubuntu X64上编译Hadoop

    在之前的文章中介绍了如何直接在Ubuntu中安装Hadoop.但是对于64位的Ubuntu来说,官方给出的Hadoop包是32位的,运行时会得到警告: WARN util.NativeCodeLoad ...

  9. win7(x64)下安装cocos2d并编译安卓项目

    好吧,不为啥,就是如题. win7 x64 脑袋内存比较小,说不定明儿就忘了,今天记录一下. 没有什么经验,所有步骤基本都是百度出来的,这里边操作边记录,为了保护原创作者,这里我都附上我查找的链接. ...

随机推荐

  1. PHP的bz2压缩扩展工具

    在日常的开发和电脑使用中,我们经常会接触到压缩和解压的一些工具,PHP 也为我们准备了很多相关的操作扩展包,都有直接可用的函数能够方便的操作一些压缩解压功能.今天,我们先学习一个比较简单但不太常用的压 ...

  2. 在PHP中检测一个类是否可以被foreach遍历

    在PHP中,我们可以非常简单的判断一个变量是什么类型,也可以非常方便的确定一个数组的长度从而决定这个数组是否可以遍历.那么类呢?我们要如何知道这个类是否可以通过 foreach 来进行遍历呢?其实,P ...

  3. 使用fiddler抓包模拟器及配置fiddler过滤

    一. 安装fiddler https://www.telerik.com/fiddler 二. 配置fiddler,一下的ip要根据自己电脑情况设置 然后重启Fiddler,一定要重启!!! 三.配置 ...

  4. Android Kotlin协程入门

    Android官方推荐使用协程来处理异步问题.以下是协程的特点: 轻量:单个线程上可运行多个协程.协程支持挂起,不会使正在运行协程的线程阻塞.挂起比阻塞节省内存,且支持多个并行操作. 内存泄漏更少:使 ...

  5. Python3入门系列之-----字典

    字典 字典是一种可变容器模型,且存放任何类型对像(如:字符串,数字,或者列表甚至字典),每个字典有键名(key)和键值(value)且用冒号 :  隔开, 多个字典用逗号(,)隔开整个字典包括在花括号 ...

  6. 腾讯首个CNCF沙箱开源项目

    作者 SuperEdge开发者.腾讯云容器产品中心边缘计算团队.腾讯开源生态管理协会 SuperEdge 进入 CNCF 沙箱 2021 年 9 月 14 日,云原生分布式边缘容器系统 SuperEd ...

  7. 用Flask 实现文件服务器(包含docker版本)

    最近有了公司局域网内共享axure原型的需求,所以用Flask开发了一款文件上传/查看工具,记录一下其中的问题和解决方案 这个工具参照了一位大神的uploads工具 https://zhuanlan. ...

  8. Apache ShardingSphere:由开源驱动的分布式数据库中间件生态

    2021 年 7 月 21 日 2021 亚马逊云科技中国峰会现场,SphereEx 联合创始人.Apache ShardingSphere PMC 潘娟受邀参与此次峰会,以<Apache Sh ...

  9. Appium iOS 原理

    一.iOS Appium 原理 1.1 iOS 9.3 系统之前自动化测试 1.1.1 Native 自动化 这是 iOS 9.3 系统之前自动化测试的架构模式.通过 Android Appium 原 ...

  10. MIPS流水线技术

    华中科技大学 - 计算机硬件系统设计 单周期指令运行动态 Instruction Fetch Instruction Decode Execution MEM Write Back 单周期时空图 设耗 ...