-
-
[原创]Inline-Hook指令还原
-
2020-11-9 10:00 4296
-
inline-hook的详细过程在 ele7enxxh的博客中已经写的很清楚了。 下面是自己对指令修复的一些细节位置的学习,特别是指令的二进制表达形式。
inline-hook
需要把原函数中的指令拷贝到另一个地方,如果这些指令与 pc
相关,在拷贝之后,由于 pc
发生了变化,所以这些指令就需要被修复。
下面以 blx
指令的修复为例子。
假定被 hook
地址处(hook_addr
)前几条指令如下,并且处于 arm
模式,那么现在需要备份的指令是前三条指令 blx addr; ins1; ins2;
,并且可以得到此时的 pc = hook_addr + 8
,lr = hook_addr + 12
。
1 2 3 4 | blx offset ;(hook地址,也就是hook_addr) ins1 ins2 ;(pc = hook_addr + 8 ) ins3 ;(lr = hook_addr + 12 ) |
blx offset
真实的跳转地址应该是 target_addr = pc + offset
,为了防止指令拷贝到其他地方之后,因为 pc
值的的改变而导致计算出的 target_addr
改变,需要先计算出真实的 target_addr
,再用直接跳到 target_addr
的指令替换 blx offset
。
比如可以将 blx offset
替换成如下指令:
1 2 | LDR PC, [PC, #-4] ;pc=target_addr target_addr ;target_addr是计算后跳转的绝对地址,直接赋值给pc来改变执行位置 |
下面就看怎么计算跳转的绝对地址 target_addr
。
首先我们查 arm
手册得到 blx
指令格式:
可以看出 target_addr = instruction + 8 + 4 * offset + 2 * a
,
instruction + 8
也就是当前 pc
的值;
offset
也就是指令字节码后24位,可以通过 offset = ins & 0xFFFFFF;
计算得到。offset * 4
等于 offset << 2
;
a
是字节码中第25位,也就是 ins & 0x1000000 >> 24;
2a
就等于 ins & 0x1000000 >> 23
;
计算 target_addr
的过程转成对应的代码就是下面这样:
1 2 3 4 5 | x = ((instruction & 0xFFFFFF ) << 2 ) | ((instruction & 0x1000000 ) >> 23 ); top_bit = x >> 25 ; / / 符号处理 imm32 = top_bit ? (x | ( 0xFFFFFFFF << 26 )) : x; / / 修复后的绝对地址 value = pc + imm32 + 1 ; |
阿里云助力开发者!2核2G 3M带宽不限流量!6.18限时价,开 发者可享99元/年,续费同价!