实现Android(安卓)ARM64平台下Inline Hook框架
Android阵营新出机型的cpu基本都是64位了,虽然可以向下兼容armeabi-v7a,但是使用32位的so毕竟不能充分发挥64位cpu的潜力,所以以后arm64-v8a用的会越来越多。但是整个安卓生态圈似乎还没有开源发布的ARM64内联HOOK方案,所以自己动手写了个,姑且取名And64InlineHook吧,需要注意的是仍然是Alpha版。
关于Inline Hook的背景知识这里不再阐述,我仅支持了相对简单的函数首指令改写方案,原则上也支持函数任意位置HOOK(需自行处理堆栈),不支持短函数,也暂不支持AArch32 state。
由于arm64-v8a指令集都是固定的32位,指令地址也因而是4字节对齐,相比变长指令处理起来会相对容易,但是没办法直接操作PC寄存器,A64处理跳转起来会比A32和T32繁琐。
首先是计算需要覆盖的指令数,我的方案是计算目标函数和转接函数的距离,然后决定是使用 B直接转跳 还是 BR寄存器绝对转跳,其中B只会影响一条指令,是比较优的路径,但是它的转跳范围不能超过0b00001111111111111111111111111100;BR需要占用4-5条指令(就我目前的方案而言,即把地址直接写在代码里),因为我们需要设法把地址加载到寄存器,这就需要类似下面的操作,然后为什么是5条指令?因为对于LOAD操作我们需要考虑内存对齐,于是可能需要一条额外的NOP指令来填充。
0x00000000 LDR X, #0x40x00000004 BR X0x00000008 DCD ...0x0000000C DCD ...
上面X是64位寄存器,显而易见这会造成寄存器污染,所以我们需要挑一个尽可能不被使用的寄存器,也就不需要去设法保护它,这里我选了X17,其实X16也行。 接着就是重头戏指令修复。把覆盖掉的指令一条条复制到我们的跳板Trampoline里,并对所有含PC-relative address操作数的指令进行重定位。至于哪些指令需要被修复,你可以查阅armv8a指令手册(我上传了份从ARM官网下载的pdf,应该是最新修订的,http://download.csdn.net/download/rrrfff/9992241) 或者 在线文档http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.100069_0608_00_en/index.html。
大概有以下几类指令,分别由__fix_branch_imm、__fix_cond_comp_test_branch、__fix_loadlit、__fix_pcreladdr完成具体修复,具体可以去看源码,不过可能会比较乱,当然了这玩意后期基本不需要什么维护,也别想着以后ARM128还能用:
// branch_immbbl// compbranchcbzcbnz// condbranchb.c// loadlitldrldrldrswprfm// pcreladdradradrp// testbranchtbztbnz// condbranchbeqbnebcsbhsbccblobmibplbvsbvcbhiblsbgebltbgtble
其中值得一提的大概有几点,一是__fix_loadlit,因为涉及到LOAD操作,自然要考虑内存对齐,然而LOAD的目的寄存器可能是32、64甚至128位,所以需要考虑的情形就有3种;二是对于BL这种带链接跳转,如果转化成BR需要先把返回地址写到LR(X30)里;此外就是代码中引用的地址可能就在我们覆盖的范围内,这种情况很少,但是还是简单处理了下,对相应地址进行了修复,参考process_fix_map。 更多相关文章
- 万字长文带你了解最常用的开源 Squid 代理服务器
- Android4.0.1 模拟器内核 最新下载地址及编译步骤
- Android(安卓)编译命令
- Android实践系列之项目基础配置
- [置顶] 玩转pandaboard之linaro对于Android的编译上的一些优化
- Android中由IP地址查询经纬度坐标的实例
- android 控制POS机图文打印(二)
- fir.im Weekly - 暖心的 iOS 持续集成,你值得拥有
- android studio 常用插件