hook核心逻辑
hook的基本思路就是 拦截原调用逻辑,加入自己新增的逻辑,然后再执行原逻辑。
技术实现方案通常是 反射 + 动态代理。
怎么寻找hook点 ?
hook点的优先级为:
单例>静态类>public final
Android常用hook点
- Aidl传递的时候hook
- handler消息传递时hook
- 使用动态代理hook
使用场景:比如Android插件化,需要将代理Activity修改为Manifest中注册过的实际Activity。
代码示例
以下代码是模拟Android ActivityManager调用 startActivity方法的流程:
- 改动前,startActivity传递的参数为1
- 增加hook后,将入参1改为2
结果判断
通过判断 startActivity 的日志打印来判断 hook是否生效。
- 若打印 start:1 ,则hook无效,代码正常调用
- 若打印 start:2 ,则hook生效,参数被修改
- 其他情况均代码运行错误
public class HookTest {
@Test
public void test() throws Throwable {
//保证单例创建
ActivityManager.getService();
//hook调用
initHook();
//调用startActivity
ActivityManager.getService().startActivity(1);
}
private void initHook() throws Throwable {
Class<?> activityManager = Class.forName("com.iflytek.edu.apm.collector.hook.ActivityManager");
Field IActivityManagerSingleton = activityManager.getDeclaredField("IActivityManagerSingleton");
IActivityManagerSingleton.setAccessible(true);
Object singleton = IActivityManagerSingleton.get(null);
Class<?> singletonClass = Class.forName("com.iflytek.edu.apm.collector.hook.Singleton");
Field instanceField = singletonClass.getDeclaredField("mInstance");
instanceField.setAccessible(true);
final Object rawActivityManager = instanceField.get(singleton);
Object proxy = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
new Class[]{IActivityManager.class},
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("startActivity")) {
args[0] = 2;
}
return method.invoke(rawActivityManager, args);
}
});
instanceField.set(singleton, proxy);
}
}
public abstract class Singleton<T> {
private T mInstance;
protected abstract T create();
public final T get() {
synchronized (this) {
if (mInstance == null) {
mInstance = create();
}
return mInstance;
}
}
}
interface IActivityManager {
void startActivity(int a);
}
class ActivityManagerIpml implements IActivityManager {
@Override
public void startActivity(int a) {
System.out.println("start:" + a);
}
}
class ActivityManager {
public static IActivityManager getService() {
return IActivityManagerSingleton.get();
}
private static final Singleton<IActivityManager> IActivityManagerSingleton =
new Singleton<IActivityManager>() {
@Override
protected IActivityManager create() {
final IActivityManager am = new ActivityManagerIpml();
return am;
}
};
}