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();
}
最终运行程序的效果
标签:黑魔法,字节,jmp,x64,rip,HOOK,地址,偏移,InlineHook 来源: https://www.cnblogs.com/VxerLee/p/15184023.html