selph
selph
发布于 2021-10-14 / 908 阅读
0
0

三种基础InlineHook的对比

三种 InlineHook 对比

InlineHook 有三类,对比如下:

x86 InlineHookretjmp regjmp offset
影响字节数6 字节7 字节5 字节
影响寄存器影响一个寄存器的值
通用性通用通用通用
x64 InlineHookretjmp regjmp offset
影响字节数14 字节12 字节6 字节
影响寄存器影响一个寄存器的值
通用性通用通用寻址范围低

通常情况下 x64 使用 ret 方式,x86 使用 jmp offset 方式即可

InlineHook:ret

x86 6 字节

原理介绍:

push Address
ret

image.png

硬编码:

Byte[6] = {0x68,0,0,0,0,0xC3}	// 中间4位是地址

x64 14 字节

原理介绍:

push LowAddress;
mov dword ptr ss:[rsp+4], HighAddress;
ret

PUSH 指令最多支持 32 位立即数,为了不改变寄存器,这里需要通过 push 提高栈顶,然后通过 mov 填充完整地址,再通过 ret 跳转

image.png

硬编码:

Byte[14] = {0x68,0,0,0,0,0xC7,0x44,0x24,0x04,0,0,0,0,0xC3}	// 前4位是低位地址,后4位是高位地址

InlineHook:jmp reg

x86 7 字节

原理介绍:

mov eax, Address;
jmp eax;

image.png

硬编码:

Byte[7] = {0xB8,0,0,0,0,0xFF,0xE0};	// 中间4位是地址

x64 12 字节

原理介绍:

mov rax, Address;
jmp rax;

image.png

硬编码:

Byte[12] = {0x48,0xb8,0,0,0,0,0,0,0,0,0xFF,0xE0}	// 中间8位是地址

InlineHook:jmp offset

x86 5 字节

原理介绍:

E9 跳转指令后面的 4 字节是与当前地址的偏移:Offset = 目标地址 - 当前地址 - 指令长度 5

jmp offset

image.png

硬编码:

Byte[5] = {0xE9,0,0,0,0}	// 中间4位是地址

x64 6 字节

原理介绍:

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

jmp qword ptr [rip + offset];

这里会从 rip 开始计算偏移取 8 字节地址,如图,这里设置的偏移是 9,于是就在地址 =当前地址 + 指令长度 6 + 9,也就是第二个红框处取地址进行跳转

因为寻址仅支持 4 字节,最大寻址范围 2GB,在 64 位程序内存中很容易就超出这个范围,这个方法能用,但不通用

image.png

硬编码:

Byte[6] = {0xFF,0x25,0,0,0,0}	// 后面4位是地址所在地址距离当前位置的偏移

参考资料:

x64 InlineHook 黑魔法 - HackLee - 博客园 (cnblogs.com)

64 位下的 InlineHook - iBinary - 博客园 (cnblogs.com)


评论