首页
社区
课程
招聘
[原创]ART/Dalvik环境下Xposed实现异同分析
发表于: 2021-4-29 19:17 5233

[原创]ART/Dalvik环境下Xposed实现异同分析

2021-4-29 19:17
5233

写了一部分,先占个坑,后续补完

了解到ART/Dalvik的异同之后,我们再来看看我们的主题,当Android虚拟机DalvikARTXposed针对这种变化对其底层实现逻辑做了哪些变更呢?

首先从源头入手,Xposed框架在编译app_main文件时做了系统适配处理,针对不同版本的系统使用不同的app_main文件

那么下面我们分析下这两份文件的实现

可以看到,在两份文件中针对AppRuntime类的修改大致是相同的,同样都是调用了xposed::onVmCreated

到目前为止可以看到关于xposed::onVmCreated的调用流程最终走到了两份文件自己的onVmCreated方法,下面来看看这两个方法的差异

Dalvik版本的onVmCreated函数做的是为Java层invokeOriginalMethodNative设置Native方法,将原本的方法转成nativeXposedBridge_invokeOriginalMethodNative方法,再回调Java层的方法

ART版本的onVmCreated函数做的是为ArtMethod赋值,classXposedBridgemethodXposedBridgeHandleHookedMethod都是之前在initXposedBridge函数中设置好的

现在关于onVmCreated的函数变更已经分析好了,下面正式开始分析main函数

同样都是调用xposed::initialize函数

xposed::initialize函数主要做了些初始化的工作:为xposed结构体赋值、启动各个子线程、最后将xposed_bridge.jar引入,执行完xposed::initialize函数之后会返回一个isXposedLoaded标识,会根据这个标识决定是否具体传入的包名,之前步骤执行正确的话传入的包名应该是"de.robv.android.xposed.XposedBridge",来看看具体的runtime.start函数是怎样执行的

runtime.start函数调用的是AndroidRuntimestart函数,关键点在于startVm(虚拟机的创建)、onVmCreated(虚拟机创建完成之后的初始化),CallStaticVoidMethod main(反射调用类的main函数),onVmCreated已经分析过了,下面分析下XposedBridgemain函数

XposedBridge.main函数关键在于三个函数的调用:

我们重点关注下initForZygoteloadModules两个方法

我们分成几部分来看

nativeForkAndSpecializenativeForkSystemServer同样都是利用Zygote利用fork来创建子进程的,我们看下Xposed框架会对这两个方法做什么操作

closeFilesBeforeForkNativereopenFilesAfterForkNative这两个方法同属于native,属于XposedBridgenative方法一般都是在initXposedBridge中动态注册的,方法是存在于各自的libxposed_xxx.so文件当中,不过这两个方法只存在于高版本系统中

这一部分的主要逻辑是针对ActivityThreadhandleBindApplication方法做了hook操作,具体的操作就是设置ActivityThreadmBoundApplication的值,并实例化LoadPackageParam进行赋值,这里的LoadPackageParam实例也就是我们在开发过程中的lpparam

我们从代码中已经知道了当lpparam封装好之后会调用它的callbacks数组每个对象的handleLoadPackage方法,那这个数组是什么时候被赋值的呢?从代码中可以发现数组是XposedBridge.sLoadedPackageCallbacks,它在下面这段代码中被赋值

hookLoadPackage是在loadModules方法中被调用,这个部分我们在loadModules的时候再说

这一部分和上一部分道理相同,只是Hook点的不同,一个是针对App启动过程中,一个是针对system server

对于loadModules的流程我们也大致了解了

那么,对于xposed::initialize函数的分析就到这里,到目前为止,我们梳理完了Xposed框架的启动流程以及它在启动过程中做了哪些工作,当然,我们的主题是ART/Dalvik环境下Xposed框架实现的异同,我们在app_main文件变更这个步骤只发现了它们对于onVmCreated的实现做了改变

从刚才的initForZygote函数中,我们可以发现使用了大量的findAndHookMethod,当然,这个函数也是我们在接触Xposed框架的时候最先学会的函数,标准的模板调用是这么来使用的

我们跟踪下findAndHookMethod的实现

先来看看Dalvik时期的,XposedBridge_hookMethodNative实现在libxposed_dalvik.cpp文件中

invokeOriginalMethodNativenative函数,想想它是在什么时候变成native函数的呢?

onVmCreated函数执行的时候,回顾一下

通过dvmSetNativeFuncxposedInvokeOriginalMethodNative的真正执行函数变为xposedInvokeOriginalMethodNative

xposedInvokeOriginalMethodNative方法我们之前也分析过,主要是通过dvmInvokeMethod来反射调用Java层的方法

分析完了Dalvik时期的hookMethodNative流程,下面来看看ART时期的hookMethodNative做了哪些改变,省略掉相同的步骤,我们直接看libxposed_art.cppXposedBridge_hookMethodNative函数实现

关键点在于函数的入口点的替换,由entry_point_from_quick_compiled_code_替换成了GetQuickProxyInvokeHandler

看看GetQuickProxyInvokeHandler的实现

GetQuickProxyInvokeHandler的具体逻辑由art_quick_proxy_invoke_handler方法来实现

从汇编文件入手

回到handleHookedMethod方法之后就和dalvik的执行逻辑一样了

[1] https://bbs.pediy.com/thread-257844.htm

[2] https://blog.csdn.net/zjx839524906/article/details/81046844

 
# Android.mk
 
# PLATFORM_SDK_VERSION字段
# 参考xref: /build/core/version_defaults.mk
# PLATFORM_VERSION := 7.1.2
# PLATFORM_SDK_VERSION := 25
# 根据系统版本不同,7以上的版本使用app_main2.cpp来编译
ifeq (1,$(strip $(shell expr $(PLATFORM_SDK_VERSION) \>= 21)))
  LOCAL_SRC_FILES := app_main2.cpp
  LOCAL_MULTILIB := both
  LOCAL_MODULE_STEM_32 := app_process32_xposed
  LOCAL_MODULE_STEM_64 := app_process64_xposed
else
  LOCAL_SRC_FILES := app_main.cpp
  LOCAL_MODULE_STEM := app_process_xposed
endif
 
##########################################################
# Library for Dalvik-/ART-specific functions
##########################################################
# 针对libxposed_xxx.cpp文件也是同样的道理
ifeq (1,$(strip $(shell expr $(PLATFORM_SDK_VERSION) \>= 21)))
  include frameworks/base/cmds/xposed/ART.mk
else
  include frameworks/base/cmds/xposed/Dalvik.mk
endif
# Android.mk
 
# PLATFORM_SDK_VERSION字段
# 参考xref: /build/core/version_defaults.mk
# PLATFORM_VERSION := 7.1.2
# PLATFORM_SDK_VERSION := 25
# 根据系统版本不同,7以上的版本使用app_main2.cpp来编译
ifeq (1,$(strip $(shell expr $(PLATFORM_SDK_VERSION) \>= 21)))
  LOCAL_SRC_FILES := app_main2.cpp
  LOCAL_MULTILIB := both
  LOCAL_MODULE_STEM_32 := app_process32_xposed
  LOCAL_MODULE_STEM_64 := app_process64_xposed
else
  LOCAL_SRC_FILES := app_main.cpp
  LOCAL_MODULE_STEM := app_process_xposed
endif
 
##########################################################
# Library for Dalvik-/ART-specific functions
##########################################################
# 针对libxposed_xxx.cpp文件也是同样的道理
ifeq (1,$(strip $(shell expr $(PLATFORM_SDK_VERSION) \>= 21)))
  include frameworks/base/cmds/xposed/ART.mk
else
  include frameworks/base/cmds/xposed/Dalvik.mk
endif
 
// xposed.cpp
 
