if (zygote) {
runtime.start(keepLoadingXposed ? XPOSED_CLASS_DOTS : "com.android.internal.os.ZygoteInit",
startSystemServer ? "start-system-server" : "");
} else if (className) {
// Remainder of args get passed to startup class main()
runtime.mClassName = className;
runtime.mArgC = argc - i;
runtime.mArgV = argv + i;
runtime.start(keepLoadingXposed ? XPOSED_CLASS_DOTS : "com.android.internal.os.RuntimeInit",application ? "application" : "tool");
}
其中XPOSED_CLASS_DOTS在xposed.h中
#define XPOSED_CLASS_DOTS "de.robv.android.xposed.XposedBridge"
if (initNative()) {//java函数jni的注册
if (startClassName == null) {
// Initializations for Zygote
initXbridgeZygote();//fork some main android class
}
loadModules(startClassName);//load xposed apks and call callbacks
} else {
log("Errors during native Xposed initialization");
}
1.initNative()主要负责java函数jni的注册
//xposedHandleHookedMethod
//xposedInvokeOriginalMethodNative
//objectArrayClass
//xresourcesClass
//xresourcesTranslateResId
//xresourcesTranslateAttrId
//register_android_content_res_XResources
主要实现Xposed.cpp->de_robv_android_xposed_XposedBridge_initNative
2.initXbridgeZygote()和loadModules相当于是Xposed对原Zygote的扩展
initXbridgeZygote()主要是做了几个hook操作
findAndHookMethod(ActivityThread.class, "handleBindApplication", "android.app.ActivityThread.AppBindData", new XC_MethodHook());
findAndHookMethod("com.android.server.ServerThread", null,
Build.VERSION.SDK_INT < 19 ? "run" : "initAndLoop", new XC_MethodHook());
hookAllConstructors(LoadedApk.class, new XC_MethodHook());
findAndHookMethod("android.app.ApplicationPackageManager",null,"getResourcesForApplication",ApplicationInfo.class, new XC_MethodHook());
if (!new File(BASE_DIR + "conf/disable_resources").exists()) {
hookResources();
}
find Method主要利用java的反射
findAndHookMethod-》findMethodExact-》
Method method = clazz.getDeclaredMethod(methodName, parameterTypes);//reflect
-》hookMethod(Member hookMethod, XC_MethodHook callback)
3.loadModules(startClassName);
Try to load all modules defined in BASE_DIR/conf/modules.list
And 安排好各种回调 IXposedHookZygoteInit,IXposedHookLoadPackage,IXposedHookInitPackageResources和IXposedHookCmdInit
Xposed扩展模块必须继承上面的4个接口之一,重写其中的handleXXX函数,即各种回调,它们就是在loadModules执行的
主要实现hookMethodNative,即Xposed.cpp中的de_robv_android_xposed_XposedBridge_hookMethodNative函数
// 保存原函数信息
XposedHookInfo* hookInfo = (XposedHookInfo*) calloc(1, sizeof(XposedHookInfo));
memcpy(hookInfo, method, sizeof(hookInfo->originalMethodStruct));
hookInfo->reflectedMethod = dvmDecodeIndirectRef(dvmThreadSelf(), env->NewGlobalRef(reflectedMethodIndirect));
hookInfo->additionalInfo = dvmDecodeIndirectRef(dvmThreadSelf(), env->NewGlobalRef(additionalInfoIndirect));
// 将函数入口替换为xposedCallHandler,每次调这个被hook的method,其实质上调用的是xposedCallHandler。
SET_METHOD_FLAG(method, ACC_NATIVE);
method->nativeFunc = &xposedCallHandler;
method->insns = (const u2*) hookInfo;
method->registersSize = method->insSize;
method->outsSize = 0;
xposedCallHandler中根据函数参数的TYPE,即(I,F...这些参数在ClassUtil.java中定义)组织好参数:
xposedSetObjectArrayElement(argsArray, dstIndex++, obj);
最后:
dvmCallMethod(self, xposedHandleHookedMethod, NULL, &result, originalReflected, (int) original, additionalInfo, thisObject,argsArray);
xposedHandleHookedMethod是对XposedBridge类handleHookedMethod的引用,de_robv_android_xposed_XposedBridge_initNative中链接:
xposedHandleHookedMethod = (Method*) env->GetStaticMethodID(xposedClass, "handleHookedMethod","(Ljava/lang/reflect/Member;ILjava/lang/Object;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;");
XposedBridge类的handleHookedMethod, disableHooks则调用原函数,否则beforeHookedMethod-》invokeOriginalMethodNative-》afterHookedMethod
if (disableHooks) {
try {
return invokeOriginalMethodNative(method, originalMethodId, additionalInfo.parameterTypes,additionalInfo.returnType, thisObject, args);
//......
do {
try {((XC_MethodHook)callbacksSnapshot[beforeIdx]).beforeHookedMethod(param);
//......
try {
param.setResult(invokeOriginalMethodNative(method,originalMethodId,
additionalInfo.parameterTypes, additionalInfo.returnType, param.thisObject, param.args));
}
//......
try {
((XC_MethodHook) callbacksSnapshot[afterIdx]).afterHookedMethod(param);
}