章节内容
一. Android Hook 系列教程(一) Xposed Hook 原理分析
二. Android Hook 系列教程(二) 自己写APK实现Hook Java层函数
三. Android Hook 系列教程(三) Cydia Hook Native 原理分析
四. Android Hook 系列教程(四) 自己写APK实现Hook Native层函数
五. Android Hook 系列教程(五) 更多Hook方法
六. Andoird Hook 系列教程(六) Hook的总结
源代码下载
Java层:https://github.com/rovo89/XposedBridge
Native层:https://github.com/rovo89/Xposed
开始
一个好的开始等于成功了一半.
为了分析Xposed Hook是怎么实现的,选取了findAndHookMethod函数作为研究对象.
在分析过程中,我们应该做到有详有略,我将以关键代码(略过对分析目的无关紧要的部分,留下必须部分).
当然在关键代码后面会贴出全部代码以供参照.
Jave层分析
findAndHookMethod
从源代码:XposedHelpers.java处找到findAndHookMethod
findAndHookMethod关键代码
public static XC_MethodHook.Unhook findAndHookMethod(Class> clazz, String methodName, Object... parameterTypesAndCallback) {
...
XC_MethodHook callback = (XC_MethodHook) parameterTypesAndCallback[parameterTypesAndCallback.length-1];//获取回调函数
Method m = findMethodExact(clazz, methodName, getParameterClasses(clazz.getClassLoader(), parameterTypesAndCallback));//获取Method
return XposedBridge.hookMethod(m, callback);
}
public static XC_MethodHook.Unhook findAndHookMethod(Class> clazz, String methodName, Object... parameterTypesAndCallback) {
if (parameterTypesAndCallback.length == 0 || !(parameterTypesAndCallback[parameterTypesAndCallback.length-1] instanceof XC_MethodHook))
throw new IllegalArgumentException("no callback defined");
XC_MethodHook callback = (XC_MethodHook) parameterTypesAndCallback[parameterTypesAndCallback.length-1];//获取回调函数
Method m = findMethodExact(clazz, methodName, getParameterClasses(clazz.getClassLoader(), parameterTypesAndCallback));//获取Method
return XposedBridge.hookMethod(m, callback);
}
上面的代码都很容易懂,简单说一下几个函数
getParameterClasses
功能:把函数所有参数转换为Class>数组返回.
比如参数列表为
String.class,int.class,"java.util.Map",回调函数
返回结果相当于
Class> []={
String.class,
int.class,
Map.class
};
findMethodExact
功能:根据方法名和方法参数类获取Method
关键代码:
public static Method findMethodExact(Class> clazz, String methodName, Class>... parameterTypes) {
...
Method method = clazz.getDeclaredMethod(methodName, parameterTypes);//获取方法声明
method.setAccessible(true);
methodCache.put(fullMethodName, method);
return method;
}
完整代码:
public static Method findMethodExact(Class> clazz, String methodName, Class>... parameterTypes) {
String fullMethodName = clazz.getName() + '#' + methodName + getParametersString(parameterTypes) + "#exact";
if (methodCache.containsKey(fullMethodName)) {
Method method = methodCache.get(fullMethodName);
if (method == null)
throw new NoSuchMethodError(fullMethodName);
return method;
}
try {
Method method = clazz.getDeclaredMethod(methodName, parameterTypes);//获取方法声明
method.setAccessible(true);
methodCache.put(fullMethodName, method);
return method;
} catch (NoSuchMethodException e) {
methodCache.put(fullMethodName, null);
throw new NoSuchMethodError(fullMethodName);
}
}
让我们继续跟进hookMethod
hookMethod
功能:把方法的参数类型,返回类型,回调函数记录到AdditionalHookInfo类里
并通过hookMethodNative方法进入Native层进行Hook.
在这个方法里面差不多都是关键代码,也就不省略,全部贴出.
完整代码:
public static XC_MethodHook.Unhook hookMethod(Member hookMethod, XC_MethodHook callback) {
/*检测是否是支持的Method类型*/
if (!(hookMethod instanceof Method) && !(hookMethod instanceof Constructor>)) {
throw new IllegalArgumentException("Only methods and constructors can be hooked: " + hookMethod.toString());
} else if (hookMethod.getDeclaringClass().isInterface()) {
throw new IllegalArgumentException("Cannot hook interfaces: " + hookMethod.toString());
} else if (Modifier.isAbstract(hookMethod.getModifiers())) {
throw new IllegalArgumentException("Cannot hook abstract methods: " + hookMethod.toString());
}
boolean newMethod = false;
CopyOnWriteSortedSet callbacks;
synchronized (sHookedMethodCallbacks) {
callbacks = sHookedMethodCallbacks.get(hookMethod);
if (callbacks == null) {//如果为null则函数没有被Hook,否则已经Hook
callbacks = new CopyOnWriteSortedSet<>();
sHookedMethodCallbacks.put(hookMethod, callbacks);
newMethod = true;
}
}
callbacks.add(callback);//记录回调函数
if (newMethod) {//建立新Hook
Class> declaringClass = hookMethod.getDeclaringClass();//获取类声明
int slot;
Class>[] parameterTypes;
Class> returnType;
if (runtime == RUNTIME_ART) {//判断是否是ART模式
slot = 0;
parameterTypes