/** Load the libxposed_*.so library for the currently active runtime. */
// 同样都是调用了xposed.cpp的onVmCreated函数
void onVmCreated(JNIEnv* env) {
    // Determine the currently active runtime
    // 初始化xposed lib路径
    const char* xposedLibPath = NULL;
    // 轮询/proc/self/maps结果,查看系统到底是art还是dalvik再决定赋值
    // xposed.h
    // #define XPOSED_LIB_DALVIK        XPOSED_LIB_DIR "libxposed_dalvik.so"
    // #define XPOSED_LIB_ART           XPOSED_LIB_DIR "libxposed_art.so"
    if (!determineRuntime(&xposedLibPath)) {
        ALOGE("Could not determine runtime, not loading Xposed");
        return;
    }
    // 通过dlopen so文件,so文件由之前的determineRuntime函数配置
    // Load the suitable libxposed_*.so for it
    void* xposedLibHandle = dlopen(xposedLibPath, RTLD_NOW);
    if (!xposedLibHandle) {
        ALOGE("Could not load libxposed: %s", dlerror());
        return;
    }
 
    // Clear previous errors
    dlerror();
 
    // Initialize the library
    // dlsym 执行so文件中xposedInitLib函数,so文件就是上面被赋值的文件
    bool (*xposedInitLib)(XposedShared* shared) = NULL;
    *(void **) (&xposedInitLib) = dlsym(xposedLibHandle, "xposedInitLib");
    if (!xposedInitLib)  {
        ALOGE("Could not find function xposedInitLib");
        return;
    }
    // xposedInitLib函数如下,赋予xposed的onVmCreated为onVmCreatedCommon
    // 也就是libxposed_common.cpp的onVmCreatedCommon方法
 
    // bool xposedInitLib(XposedShared* shared) {
    //     xposed = shared;
    //     xposed->onVmCreated = &onVmCreatedCommon;
    //     return true;
    // }
 
#if XPOSED_WITH_SELINUX
    xposed->zygoteservice_accessFile = &service::membased::accessFile;
    xposed->zygoteservice_statFile   = &service::membased::statFile;
    xposed->zygoteservice_readFile   = &service::membased::readFile;
#endif  // XPOSED_WITH_SELINUX
    // 方法返回true,执行onVmCreatedCommon方法,到目前为止,流程都是相同的
    if (xposedInitLib(xposed)) {
        xposed->onVmCreated(env);
    }
}
// xposed.cpp
 
/** Load the libxposed_*.so library for the currently active runtime. */
// 同样都是调用了xposed.cpp的onVmCreated函数
void onVmCreated(JNIEnv* env) {
    // Determine the currently active runtime
    // 初始化xposed lib路径
    const char* xposedLibPath = NULL;
    // 轮询/proc/self/maps结果,查看系统到底是art还是dalvik再决定赋值
    // xposed.h
    // #define XPOSED_LIB_DALVIK        XPOSED_LIB_DIR "libxposed_dalvik.so"
    // #define XPOSED_LIB_ART           XPOSED_LIB_DIR "libxposed_art.so"
    if (!determineRuntime(&xposedLibPath)) {
        ALOGE("Could not determine runtime, not loading Xposed");
        return;
    }
    // 通过dlopen so文件,so文件由之前的determineRuntime函数配置
    // Load the suitable libxposed_*.so for it
    void* xposedLibHandle = dlopen(xposedLibPath, RTLD_NOW);
    if (!xposedLibHandle) {
        ALOGE("Could not load libxposed: %s", dlerror());
        return;
    }
 
    // Clear previous errors
    dlerror();
 
    // Initialize the library
    // dlsym 执行so文件中xposedInitLib函数,so文件就是上面被赋值的文件
    bool (*xposedInitLib)(XposedShared* shared) = NULL;
    *(void **) (&xposedInitLib) = dlsym(xposedLibHandle, "xposedInitLib");
    if (!xposedInitLib)  {
        ALOGE("Could not find function xposedInitLib");
        return;
    }
    // xposedInitLib函数如下,赋予xposed的onVmCreated为onVmCreatedCommon
    // 也就是libxposed_common.cpp的onVmCreatedCommon方法
 
    // bool xposedInitLib(XposedShared* shared) {
    //     xposed = shared;
    //     xposed->onVmCreated = &onVmCreatedCommon;
    //     return true;
    // }
 
#if XPOSED_WITH_SELINUX
    xposed->zygoteservice_accessFile = &service::membased::accessFile;
    xposed->zygoteservice_statFile   = &service::membased::statFile;
    xposed->zygoteservice_readFile   = &service::membased::readFile;
#endif  // XPOSED_WITH_SELINUX
    // 方法返回true,执行onVmCreatedCommon方法,到目前为止,流程都是相同的
    if (xposedInitLib(xposed)) {
        xposed->onVmCreated(env);
    }
}
// libxposed_common.cpp
// 两份文件公有部分
 
void onVmCreatedCommon(JNIEnv* env) {
    // 判断xposed_bridge.jar是否正常载入以及zygote服务启动是否正常
    if (!initXposedBridge(env) || !initZygoteService(env)) {
        return;
    }
    // 判断虚拟机是否正常启动,这里调用onVmCreated就是libxposed_xx.so文件中自己的onVmCreated函数了,这里应该就是第一个变化点
    if (!onVmCreated(env)) {
        return;
    }
    // 多重判断之后,返回xposed已正确安装标识
    xposedLoadedSuccessfully = true;
    return;
}
 
bool initXposedBridge(JNIEnv* env) {
    // #define CLASS_XPOSED_BRIDGE  "de/robv/android/xposed/XposedBridge"
    // 通过FindClass获取XposedBridge类,判断xposed_bridge类是否正常加载
    classXposedBridge = env->FindClass(CLASS_XPOSED_BRIDGE);
    if (classXposedBridge == NULL) {
        ALOGE("Error while loading Xposed class '%s':", CLASS_XPOSED_BRIDGE);
        logExceptionStackTrace();
        env->ExceptionClear();
        return false;
    }
    // PS:这里没有理解做了什么
    classXposedBridge = reinterpret_cast<jclass>(env->NewGlobalRef(classXposedBridge));
 
    ALOGI("Found Xposed class '%s', now initializing", CLASS_XPOSED_BRIDGE);
    // xposed_bridge的函数是否通过RegisterNatives动态注册成功
    if (register_natives_XposedBridge(env, classXposedBridge) != JNI_OK) {
        ALOGE("Could not register natives for '%s'", CLASS_XPOSED_BRIDGE);
        logExceptionStackTrace();
        env->ExceptionClear();
        return false;
    }
    // 判断通过jni获取handleHookedMethod函数是否成功
    methodXposedBridgeHandleHookedMethod = env->GetStaticMethodID(classXposedBridge, "handleHookedMethod",
        "(Ljava/lang/reflect/Member;ILjava/lang/Object;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;");
    if (methodXposedBridgeHandleHookedMethod == NULL) {
        ALOGE("ERROR: could not find method %s.handleHookedMethod(Member, int, Object, Object, Object[])", CLASS_XPOSED_BRIDGE);
        logExceptionStackTrace();
        env->ExceptionClear();
        return false;
    }
 
    return true;
}
 
int register_natives_XposedBridge(JNIEnv* env, jclass clazz) {
    // 动态注册XposedBridge相关的函数,形式如XposedBridge_hookMethodNative
    const JNINativeMethod methods[] = {
        NATIVE_METHOD(XposedBridge, hadInitErrors, "()Z"),
        NATIVE_METHOD(XposedBridge, getStartClassName, "()Ljava/lang/String;"),
        NATIVE_METHOD(XposedBridge, getRuntime, "()I"),
        NATIVE_METHOD(XposedBridge, startsSystemServer, "()Z"),
        NATIVE_METHOD(XposedBridge, getXposedVersion, "()I"),
        NATIVE_METHOD(XposedBridge, initXResourcesNative, "()Z"),
        // 关键函数,之后在findandhook中会涉及
        NATIVE_METHOD(XposedBridge, hookMethodNative, "(Ljava/lang/reflect/Member;Ljava/lang/Class;ILjava/lang/Object;)V"),
        NATIVE_METHOD(XposedBridge, setObjectClassNative, "(Ljava/lang/Object;Ljava/lang/Class;)V"),
        NATIVE_METHOD(XposedBridge, dumpObjectNative, "(Ljava/lang/Object;)V"),
        NATIVE_METHOD(XposedBridge, cloneToSubclassNative, "(Ljava/lang/Object;Ljava/lang/Class;)Ljava/lang/Object;"),
        NATIVE_METHOD(XposedBridge, removeFinalFlagNative, "(Ljava/lang/Class;)V"),
#if PLATFORM_SDK_VERSION >= 21
        NATIVE_METHOD(XposedBridge, invokeOriginalMethodNative,
            "!(Ljava/lang/reflect/Member;I[Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;"),
        NATIVE_METHOD(XposedBridge, closeFilesBeforeForkNative, "()V"),
        NATIVE_METHOD(XposedBridge, reopenFilesAfterForkNative, "()V"),
#endif
#if PLATFORM_SDK_VERSION >= 24
        NATIVE_METHOD(XposedBridge, invalidateCallersNative, "([Ljava/lang/reflect/Member;)V"),
#endif
    };
    return env->RegisterNatives(clazz, methods, NELEM(methods));
}
// libxposed_common.cpp
// 两份文件公有部分
 
void onVmCreatedCommon(JNIEnv* env) {
    // 判断xposed_bridge.jar是否正常载入以及zygote服务启动是否正常
    if (!initXposedBridge(env) || !initZygoteService(env)) {
        return;
    }
    // 判断虚拟机是否正常启动,这里调用onVmCreated就是libxposed_xx.so文件中自己的onVmCreated函数了,这里应该就是第一个变化点
    if (!onVmCreated(env)) {
        return;
    }
    // 多重判断之后,返回xposed已正确安装标识
    xposedLoadedSuccessfully = true;
    return;
}
 
bool initXposedBridge(JNIEnv* env) {
    // #define CLASS_XPOSED_BRIDGE  "de/robv/android/xposed/XposedBridge"
    // 通过FindClass获取XposedBridge类,判断xposed_bridge类是否正常加载
    classXposedBridge = env->FindClass(CLASS_XPOSED_BRIDGE);
    if (classXposedBridge == NULL) {
        ALOGE("Error while loading Xposed class '%s':", CLASS_XPOSED_BRIDGE);
        logExceptionStackTrace();
        env->ExceptionClear();
        return false;
    }
    // PS:这里没有理解做了什么
    classXposedBridge = reinterpret_cast<jclass>(env->NewGlobalRef(classXposedBridge));
 
    ALOGI("Found Xposed class '%s', now initializing", CLASS_XPOSED_BRIDGE);
    // xposed_bridge的函数是否通过RegisterNatives动态注册成功
    if (register_natives_XposedBridge(env, classXposedBridge) != JNI_OK) {
        ALOGE("Could not register natives for '%s'", CLASS_XPOSED_BRIDGE);
        logExceptionStackTrace();
        env->ExceptionClear();
        return false;
    }
    // 判断通过jni获取handleHookedMethod函数是否成功
    methodXposedBridgeHandleHookedMethod = env->GetStaticMethodID(classXposedBridge, "handleHookedMethod",
        "(Ljava/lang/reflect/Member;ILjava/lang/Object;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;");
    if (methodXposedBridgeHandleHookedMethod == NULL) {
        ALOGE("ERROR: could not find method %s.handleHookedMethod(Member, int, Object, Object, Object[])", CLASS_XPOSED_BRIDGE);
        logExceptionStackTrace();
        env->ExceptionClear();
        return false;
    }
 
    return true;
}
 
int register_natives_XposedBridge(JNIEnv* env, jclass clazz) {
    // 动态注册XposedBridge相关的函数,形式如XposedBridge_hookMethodNative
    const JNINativeMethod methods[] = {
        NATIVE_METHOD(XposedBridge, hadInitErrors, "()Z"),
        NATIVE_METHOD(XposedBridge, getStartClassName, "()Ljava/lang/String;"),
        NATIVE_METHOD(XposedBridge, getRuntime, "()I"),
        NATIVE_METHOD(XposedBridge, startsSystemServer, "()Z"),
        NATIVE_METHOD(XposedBridge, getXposedVersion, "()I"),
        NATIVE_METHOD(XposedBridge, initXResourcesNative, "()Z"),
        // 关键函数,之后在findandhook中会涉及
        NATIVE_METHOD(XposedBridge, hookMethodNative, "(Ljava/lang/reflect/Member;Ljava/lang/Class;ILjava/lang/Object;)V"),
        NATIVE_METHOD(XposedBridge, setObjectClassNative, "(Ljava/lang/Object;Ljava/lang/Class;)V"),
        NATIVE_METHOD(XposedBridge, dumpObjectNative, "(Ljava/lang/Object;)V"),
        NATIVE_METHOD(XposedBridge, cloneToSubclassNative, "(Ljava/lang/Object;Ljava/lang/Class;)Ljava/lang/Object;"),
        NATIVE_METHOD(XposedBridge, removeFinalFlagNative, "(Ljava/lang/Class;)V"),
#if PLATFORM_SDK_VERSION >= 21
        NATIVE_METHOD(XposedBridge, invokeOriginalMethodNative,
            "!(Ljava/lang/reflect/Member;I[Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;"),
        NATIVE_METHOD(XposedBridge, closeFilesBeforeForkNative, "()V"),
        NATIVE_METHOD(XposedBridge, reopenFilesAfterForkNative, "()V"),
#endif
#if PLATFORM_SDK_VERSION >= 24
        NATIVE_METHOD(XposedBridge, invalidateCallersNative, "([Ljava/lang/reflect/Member;)V"),
#endif
    };
    return env->RegisterNatives(clazz, methods, NELEM(methods));
}
// libxposed_dalvik.cpp
 
/** Called very early during VM startup. */
bool onVmCreated(JNIEnv* env) {
    if (!initMemberOffsets(env))
        return false;
    // #define CLASS_MIUI_RESOURCES "android/content/res/MiuiResources"
    jclass classMiuiResources = env->FindClass(CLASS_MIUI_RESOURCES);
    if (classMiuiResources != NULL) {
        ClassObject* clazz = (ClassObject*)dvmDecodeIndirectRef(dvmThreadSelf(), classMiuiResources);
        if (dvmIsFinalClass(clazz)) {
            ALOGD("Removing final flag for class '%s'", CLASS_MIUI_RESOURCES);
            clazz->accessFlags &= ~ACC_FINAL;
        }
    }
    env->ExceptionClear();
    // 关键点
    // 获取invokeOriginalMethodNative方法的jmethodId
    // 将invokeOriginalMethodNative的native方法关联到XposedBridge_invokeOriginalMethodNative方法,为后续调用的时候使用
    Method* xposedInvokeOriginalMethodNative = (Method*) env->GetStaticMethodID(classXposedBridge, "invokeOriginalMethodNative",
        "(Ljava/lang/reflect/Member;I[Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;");
    if (xposedInvokeOriginalMethodNative == NULL) {
        ALOGE("ERROR: could not find method %s.invokeOriginalMethodNative(Member, int, Class[], Class, Object, Object[])", CLASS_XPOSED_BRIDGE);
        dvmLogExceptionStackTrace();
        env->ExceptionClear();
        return false;
    }
    dvmSetNativeFunc(xposedInvokeOriginalMethodNative, XposedBridge_invokeOriginalMethodNative, NULL);
 
    objectArrayClass = dvmFindArrayClass("[Ljava/lang/Object;", NULL);
    if (objectArrayClass == NULL) {
        ALOGE("Error while loading Object[] class");
        dvmLogExceptionStackTrace();
        env->ExceptionClear();
        return false;
    }
 
    return true;
}
 
void XposedBridge_invokeOriginalMethodNative(const u4* args, JValue* pResult,
            const Method* method, ::Thread* self) {
    // 获取method
    Method* meth = (Method*) args[1];
    if (meth == NULL) {
        // 反射获取
        meth = dvmGetMethodFromReflectObj((Object*) args[0]);
        if (isMethodHooked(meth)) {
            meth = (Method*) meth->insns;
        }
    }
    ArrayObject* params = (ArrayObject*) args[2];
    ClassObject* returnType = (ClassObject*) args[3];
    Object* thisObject = (Object*) args[4]; // null for static methods
    ArrayObject* argList = (ArrayObject*) args[5];
 
    // invoke the method
    // 通过dvmInvokeMethod执行方法,dvmInvokeMethod是在虚拟机中执行java方法的方法,可以理解为c语言执行java方法
    pResult->l = dvmInvokeMethod(thisObject, meth, argList, params, returnType, true);
    return;
}
// libxposed_dalvik.cpp
 
/** Called very early during VM startup. */
bool onVmCreated(JNIEnv* env) {
    if (!initMemberOffsets(env))
        return false;
    // #define CLASS_MIUI_RESOURCES "android/content/res/MiuiResources"
    jclass classMiuiResources = env->FindClass(CLASS_MIUI_RESOURCES);
    if (classMiuiResources != NULL) {
        ClassObject* clazz = (ClassObject*)dvmDecodeIndirectRef(dvmThreadSelf(), classMiuiResources);
        if (dvmIsFinalClass(clazz)) {
            ALOGD("Removing final flag for class '%s'", CLASS_MIUI_RESOURCES);
            clazz->accessFlags &= ~ACC_FINAL;
        }
    }
    env->ExceptionClear();
    // 关键点
    // 获取invokeOriginalMethodNative方法的jmethodId
    // 将invokeOriginalMethodNative的native方法关联到XposedBridge_invokeOriginalMethodNative方法,为后续调用的时候使用
    Method* xposedInvokeOriginalMethodNative = (Method*) env->GetStaticMethodID(classXposedBridge, "invokeOriginalMethodNative",
        "(Ljava/lang/reflect/Member;I[Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;");
    if (xposedInvokeOriginalMethodNative == NULL) {
        ALOGE("ERROR: could not find method %s.invokeOriginalMethodNative(Member, int, Class[], Class, Object, Object[])", CLASS_XPOSED_BRIDGE);
        dvmLogExceptionStackTrace();
        env->ExceptionClear();
        return false;
    }
    dvmSetNativeFunc(xposedInvokeOriginalMethodNative, XposedBridge_invokeOriginalMethodNative, NULL);
 
    objectArrayClass = dvmFindArrayClass("[Ljava/lang/Object;", NULL);
    if (objectArrayClass == NULL) {
        ALOGE("Error while loading Object[] class");
        dvmLogExceptionStackTrace();
        env->ExceptionClear();
        return false;
    }
 
    return true;
}
 
void XposedBridge_invokeOriginalMethodNative(const u4* args, JValue* pResult,
            const Method* method, ::Thread* self) {
    // 获取method
    Method* meth = (Method*) args[1];
    if (meth == NULL) {
        // 反射获取
        meth = dvmGetMethodFromReflectObj((Object*) args[0]);
        if (isMethodHooked(meth)) {
            meth = (Method*) meth->insns;
        }
    }
    ArrayObject* params = (ArrayObject*) args[2];
    ClassObject* returnType = (ClassObject*) args[3];
    Object* thisObject = (Object*) args[4]; // null for static methods
    ArrayObject* argList = (ArrayObject*) args[5];
 
    // invoke the method
    // 通过dvmInvokeMethod执行方法,dvmInvokeMethod是在虚拟机中执行java方法的方法,可以理解为c语言执行java方法
    pResult->l = dvmInvokeMethod(thisObject, meth, argList, params, returnType, true);
    return;
}
// libxposed_art.cpp
 
/** Called very early during VM startup. */
bool onVmCreated(JNIEnv*) {
    // 没有针对Resource的操作
    // TODO: Handle CLASS_MIUI_RESOURCES?
    // 为ArtMethod的两个属性赋值,而这个ArtMethod定义来自于Xposed的android_art
    // classXposedBridge和methodXposedBridgeHandleHookedMethod被赋值是在libxposed_common的initXposedBridge函数中
    // classXposedBridge = env->FindClass(CLASS_XPOSED_BRIDGE);
    // methodXposedBridgeHandleHookedMethod = env->GetStaticMethodID(classXposedBridge, "handleHookedMethod",
        "(Ljava/lang/reflect/Member;ILjava/lang/Object;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;");
    ArtMethod::xposed_callback_class = classXposedBridge;
    ArtMethod::xposed_callback_method = methodXposedBridgeHandleHookedMethod;
    return true;
}
// libxposed_art.cpp
 
/** Called very early during VM startup. */
bool onVmCreated(JNIEnv*) {
    // 没有针对Resource的操作
    // TODO: Handle CLASS_MIUI_RESOURCES?
    // 为ArtMethod的两个属性赋值,而这个ArtMethod定义来自于Xposed的android_art
    // classXposedBridge和methodXposedBridgeHandleHookedMethod被赋值是在libxposed_common的initXposedBridge函数中
    // classXposedBridge = env->FindClass(CLASS_XPOSED_BRIDGE);
    // methodXposedBridgeHandleHookedMethod = env->GetStaticMethodID(classXposedBridge, "handleHookedMethod",
        "(Ljava/lang/reflect/Member;ILjava/lang/Object;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;");
    ArtMethod::xposed_callback_class = classXposedBridge;
    ArtMethod::xposed_callback_method = methodXposedBridgeHandleHookedMethod;
    return true;
}
 
 
// xposed.cpp
 
/** Initialize Xposed (unless it is disabled). */
bool initialize(bool zygote, bool startSystemServer, const char* className, int argc, char* const argv[]) {
#if !defined(XPOSED_ENABLE_FOR_TOOLS)
    if (!zygote)
        return false;
#endif
 
    if (isMinimalFramework()) {
        ALOGI("Not loading Xposed for minimal framework (encrypted device)");
        return false;
    }
    // xposed结构体赋值
    xposed->zygote = zygote;
    xposed->startSystemServer = startSystemServer;
    xposed->startClassName = className;
    xposed->xposedVersionInt = xposedVersionInt;
// 针对selinux做的操作
#if XPOSED_WITH_SELINUX
    xposed->isSELinuxEnabled   = is_selinux_enabled() == 1;
    xposed->isSELinuxEnforcing = xposed->isSELinuxEnabled && security_getenforce() == 1;
#else
    xposed->isSELinuxEnabled   = false;
    xposed->isSELinuxEnforcing = false;
#endif  // XPOSED_WITH_SELINUX
 
    if (startSystemServer) {
        xposed::logcat::printStartupMarker();
    } else if (zygote) {
        // TODO Find a better solution for this
        // Give the primary Zygote process a little time to start first.
        // This also makes the log easier to read, as logs for the two Zygotes are not mixed up.
        sleep(10);
    }
    // 打印rom信息
    printRomInfo();
 
    if (startSystemServer) {
        // 在Android中一个UID的对应的就是一个可执行的程序,对于普通的程序其UID就是对应与GID,程序在Android系统留存期间,其UID不变。
        // xposed::service::startAll() fork子进程启动system context service和app context service
        // 启动xposed_service_system xposed_service_app
        if (!determineXposedInstallerUidGid() || !xposed::service::startAll()) {
            return false;
        }
        // fork调用xposed logcat进程,负责打印xposed日志
        xposed::logcat::start();
#if XPOSED_WITH_SELINUX
    } else if (xposed->isSELinuxEnabled) {
        // 启动xposed_zygote_service
        if (!xposed::service::startMembased()) {
            return false;
        }
#endif  // XPOSED_WITH_SELINUX
    }
 
#if XPOSED_WITH_SELINUX
    // Don't let any further forks access the Zygote service
    if (xposed->isSELinuxEnabled) {
        xposed::service::membased::restrictMemoryInheritance();
    }
#endif  // XPOSED_WITH_SELINUX
 
    // FIXME Zygote has no access to input devices, this would need to be check in system_server context
    if (zygote && !isSafemodeDisabled() && detectSafemodeTrigger(shouldSkipSafemodeDelay()))
        disableXposed();
 
    if (isDisabled() || (!zygote && shouldIgnoreCommand(argc, argv)))
        return false;
    // 把jar包加入到classpath当中
    return addJarToClasspath();
}
 
/** Add XposedBridge.jar to the Java classpath. */
bool addJarToClasspath() {
    ALOGI("-----------------");
 
    // Do we have a new version and are (re)starting zygote? Then load it!
    /*
    FIXME if you can
    if (xposed->startSystemServer && access(XPOSED_JAR_NEWVERSION, R_OK) == 0) {
        ALOGI("Found new Xposed jar version, activating it");
        if (rename(XPOSED_JAR_NEWVERSION, XPOSED_JAR) != 0) {
            ALOGE("Could not move %s to %s", XPOSED_JAR_NEWVERSION, XPOSED_JAR);
            return false;
        }
    }
    */
 
    if (access(XPOSED_JAR, R_OK) == 0) {
        // #define XPOSED_JAR "/system/framework/XposedBridge.jar"
        将xposed_bridge的jar加入classpath
        if (!addPathToEnv("CLASSPATH", XPOSED_JAR))
            return false;
 
        ALOGI("Added Xposed (%s) to CLASSPATH", XPOSED_JAR);
        return true;
    } else {
        ALOGE("ERROR: Could not access Xposed jar '%s'", XPOSED_JAR);
        return false;
    }
}
// xposed.cpp
 
/** Initialize Xposed (unless it is disabled). */
bool initialize(bool zygote, bool startSystemServer, const char* className, int argc, char* const argv[]) {
#if !defined(XPOSED_ENABLE_FOR_TOOLS)
    if (!zygote)
        return false;
#endif
 
    if (isMinimalFramework()) {
        ALOGI("Not loading Xposed for minimal framework (encrypted device)");
        return false;
    }
    // xposed结构体赋值
    xposed->zygote = zygote;
    xposed->startSystemServer = startSystemServer;
    xposed->startClassName = className;
    xposed->xposedVersionInt = xposedVersionInt;
// 针对selinux做的操作
#if XPOSED_WITH_SELINUX
    xposed->isSELinuxEnabled   = is_selinux_enabled() == 1;
    xposed->isSELinuxEnforcing = xposed->isSELinuxEnabled && security_getenforce() == 1;
#else
    xposed->isSELinuxEnabled   = false;
    xposed->isSELinuxEnforcing = false;
#endif  // XPOSED_WITH_SELINUX
 
    if (startSystemServer) {
        xposed::logcat::printStartupMarker();
    } else if (zygote) {
        // TODO Find a better solution for this
        // Give the primary Zygote process a little time to start first.
        // This also makes the log easier to read, as logs for the two Zygotes are not mixed up.
        sleep(10);
    }
    // 打印rom信息
    printRomInfo();
 
    if (startSystemServer) {
        // 在Android中一个UID的对应的就是一个可执行的程序,对于普通的程序其UID就是对应与GID,程序在Android系统留存期间,其UID不变。
        // xposed::service::startAll() fork子进程启动system context service和app context service
        // 启动xposed_service_system xposed_service_app
        if (!determineXposedInstallerUidGid() || !xposed::service::startAll()) {
            return false;
        }
        // fork调用xposed logcat进程,负责打印xposed日志
        xposed::logcat::start();
#if XPOSED_WITH_SELINUX
    } else if (xposed->isSELinuxEnabled) {
        // 启动xposed_zygote_service
        if (!xposed::service::startMembased()) {
            return false;
        }
#endif  // XPOSED_WITH_SELINUX
    }
 
#if XPOSED_WITH_SELINUX
    // Don't let any further forks access the Zygote service
    if (xposed->isSELinuxEnabled) {
        xposed::service::membased::restrictMemoryInheritance();
    }
#endif  // XPOSED_WITH_SELINUX
 
    // FIXME Zygote has no access to input devices, this would need to be check in system_server context
    if (zygote && !isSafemodeDisabled() && detectSafemodeTrigger(shouldSkipSafemodeDelay()))
        disableXposed();
 
    if (isDisabled() || (!zygote && shouldIgnoreCommand(argc, argv)))
        return false;
    // 把jar包加入到classpath当中
    return addJarToClasspath();
}
 
/** Add XposedBridge.jar to the Java classpath. */
bool addJarToClasspath() {
    ALOGI("-----------------");
 
    // Do we have a new version and are (re)starting zygote? Then load it!
    /*
    FIXME if you can
    if (xposed->startSystemServer && access(XPOSED_JAR_NEWVERSION, R_OK) == 0) {
        ALOGI("Found new Xposed jar version, activating it");
        if (rename(XPOSED_JAR_NEWVERSION, XPOSED_JAR) != 0) {
            ALOGE("Could not move %s to %s", XPOSED_JAR_NEWVERSION, XPOSED_JAR);
            return false;
        }
    }
    */
 
    if (access(XPOSED_JAR, R_OK) == 0) {
        // #define XPOSED_JAR "/system/framework/XposedBridge.jar"
        将xposed_bridge的jar加入classpath
        if (!addPathToEnv("CLASSPATH", XPOSED_JAR))
            return false;
 
        ALOGI("Added Xposed (%s) to CLASSPATH", XPOSED_JAR);
        return true;
    } else {
        ALOGE("ERROR: Could not access Xposed jar '%s'", XPOSED_JAR);
        return false;
    }
}
// frameworks/base/core/jni/AndroidRuntime.cpp
 
// runtime.start()函数
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    ALOGD(">>>>>> START %s uid %d <<<<<<\n",
            className != NULL ? className : "(unknown)", getuid());
 
    static const String8 startSystemServer("start-system-server");
 
    /*
     * 'startSystemServer == true' means runtime is obsolete and not run from
     * init.rc anymore, so we print out the boot start event here.
     */
    for (size_t i = 0; i < options.size(); ++i) {
        if (options[i] == startSystemServer) {
           /* track our progress through the boot sequence */
           const int LOG_BOOT_PROGRESS_START = 3000;
           LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,  ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
        }
    }
 
    const char* rootDir = getenv("ANDROID_ROOT");
    if (rootDir == NULL) {
        rootDir = "/system";
        if (!hasDir("/system")) {
            LOG_FATAL("No root directory specified, and /android does not exist.");
            return;
        }
        setenv("ANDROID_ROOT", rootDir, 1);
    }
 
    //const char* kernelHack = getenv("LD_ASSUME_KERNEL");
    //ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);
 
    /* start the virtual machine */
    JniInvocation jni_invocation;
    // 加载虚拟机的核心库
    // 没有具体分析,加载的是libart.so/libdalvik.so
    jni_invocation.Init(NULL);
    JNIEnv* env;
    // 创建虚拟机
    if (startVm(&mJavaVM, &env, zygote) != 0) {
        return;
    }
    // 这个函数被xposed替换
    onVmCreated(env);
 
    /*
     * Register android functions.
     */
    // 注册andorid native函数
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        return;
    }
 
    /*
     * We want to call main() with a String array with arguments in it.
     * At present we have two arguments, the class name and an option string.
     * Create an array to hold them.
     */
    jclass stringClass;
    jobjectArray strArray;
    jstring classNameStr;
    // 可以理解为为字符串申请空间
    stringClass = env->FindClass("java/lang/String");
    assert(stringClass != NULL);
    strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
    assert(strArray != NULL);
    classNameStr = env->NewStringUTF(className);
    assert(classNameStr != NULL);
    env->SetObjectArrayElement(strArray, 0, classNameStr);
 
    for (size_t i = 0; i < options.size(); ++i) {
        jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());
        assert(optionsStr != NULL);
        env->SetObjectArrayElement(strArray, i + 1, optionsStr);
    }
 
    /*
     * Start VM.  This thread becomes the main thread of the VM, and will
     * not return until the VM exits.
     */
    char* slashClassName = toSlashClassName(className);
    // 获取字符串对应的类,此时类为xposed_bridge类,由于在initialize方法中已经被加入到classpath中,因此可以获取到
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
        /* keep going */
    } else {
        // 获取类的main方法jmethodID
        jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
            "([Ljava/lang/String;)V");
        if (startMeth == NULL) {
            ALOGE("JavaVM unable to find main() in '%s'\n", className);
            /* keep going */
        } else {
            // 执行main函数
            env->CallStaticVoidMethod(startClass, startMeth, strArray);
 
#if 0
            if (env->ExceptionCheck())
                threadExitUncaughtException(env);
#endif
        }
    }
    free(slashClassName);
 
    ALOGD("Shutting down VM\n");
    if (mJavaVM->DetachCurrentThread() != JNI_OK)
        ALOGW("Warning: unable to detach main thread\n");
    if (mJavaVM->DestroyJavaVM() != 0)
        ALOGW("Warning: VM did not shut down cleanly\n");
}
// frameworks/base/core/jni/AndroidRuntime.cpp
 
// runtime.start()函数
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    ALOGD(">>>>>> START %s uid %d <<<<<<\n",
            className != NULL ? className : "(unknown)", getuid());
 
    static const String8 startSystemServer("start-system-server");
 
    /*
     * 'startSystemServer == true' means runtime is obsolete and not run from
     * init.rc anymore, so we print out the boot start event here.
     */
    for (size_t i = 0; i < options.size(); ++i) {
        if (options[i] == startSystemServer) {
           /* track our progress through the boot sequence */
           const int LOG_BOOT_PROGRESS_START = 3000;
           LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,  ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
        }
    }
 
    const char* rootDir = getenv("ANDROID_ROOT");
    if (rootDir == NULL) {
        rootDir = "/system";
        if (!hasDir("/system")) {
            LOG_FATAL("No root directory specified, and /android does not exist.");
            return;
        }
        setenv("ANDROID_ROOT", rootDir, 1);
    }
 
    //const char* kernelHack = getenv("LD_ASSUME_KERNEL");
    //ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);
 
    /* start the virtual machine */
    JniInvocation jni_invocation;
    // 加载虚拟机的核心库
    // 没有具体分析,加载的是libart.so/libdalvik.so
    jni_invocation.Init(NULL);
    JNIEnv* env;
    // 创建虚拟机
    if (startVm(&mJavaVM, &env, zygote) != 0) {
        return;
    }
    // 这个函数被xposed替换
    onVmCreated(env);
 
    /*
     * Register android functions.
     */
    // 注册andorid native函数
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        return;
    }
 
    /*
     * We want to call main() with a String array with arguments in it.
     * At present we have two arguments, the class name and an option string.
     * Create an array to hold them.
     */
    jclass stringClass;
    jobjectArray strArray;
    jstring classNameStr;
    // 可以理解为为字符串申请空间
    stringClass = env->FindClass("java/lang/String");
    assert(stringClass != NULL);
    strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
    assert(strArray != NULL);
    classNameStr = env->NewStringUTF(className);
    assert(classNameStr != NULL);
    env->SetObjectArrayElement(strArray, 0, classNameStr);
 
    for (size_t i = 0; i < options.size(); ++i) {
        jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());
        assert(optionsStr != NULL);
        env->SetObjectArrayElement(strArray, i + 1, optionsStr);
    }
 
    /*
     * Start VM.  This thread becomes the main thread of the VM, and will
     * not return until the VM exits.
     */
    char* slashClassName = toSlashClassName(className);
    // 获取字符串对应的类,此时类为xposed_bridge类,由于在initialize方法中已经被加入到classpath中,因此可以获取到
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
        /* keep going */
    } else {
        // 获取类的main方法jmethodID
        jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
            "([Ljava/lang/String;)V");
        if (startMeth == NULL) {
            ALOGE("JavaVM unable to find main() in '%s'\n", className);
            /* keep going */
        } else {
            // 执行main函数
            env->CallStaticVoidMethod(startClass, startMeth, strArray);
 
#if 0
            if (env->ExceptionCheck())
                threadExitUncaughtException(env);
#endif
        }
    }
    free(slashClassName);
 
    ALOGD("Shutting down VM\n");
    if (mJavaVM->DetachCurrentThread() != JNI_OK)
        ALOGW("Warning: unable to detach main thread\n");
    if (mJavaVM->DestroyJavaVM() != 0)
        ALOGW("Warning: VM did not shut down cleanly\n");
}
// XposedBridge/XposedBridge.java
 
