一、概述
在使用YAHFA框架的过程中,遇到了些问题,为了解决这些问题在YAHFA的基础上写了FastHook框架。本文分析内容基于Android 8.1。
项目地址:FastHook:https://github.com/turing-technician/FastHook
二、YAHFA
2.1 YAHFA原理
首先我们来看看YAHFA框架基本流程,再分析其实现原理。
- Target方法EntryPoint替换为HookTrampoline。当执行Target方法时,实际执行HookTrampoline,从而实现方法Hook。
- HookTrampoline先将r0设置为Hook方法,再跳转到Hook方法EntryPoint执行Hook方法。
- Hook方法参数与Target方法参数须一致,在Hook方法里调用Backup方法达到间接调用Target方法的目的。
- Backup方法必须是static方法(如果Target方法不是static方法,Backup方法第一个参数必须为this,Hook方法不需要一定是static方法,只要保证参数一致即可)。static方法是静态分派的,这可以保证调用的是Backup方法本身。
- Backup方法必须要完全备份Target方法,ART需要知道native code与dex code的映射关系,例如一条native指令对应哪条dex指令,这个映射关系需要EntryPoint来计算,而为了实现Hook,我们替换了Target方法的EntryPoint。所以我们必须完全复制Backup方法,此时我们执行的还是Backup方法,只是这个Backup方法的内容跟Target完全一样,这样间接达到调用Target方法的目的。
2.2 YAHFA缺陷
- 方法执行效率低。YAHFA通过禁止JIT和AOT编译来规避一些问题,但是同时也极大降低了方法执行效率。
- Backup方法不能被再次解析。由于Backup方法已备份为Target方法,因而再此被解析将引发NoSuchMethod异常。
- Moving GC引发的空指针异常。当Target方法的某些成员(例如Class)被移动时,由于Backup方法是备份得到的,因而不会更新到新地址,导致空指针异常。
- 方法内联导致Hook失效。Hook是通过替换方法EntryPoint实现的,因此当方法被内联时就不会用到EntryPoint,这是Hook将失效。
三、FastHook
FastHook提供了两种方案,一种类似Native Inline Hook,另一个依旧是Entrypoint替换。
3.1 Inline模式
Inline模式由5部分组成: