一、概述
FastHook框架要求调用者准备与原方法参数一致的Hook方法和Forward方法,这些限制将业务逻辑和Hook逻辑耦合在一起。若不了解FastHook原理,请移步FastHook——一种高效稳定、简洁易用的Android Hook框架
因此可能需要一种新实现方式,其可将业务逻辑和Hook逻辑解耦。一种简单的方案便是动态生成Hook方法和Forword方法。然而该方案对性能的影响比较大,动态生成dex文件并加载是耗时操作。
本文将介绍一种新的思路,统一Hook方法,利用动态代理创建Forward方法。该方案比上述方案更加高效、简洁。
二、Hook方法
Hook方法必须能实现以下两点需求
1. 能正确识别原方法
2. 能正确解析原方法参数
2.1 ART方法调用约定
以32位arm平台为例
/*
* Quick invocation stub internal.
* On entry:
* r0 = method pointer
* r1 = argument array or null for no argument methods
* r2 = size of argument array in bytes
* r3 = (managed) thread pointer
* [sp] = JValue* result
* [sp + 4] = result_in_float
* [sp + 8] = core register argument array
* [sp + 12] = fp register argument array
* +-------------------------+
* | uint32_t* fp_reg_args |
* | uint32_t* core_reg_args |
* | result_in_float | <- Caller frame
* | Jvalue* result |
* +-------------------------+
* | lr |
* | r11 |
* | r9 |
* | r4 | <- r11
* +-------------------------+
* | uint32_t out[n-1] |
* | : : | Outs
* | uint32_t out[0] |
* | StackRef<ArtMethod> | <- SP value=null
* +-------------------------+
*/
1. r0寄存器存放被调用方法ArtMethod指针
2. r1~r3存放前3个参数
3. 从(sp+指针长度)地址起,按照参数顺序依次存放参数
显而易见,只需将被调用方法ArtMethod指针与sp指针传如Hook方法即可。32位指针长度为4字节,将以int类型传入,一种返回类型对应一个Hook方法。
private static Object hookHandleObject(int targetArtMethod, int sp) {
FastHookParam param = hookHandle(targetArtMethod,sp);
return param.result;
}
private static boolean hookHandleBoolean(int targetArtMethod, int sp) {
FastHookParam param = hookHandle(targetArtMethod,sp);
if(param.result != null && param.result instanceof Boolean) {
return ((Boolean) param.result).booleanValue();
}
return false;
}
private static byte hookHandleByte(int targetArtMethod, int sp) {
FastHookParam param = hookHandle(targetArtMethod,sp);
if(param.result != null && param.result instanceof Byte) {
return ((Byte) param.result).byteValue();
}
return 0;
}
private static char hookHandleChar(int targetArtMethod, int sp) {
FastHookParam param = hookHandle(targetArtMethod,sp);
if(param.result != null && param.result instanceof Character) {
return ((Character) param.result).charValue();
}
return 0;
}
private static short hookHandleShort(int targetArtMethod, int sp) {
FastHookParam param = hookHandle(targetArtMethod,sp);
if(param.result != null && param.result instanceof Short) {
return ((Short) param.result).shortValue();
}
return 0;
}
private static int hookHandleInt(int targetArtMethod, int sp) {
FastHookParam param = hookHandle(targetArtMethod,sp);
if(param.result != null && param.result instanceof Integer) {
return ((Integer) param.result).intValue();
}
return 0;
}
private static long hookHandleLong(int targetArtMethod, int sp) {
FastHookParam param = hookHandle(targetArtMethod,sp);
if(param.result != null && param.result instanceof Long) {
return ((Long) param.result).longValue();
}
return 0;
}
private static float hookHandleFloat(int targe