@SuppressWarnings("deprecation")
protected static void main(String[] args) {
    // Initialize the Xposed framework and modules
    // XposedBridge的入口
    try {
        if (!hadInitErrors()) {
            // 获取资源文件
            initXResources();
 
            SELinuxHelper.initOnce();
            SELinuxHelper.initForProcess(null);
 
            runtime = getRuntime();
            XPOSED_BRIDGE_VERSION = getXposedVersion();
            // 三个关键步骤
            if (isZygote) {
                // 针对资源文件的hook
                XposedInit.hookResources();
                // 针对方法的hook
                XposedInit.initForZygote();
            }
            // 加载hook模块列表的模块
            XposedInit.loadModules();
        } else {
            Log.e(TAG, "Not initializing Xposed because of previous errors");
        }
    } catch (Throwable t) {
        Log.e(TAG, "Errors during Xposed initialization", t);
        disableHooks = true;
    }
 
    // Call the original startup code
    // 最后回到了基本的zygote启动流程,不影响正常的启动,之前的操作都是为了hook的初始化
    if (isZygote) {
        ZygoteInit.main(args);
    } else {
        RuntimeInit.main(args);
    }
}
// XposedBridge/XposedBridge.java
 
@SuppressWarnings("deprecation")
protected static void main(String[] args) {
    // Initialize the Xposed framework and modules
    // XposedBridge的入口
    try {
        if (!hadInitErrors()) {
            // 获取资源文件
            initXResources();
 
            SELinuxHelper.initOnce();
            SELinuxHelper.initForProcess(null);
 
            runtime = getRuntime();
            XPOSED_BRIDGE_VERSION = getXposedVersion();
            // 三个关键步骤
            if (isZygote) {
                // 针对资源文件的hook
                XposedInit.hookResources();
                // 针对方法的hook
                XposedInit.initForZygote();
            }
            // 加载hook模块列表的模块
            XposedInit.loadModules();
        } else {
            Log.e(TAG, "Not initializing Xposed because of previous errors");
        }
    } catch (Throwable t) {
        Log.e(TAG, "Errors during Xposed initialization", t);
        disableHooks = true;
    }
 
    // Call the original startup code
    // 最后回到了基本的zygote启动流程,不影响正常的启动,之前的操作都是为了hook的初始化
    if (isZygote) {
        ZygoteInit.main(args);
    } else {
        RuntimeInit.main(args);
    }
}
// XposedBridge/XposedInit.java
 
if (needsToCloseFilesForFork()) {
    // 匿名内部类实例化XC_MethodHook抽象类
    XC_MethodHook callback = new XC_MethodHook() {
        @Override
        protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
            XposedBridge.closeFilesBeforeForkNative();
        }
 
        @Override
        protected void afterHookedMethod(MethodHookParam param) throws Throwable {
            XposedBridge.reopenFilesAfterForkNative();
        }
    };
 
    Class<?> zygote = findClass("com.android.internal.os.Zygote", null);
    // hook nativeForkAndSpecialize
    // nativeForkAndSpecialize是Zygote的forkAndSpecialize的底层实现,调用fork()创建新进程,设置新进程的主线程id,重置gc性能数据,设置信号处理函数等功能
    hookAllMethods(zygote, "nativeForkAndSpecialize", callback);
    // hook nativeForkSystemServer
    // forkSystemServer是由Zygote的forkSystemServer的底层实现,调用fork()创建system server服务
    hookAllMethods(zygote, "nativeForkSystemServer", callback);
}
// XposedBridge/XposedInit.java
 
if (needsToCloseFilesForFork()) {
    // 匿名内部类实例化XC_MethodHook抽象类
    XC_MethodHook callback = new XC_MethodHook() {
        @Override
        protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
            XposedBridge.closeFilesBeforeForkNative();
        }
 
        @Override
        protected void afterHookedMethod(MethodHookParam param) throws Throwable {
            XposedBridge.reopenFilesAfterForkNative();
        }
    };
 
    Class<?> zygote = findClass("com.android.internal.os.Zygote", null);
    // hook nativeForkAndSpecialize
    // nativeForkAndSpecialize是Zygote的forkAndSpecialize的底层实现,调用fork()创建新进程,设置新进程的主线程id,重置gc性能数据,设置信号处理函数等功能
    hookAllMethods(zygote, "nativeForkAndSpecialize", callback);
    // hook nativeForkSystemServer
    // forkSystemServer是由Zygote的forkSystemServer的底层实现,调用fork()创建system server服务
    hookAllMethods(zygote, "nativeForkSystemServer", callback);
}
 
// libxposed_common.cpp
 
#if PLATFORM_SDK_VERSION >= 21
        NATIVE_METHOD(XposedBridge, invokeOriginalMethodNative,
            "!(Ljava/lang/reflect/Member;I[Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;"),
        NATIVE_METHOD(XposedBridge, closeFilesBeforeForkNative, "()V"),
        NATIVE_METHOD(XposedBridge, reopenFilesAfterForkNative, "()V"),
#endif
 
// libxposed_art.cpp
 
// 不太清楚做了什么
void XposedBridge_closeFilesBeforeForkNative(JNIEnv*, jclass) {
    gClosedFdTable = FileDescriptorTable::Create();
}
 
void XposedBridge_reopenFilesAfterForkNative(JNIEnv*, jclass) {
    gClosedFdTable->Reopen();
    delete gClosedFdTable;
    gClosedFdTable = NULL;
}
// libxposed_common.cpp
 
#if PLATFORM_SDK_VERSION >= 21
        NATIVE_METHOD(XposedBridge, invokeOriginalMethodNative,
            "!(Ljava/lang/reflect/Member;I[Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;"),
        NATIVE_METHOD(XposedBridge, closeFilesBeforeForkNative, "()V"),
        NATIVE_METHOD(XposedBridge, reopenFilesAfterForkNative, "()V"),
#endif
 
// libxposed_art.cpp
 
// 不太清楚做了什么
void XposedBridge_closeFilesBeforeForkNative(JNIEnv*, jclass) {
    gClosedFdTable = FileDescriptorTable::Create();
}
 
void XposedBridge_reopenFilesAfterForkNative(JNIEnv*, jclass) {
    gClosedFdTable->Reopen();
    delete gClosedFdTable;
    gClosedFdTable = NULL;
}
// normal process initialization (for new Activity, Service, BroadcastReceiver etc.)
// hook ActivityThread.handleBindApplication()方法的hook
findAndHookMethod(ActivityThread.class, "handleBindApplication", "android.app.ActivityThread.AppBindData", new XC_MethodHook() {
    @Override
    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
        // 获取activityThread
        ActivityThread activityThread = (ActivityThread) param.thisObject;
        // 获取AppBindData的appInfo
        ApplicationInfo appInfo = (ApplicationInfo) getObjectField(param.args[0], "appInfo");
        String reportedPackageName = appInfo.packageName.equals("android") ? "system" : appInfo.packageName;
        SELinuxHelper.initForProcess(reportedPackageName);
        // 获取AppBindData的instrumentationName
        ComponentName instrumentationName = (ComponentName) getObjectField(param.args[0], "instrumentationName");
        if (instrumentationName != null) {
            Log.w(TAG, "Instrumentation detected, disabling framework for " + reportedPackageName);
            XposedBridge.disableHooks = true;
            return;
        }
        CompatibilityInfo compatInfo = (CompatibilityInfo) getObjectField(param.args[0], "compatInfo");
        if (appInfo.sourceDir == null)
            return;
        // 设置mBoundApplication属性为AppBindData
        setObjectField(activityThread, "mBoundApplication", param.args[0]);
        loadedPackagesInProcess.add(reportedPackageName);
        // 通过activityThread获取当前已加载的apk
        LoadedApk loadedApk = activityThread.getPackageInfoNoCheck(appInfo, compatInfo);
        XResources.setPackageNameForResDir(appInfo.packageName, loadedApk.getResDir());
        // 打包成LoadPackageParam对象
        XC_LoadPackage.LoadPackageParam lpparam = new XC_LoadPackage.LoadPackageParam(XposedBridge.sLoadedPackageCallbacks);
        lpparam.packageName = reportedPackageName;
        lpparam.processName = (String) getObjectField(param.args[0], "processName");
        lpparam.classLoader = loadedApk.getClassLoader();
        lpparam.appInfo = appInfo;
        lpparam.isFirstApplication = true;
        // 针对lpparam的所有callback函数进行调用
        XC_LoadPackage.callAll(lpparam);
 
        if (reportedPackageName.equals(INSTALLER_PACKAGE_NAME))
            hookXposedInstaller(lpparam.classLoader);
    }
});
 
