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. html 表单input disabled属性提交后台无法获得数据

    在input上加入disabled属性后, 点击提交会遗漏该值, 有两个办法: 一 可以考虑readonly属性,一样的不可修改操作,但是可以提交 二 在提交时 js 代码操作去除input上的dis ...

  2. php_excel导出

    1.下载PHPExcel工具 2.解压后放置位置:ThinkPHP\Extend\Vendor\PHPExcel\PHPExcel.php. 3.Common.php代码 public functio ...

  3. 让selenium规避网站的检测

    在使用selenium对某些网站模拟访问的时候会被检测出来,检测出来之后就有可能拿不到我们想要的数据,那么我们怎么可以规避掉呢? 在使用谷歌浏览器的时候我们右键-检查-console-输入window ...

  4. 定要过python二级选择题二套

    1. 2. 3. 4. 5. 6. 7. 8. 非主属性???? 9. 10.. 11.` 调用只是调用,但是没有返回值,,应为里面没有输出 12. 13. 14. 15. 16. 18. 19.

  5. Oracle部署迁移手册

    第1章 安装准备 1.1 安装环境 操作系统:Redhat6.5 x64 32核CPU 62G内存 系统盘300G 数据磁盘3T Oracle软件:Oracle Database 11g Enterp ...

  6. vector 的交换技巧

    面试被问到如何解决 vector 有过多空闲内存的问题. 假定先有一 vector 容器 vec,它的容量是 10000,大小是 3. vector 的内存增长问题 vector 申请的是连续内存空间 ...

  7. T-SQL——透视PIVOT动态获取待扩展元素集

    目录 0.背景说明 1.准备测试数据 2.示例1--利用SELECT循环赋值 3.示例2--使用游标 4.示例3--使用FOR XML PATH() 5. 参考 志铭-2021年10月8日 00:57 ...

  8. Java基础之(二):Notepad++实现HelloWorld

    现在我们开始编写我们的第一个程序:Hello World! HelloWorld 新建一个java文件 文件后缀名为.java Hello.java 代码分析: 接下来写完最大的框之后,那接下来当然就 ...

  9. Azure Tips 第一期: Azure 中的安全监视工具,数据存储, 动态数据屏蔽以及资源部署

    # 1 Azure 中的安全监视工具 微软 Azure 云提供以下监控工具,可用于观察操作和检测异常行为. Azure 安全中心 Azure 安全中心是一个统一的基础结构安全管理系统,可以增强数据中心 ...

  10. bzoj1858SCOI 序列操作 (线段树)

    题目大意: 给定一个长度为n的01序列为,现在有m种操作 \(0\ a\ b\) 把\([a,b]\)的数全部修改为0 \(1\ a\ b\) 把\([a,b]\)的数全部修改为1 \(2\ a\ b ...