x64 InlineHook 黑魔法
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 黑魔法的更多相关文章
- C# inline-hook / api-hook
我查阅了一下相关C#方面的资料,却没有发现有提供过关于api-hook方面的资 料包括应用库由此本人编写一套inline-hook的库用于支持x64.x86上的基于在 clr的公共语言,如: c#.c ...
- Win64 驱动内核编程-23.Ring0 InLineHook 和UnHook
Ring0 InLineHook 和UnHook 如果是要在R0里hook,作者的建议是InLine HOOK,毕竟SSDT HOOK 和 SHADOW SSDT HOOK比较麻烦,不好修改.目前R3 ...
- HOOK技术之SSDT hook(x86/x64)
x86 SSDT Hook 32位下进行SSDT Hook比较简单,通过修改SSDT表中需要hook的系统服务为自己的函数,在自己的函数中进行过滤判断达到hook的目的. 获取KeServiceDes ...
- X86和X86_64和X64有什么区别?
x86是指intel的开发的一种32位指令集,从386开始时代开始的,一直沿用至今,是一种cisc指令集,所有intel早期的cpu,amd早期的cpu都支持这种指令集,ntel官方文档里面称为&qu ...
- VisualStudio 2015 开启IIS Express可以调试X64项目
现在项目开发时总有时需要在X64下开发,这样我们就需要IIS Express中调试.不要总是放在IIS中,在Attach这样好慢. 如果不设置直接调试X64的程序,我们有可能会受到以下类似的错误 ...
- Win7(x64)升级到Win10
北京时间7月29日零点起,微软正式开始向包含中国在内的全球用户推送Windows 10正式版安装包,Win7.Win8正版用户从29日零点起就可以免费升级到Win 10. 如果你的C盘里边有“$Win ...
- 数据库管理工具GUI - PremiumSoft Navicat Premium Enterprise 11.2.15 x86/x64 KEY
转载自: 数据库管理工具GUI - PremiumSoft Navicat Premium Enterprise 11.2.15 x86/x64 KEY Navicat Premium(数据库管理工具 ...
- 在Ubuntu X64上编译Hadoop
在之前的文章中介绍了如何直接在Ubuntu中安装Hadoop.但是对于64位的Ubuntu来说,官方给出的Hadoop包是32位的,运行时会得到警告: WARN util.NativeCodeLoad ...
- win7(x64)下安装cocos2d并编译安卓项目
好吧,不为啥,就是如题. win7 x64 脑袋内存比较小,说不定明儿就忘了,今天记录一下. 没有什么经验,所有步骤基本都是百度出来的,这里边操作边记录,为了保护原创作者,这里我都附上我查找的链接. ...
随机推荐
- python学习笔记(八)-模块
大型python程序以模块和包的形式组织.python标准库中包含大量的模块.一个python文件就是一个模块.1.标准模块 python自带的,不需要你安装的2.第三方模块 需要安装,别人提供的. ...
- 『Python』matplotlib初识
1. 核心原理 使用matplotlib绘图的原理,主要就是理解figure(画布).axes(坐标系).axis(坐标轴)三者之间的关系. 下面这幅图更详细: 以"美院学生张三写生画画&q ...
- 深入浅出WPF-12.绘图与动画
绘图 1)Brush(画刷) SolidColorBrush实心画刷,直接使用颜色赋值 LinearGradientBrush线性渐变画刷,色彩沿设定的直线方向.按设定的变化点进行渐变 RadialG ...
- 请求既有multipartFile,也有实体的解决方案
上回书我们说到,我们在发文件上传请求的时候,携带数据 this.fileData.append('trainName', this.dataModel.trainName); // 添加培训名称 然后 ...
- VS2013的主函数问题
报错如下: 打开属性里面,修改字符集即可
- 题解 [AGC017C] Snuke and Spells
题目传送门 Description 有 \(n\) 个球排在一起,每个球有颜色 \(a_i\),若当前有 \(k\) 个球,则会将所有 \(a_i=k\) 的球删掉.有 \(m\) 次查询,每次将 \ ...
- PAT (Basic Level) Practice (中文)1026 程序运行时间 (15分)
1026 程序运行时间 (15分) 要获得一个 C 语言程序的运行时间,常用的方法是调用头文件 time.h,其中提供了 clock() 函数,可以捕捉从程序开始运行到 clock() 被调用时所耗费 ...
- OpenSSL version mismatch. Built against 1010104f, you have 101000cf
现象:公司一台Ubuntu16.04.2的ssh后台无法连接,telnet端口也不通,只能接显示器操作了. 先进行初步排查 查看服务是否启动(公司测试机ssh都是默认启动的) netstat -anp ...
- css如何简单设置文字溢出盒子显示省略号
1.单行文本溢出显示省略号单行文本溢出显示省略号,必须满足三个条件:(1)先强制一行内显示文本white-space:nowrap;(默认 normal自动换行)(2)超出的部分隐藏overflow: ...
- ES2020新特性记录
1.可选链操作符 // oldlet ret = obj && obj.first && obj.first.second// newlet ret = obj?.fi ...