// XCallback.java
public static void callAll(Param param) {
    if (param.callbacks == null)
        throw new IllegalStateException("This object was not created for use with callAll");
    // 调用每个参数的callbacks数组每个对象的call方法
    for (int i = 0; i < param.callbacks.length; i++) {
        try {
            ((XCallback) param.callbacks[i]).call(param);
        } catch (Throwable t) { XposedBridge.log(t); }
    }
}
 
// XC_LoadPackage.java
@Override
protected void call(Param param) throws Throwable {
    // 也就是调用callbacks数组每个对象的handleLoadPackage方法
    if (param instanceof LoadPackageParam)
        handleLoadPackage((LoadPackageParam) param);
}
// normal process initialization (for new Activity, Service, BroadcastReceiver etc.)
// hook ActivityThread.handleBindApplication()方法的hook
findAndHookMethod(ActivityThread.class, "handleBindApplication", "android.app.ActivityThread.AppBindData", new XC_MethodHook() {
    @Override
    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
        // 获取activityThread
        ActivityThread activityThread = (ActivityThread) param.thisObject;
        // 获取AppBindData的appInfo
        ApplicationInfo appInfo = (ApplicationInfo) getObjectField(param.args[0], "appInfo");
        String reportedPackageName = appInfo.packageName.equals("android") ? "system" : appInfo.packageName;
        SELinuxHelper.initForProcess(reportedPackageName);
        // 获取AppBindData的instrumentationName
        ComponentName instrumentationName = (ComponentName) getObjectField(param.args[0], "instrumentationName");
        if (instrumentationName != null) {
            Log.w(TAG, "Instrumentation detected, disabling framework for " + reportedPackageName);
            XposedBridge.disableHooks = true;
            return;
        }
        CompatibilityInfo compatInfo = (CompatibilityInfo) getObjectField(param.args[0], "compatInfo");
        if (appInfo.sourceDir == null)
            return;
        // 设置mBoundApplication属性为AppBindData
        setObjectField(activityThread, "mBoundApplication", param.args[0]);
        loadedPackagesInProcess.add(reportedPackageName);
        // 通过activityThread获取当前已加载的apk
        LoadedApk loadedApk = activityThread.getPackageInfoNoCheck(appInfo, compatInfo);
        XResources.setPackageNameForResDir(appInfo.packageName, loadedApk.getResDir());
        // 打包成LoadPackageParam对象
        XC_LoadPackage.LoadPackageParam lpparam = new XC_LoadPackage.LoadPackageParam(XposedBridge.sLoadedPackageCallbacks);
        lpparam.packageName = reportedPackageName;
        lpparam.processName = (String) getObjectField(param.args[0], "processName");
        lpparam.classLoader = loadedApk.getClassLoader();
        lpparam.appInfo = appInfo;
        lpparam.isFirstApplication = true;
        // 针对lpparam的所有callback函数进行调用
        XC_LoadPackage.callAll(lpparam);
 
        if (reportedPackageName.equals(INSTALLER_PACKAGE_NAME))
            hookXposedInstaller(lpparam.classLoader);
    }
});
 
// XCallback.java
public static void callAll(Param param) {
    if (param.callbacks == null)
        throw new IllegalStateException("This object was not created for use with callAll");
    // 调用每个参数的callbacks数组每个对象的call方法
    for (int i = 0; i < param.callbacks.length; i++) {
        try {
            ((XCallback) param.callbacks[i]).call(param);
        } catch (Throwable t) { XposedBridge.log(t); }
    }
}
 
// XC_LoadPackage.java
@Override
protected void call(Param param) throws Throwable {
    // 也就是调用callbacks数组每个对象的handleLoadPackage方法
    if (param instanceof LoadPackageParam)
        handleLoadPackage((LoadPackageParam) param);
}
public void handleLoadPackage(final XC_LoadPackage.LoadPackageParam lpparam) throws Throwable
public void handleLoadPackage(final XC_LoadPackage.LoadPackageParam lpparam) throws Throwable
// XposedBridge/XposedBridge.java
 
public static void hookLoadPackage(XC_LoadPackage callback) {
    synchronized (sLoadedPackageCallbacks) {
        sLoadedPackageCallbacks.add(callback);
    }
}
// XposedBridge/XposedBridge.java
 
public static void hookLoadPackage(XC_LoadPackage callback) {
    synchronized (sLoadedPackageCallbacks) {
        sLoadedPackageCallbacks.add(callback);
    }
}
// system_server initialization
// 主要是对system_server做处理
if (Build.VERSION.SDK_INT < 21) {
    findAndHookMethod("com.android.server.ServerThread", null,
                      Build.VERSION.SDK_INT < 19 ? "run" : "initAndLoop", new XC_MethodHook() {
                          @Override
                          protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                              SELinuxHelper.initForProcess("android");
                              loadedPackagesInProcess.add("android");
                              // 道理同上
                              XC_LoadPackage.LoadPackageParam lpparam = new XC_LoadPackage.LoadPackageParam(XposedBridge.sLoadedPackageCallbacks);
                              lpparam.packageName = "android";
                              lpparam.processName = "android"; // it's actually system_server, but other functions return this as well
                              lpparam.classLoader = XposedBridge.BOOTCLASSLOADER;
                              lpparam.appInfo = null;
                              lpparam.isFirstApplication = true;
                              XC_LoadPackage.callAll(lpparam);
                          }
                      });
} else if (startsSystemServer) {
    findAndHookMethod(ActivityThread.class, "systemMain", new XC_MethodHook() {
        @Override
        protected void afterHookedMethod(MethodHookParam param) throws Throwable {
            final ClassLoader cl = Thread.currentThread().getContextClassLoader();
            findAndHookMethod("com.android.server.SystemServer", cl, "startBootstrapServices", new XC_MethodHook() {
                @Override
                protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                    SELinuxHelper.initForProcess("android");
                    loadedPackagesInProcess.add("android");
                    // 道理同上
                    XC_LoadPackage.LoadPackageParam lpparam = new XC_LoadPackage.LoadPackageParam(XposedBridge.sLoadedPackageCallbacks);
                    lpparam.packageName = "android";
                    lpparam.processName = "android"; // it's actually system_server, but other functions return this as well
                    lpparam.classLoader = cl;
                    lpparam.appInfo = null;
                    lpparam.isFirstApplication = true;
                    XC_LoadPackage.callAll(lpparam);
                }
            });
        }
    });
}
// system_server initialization
// 主要是对system_server做处理
if (Build.VERSION.SDK_INT < 21) {
    findAndHookMethod("com.android.server.ServerThread", null,
                      Build.VERSION.SDK_INT < 19 ? "run" : "initAndLoop", new XC_MethodHook() {
                          @Override
                          protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                              SELinuxHelper.initForProcess("android");
                              loadedPackagesInProcess.add("android");
                              // 道理同上
                              XC_LoadPackage.LoadPackageParam lpparam = new XC_LoadPackage.LoadPackageParam(XposedBridge.sLoadedPackageCallbacks);
                              lpparam.packageName = "android";
                              lpparam.processName = "android"; // it's actually system_server, but other functions return this as well
                              lpparam.classLoader = XposedBridge.BOOTCLASSLOADER;
                              lpparam.appInfo = null;
                              lpparam.isFirstApplication = true;
                              XC_LoadPackage.callAll(lpparam);
                          }
                      });
} else if (startsSystemServer) {
    findAndHookMethod(ActivityThread.class, "systemMain", new XC_MethodHook() {
        @Override
        protected void afterHookedMethod(MethodHookParam param) throws Throwable {
            final ClassLoader cl = Thread.currentThread().getContextClassLoader();
            findAndHookMethod("com.android.server.SystemServer", cl, "startBootstrapServices", new XC_MethodHook() {
                @Override
                protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                    SELinuxHelper.initForProcess("android");
                    loadedPackagesInProcess.add("android");
                    // 道理同上
                    XC_LoadPackage.LoadPackageParam lpparam = new XC_LoadPackage.LoadPackageParam(XposedBridge.sLoadedPackageCallbacks);
                    lpparam.packageName = "android";
                    lpparam.processName = "android"; // it's actually system_server, but other functions return this as well
                    lpparam.classLoader = cl;
                    lpparam.appInfo = null;
                    lpparam.isFirstApplication = true;
                    XC_LoadPackage.callAll(lpparam);
                }
            });
        }
    });
}
// XposedBridge/XposedInit
 
