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. Linux从头学13:想彻底搞懂“系统调用”的底层原理?建议您别错过这篇【调用门】

    作 者:道哥,10+年嵌入式开发老兵,专注于:C/C++.嵌入式.Linux. 关注下方公众号,回复[书籍],获取 Linux.嵌入式领域经典书籍:回复[PDF],获取所有原创文章( PDF 格式). ...

  2. 基于Tensorflow + Opencv 实现CNN自定义图像分类

    摘要:本篇文章主要通过Tensorflow+Opencv实现CNN自定义图像分类案例,它能解决我们现实论文或实践中的图像分类问题,并与机器学习的图像分类算法进行对比实验. 本文分享自华为云社区< ...

  3. 基于pgpool搭建postgresql集群

    postgresql集群搭建 基于pgpool中间件实现postgresql一主多从集群部署,这里用两台服务器作一主一从示例 虚拟机名 IP 主从划分 THApps 192.168.1.31 主节点 ...

  4. gitlab与git命令

    gitlab安装目录 /etc/gitlab#配置文件目录 /run/gitlab#运行pid目录 /opt/gitlab#安装目录 /var/opt/gitlab#数据目录 /var/log/git ...

  5. 执行:vim /etc/profile,提示:Command 'vim' not found, but can be installed with:

    root@uni-virtual-machine:/# vim /etc/profile Command 'vim' not found, but can be installed with: apt ...

  6. whistle浏览器抓包(以火狐浏览器为例)

    环境:whistle:1.14.6 whistle浏览器抓包 以火狐浏览器为例 1.启动whistle 使用w2 start启动whistle. 退出cmd后,whistle自动关闭了,所以每次使用w ...

  7. Spring Security 学习+实践

    Spring Security是Spring为解决应用安全所提供的一个全面的安全性解决方案.基于Spring AOP和Servlet过滤器,启动时在Spring上下文中注入了一组安全应用的Bean,并 ...

  8. Redis分布式方案:集群

    Redis集群通过分片(sharding)进行数据共享,并提供复制和故障转移功能. 节点 一个Redis集群由多个node组成,连接各节点的命令格式如下: CLUSTER MEET 127.0.0.1 ...

  9. mac上通过git推送时忽略node_modules文件夹

    node_modules出现改动一般不需要通过git推送,如果不忽略node_modules每次安装新的包会出现几千条新变动,并没有必要推送 1.通过终端进入项目根目录 创建 .gitignore 文 ...

  10. CentOS7部署Prometheus

    部署Prometheus监控报警系统 一.Prometheus介绍 Prometheus是由SoundCloud开发的开源监控报警系统和时序列数据库(TSDB):Prometheus使用Go语言开发, ...