static void loadModules() throws IOException {
    final String filename = BASE_DIR + "conf/modules.list";
    BaseService service = SELinuxHelper.getAppDataFileService();
    if (!service.checkFileExists(filename)) {
        Log.e(TAG, "Cannot load any modules because " + filename + " was not found");
        return;
    }
    // public static final ClassLoader BOOTCLASSLOADER = ClassLoader.getSystemClassLoader();
    // 获取classloader
    ClassLoader topClassLoader = XposedBridge.BOOTCLASSLOADER;
    ClassLoader parent;
    while ((parent = topClassLoader.getParent()) != null) {
        topClassLoader = parent;
    }
 
    InputStream stream = service.getFileInputStream(filename);
    BufferedReader apks = new BufferedReader(new InputStreamReader(stream));
    String apk;
    // 每行读取apk,调用loadMudle()
    while ((apk = apks.readLine()) != null) {
        loadModule(apk, topClassLoader);
    }
    apks.close();
}
// XposedBridge/XposedInit
 
static void loadModules() throws IOException {
    final String filename = BASE_DIR + "conf/modules.list";
    BaseService service = SELinuxHelper.getAppDataFileService();
    if (!service.checkFileExists(filename)) {
        Log.e(TAG, "Cannot load any modules because " + filename + " was not found");
        return;
    }
    // public static final ClassLoader BOOTCLASSLOADER = ClassLoader.getSystemClassLoader();
    // 获取classloader
    ClassLoader topClassLoader = XposedBridge.BOOTCLASSLOADER;
    ClassLoader parent;
    while ((parent = topClassLoader.getParent()) != null) {
        topClassLoader = parent;
    }
 
    InputStream stream = service.getFileInputStream(filename);
    BufferedReader apks = new BufferedReader(new InputStreamReader(stream));
    String apk;
    // 每行读取apk,调用loadMudle()
    while ((apk = apks.readLine()) != null) {
        loadModule(apk, topClassLoader);
    }
    apks.close();
}
// XposedBridge/XposedInit
 
private static void loadModule(String apk, ClassLoader topClassLoader) {
    Log.i(TAG, "Loading modules from " + apk);
    // 判断Xposed模块是否存在
    if (!new File(apk).exists()) {
        Log.e(TAG, "  File does not exist");
        return;
    }
 
    DexFile dexFile;
    try {
        dexFile = new DexFile(apk);
    } catch (IOException e) {
        Log.e(TAG, "  Cannot load module", e);
        return;
    }
 
    if (dexFile.loadClass(INSTANT_RUN_CLASS, topClassLoader) != null) {
        Log.e(TAG, "  Cannot load module, please disable \"Instant Run\" in Android Studio.");
        closeSilently(dexFile);
        return;
    }
 
    if (dexFile.loadClass(XposedBridge.class.getName(), topClassLoader) != null) {
        Log.e(TAG, "  Cannot load module:");
        Log.e(TAG, "  The Xposed API classes are compiled into the module's APK.");
        Log.e(TAG, "  This may cause strange issues and must be fixed by the module developer.");
        Log.e(TAG, "  For details, see: http://api.xposed.info/using.html");
        closeSilently(dexFile);
        return;
    }
 
    closeSilently(dexFile);
 
    ZipFile zipFile = null;
    InputStream is;
    try {
        zipFile = new ZipFile(apk);
        // 获取模块中的assets/xposed_init,也就是我们开发过程中指定Xposed入口的文件
        ZipEntry zipEntry = zipFile.getEntry("assets/xposed_init");
        if (zipEntry == null) {
            Log.e(TAG, "  assets/xposed_init not found in the APK");
            closeSilently(zipFile);
            return;
        }
        is = zipFile.getInputStream(zipEntry);
    } catch (IOException e) {
        Log.e(TAG, "  Cannot read assets/xposed_init in the APK", e);
        closeSilently(zipFile);
        return;
    }
 
    ClassLoader mcl = new PathClassLoader(apk, XposedBridge.BOOTCLASSLOADER);
    // 读取assets/xposed_init文件
    BufferedReader moduleClassesReader = new BufferedReader(new InputStreamReader(is));
    try {
        String moduleClassName;
        while ((moduleClassName = moduleClassesReader.readLine()) != null) {
            moduleClassName = moduleClassName.trim();
            if (moduleClassName.isEmpty() || moduleClassName.startsWith("#"))
                continue;
 
            try {
                // 获取Xposed模块入口类名
                Log.i(TAG, "  Loading class " + moduleClassName);
                Class<?> moduleClass = mcl.loadClass(moduleClassName);
 
                if (!IXposedMod.class.isAssignableFrom(moduleClass)) {
                    Log.e(TAG, "    This class doesn't implement any sub-interface of IXposedMod, skipping it");
                    continue;
                } else if (disableResources && IXposedHookInitPackageResources.class.isAssignableFrom(moduleClass)) {
                    Log.e(TAG, "    This class requires resource-related hooks (which are disabled), skipping it.");
                    continue;
                }
                // 获取实例
                final Object moduleInstance = moduleClass.newInstance();
                if (XposedBridge.isZygote) {
                    if (moduleInstance instanceof IXposedHookZygoteInit) {
                        IXposedHookZygoteInit.StartupParam param = new IXposedHookZygoteInit.StartupParam();
                        param.modulePath = apk;
                        param.startsSystemServer = startsSystemServer;
                        ((IXposedHookZygoteInit) moduleInstance).initZygote(param);
                    }
 
                    if (moduleInstance instanceof IXposedHookLoadPackage)
                        // 调用内部类IXposedHookLoadPackage.Wrapper构造方法生成XC_LoadPackage类,就可以被hookLoadPackage调用
                        XposedBridge.hookLoadPackage(new IXposedHookLoadPackage.Wrapper((IXposedHookLoadPackage) moduleInstance));
 
                    if (moduleInstance instanceof IXposedHookInitPackageResources)
                        XposedBridge.hookInitPackageResources(new IXposedHookInitPackageResources.Wrapper((IXposedHookInitPackageResources) moduleInstance));
                } else {
                    if (moduleInstance instanceof IXposedHookCmdInit) {
                        IXposedHookCmdInit.StartupParam param = new IXposedHookCmdInit.StartupParam();
                        param.modulePath = apk;
                        param.startClassName = startClassName;
                        ((IXposedHookCmdInit) moduleInstance).initCmdApp(param);
                    }
                }
            } catch (Throwable t) {
                Log.e(TAG, "    Failed to load class " + moduleClassName, t);
            }
        }
    } catch (IOException e) {
        Log.e(TAG, "  Failed to load module from " + apk, e);
    } finally {
        closeSilently(is);
        closeSilently(zipFile);
    }
}
}
// XposedBridge/XposedInit
 
private static void loadModule(String apk, ClassLoader topClassLoader) {
    Log.i(TAG, "Loading modules from " + apk);
    // 判断Xposed模块是否存在
    if (!new File(apk).exists()) {
        Log.e(TAG, "  File does not exist");
        return;
    }
 
    DexFile dexFile;
    try {
        dexFile = new DexFile(apk);
    } catch (IOException e) {
        Log.e(TAG, "  Cannot load module", e);
        return;
    }
 
    if (dexFile.loadClass(INSTANT_RUN_CLASS, topClassLoader) != null) {
        Log.e(TAG, "  Cannot load module, please disable \"Instant Run\" in Android Studio.");
        closeSilently(dexFile);
        return;
    }
 
    if (dexFile.loadClass(XposedBridge.class.getName(), topClassLoader) != null) {
        Log.e(TAG, "  Cannot load module:");
        Log.e(TAG, "  The Xposed API classes are compiled into the module's APK.");
        Log.e(TAG, "  This may cause strange issues and must be fixed by the module developer.");
        Log.e(TAG, "  For details, see: http://api.xposed.info/using.html");
        closeSilently(dexFile);
        return;
    }
 
    closeSilently(dexFile);
 
    ZipFile zipFile = null;
    InputStream is;
    try {
        zipFile = new ZipFile(apk);
        // 获取模块中的assets/xposed_init,也就是我们开发过程中指定Xposed入口的文件
        ZipEntry zipEntry = zipFile.getEntry("assets/xposed_init");

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 1
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
// // 统计代码