Skip to content

Xposed学习 #6

@NazcaLines

Description

@NazcaLines

Xposed的启动

Xposed(Xposed.git)用于替换app_process,跟app_process的启动一样,Xposed在启动流程上与原来的app_process基本一样,唯一做了修改的地方是在app_main.c#main()中读取了Xposed自己的配置,然后在执行

runtime.start("com.android.internal.os.ZygoteInit",
                startSystemServer ? "start-system-server" : "");

的时候,修改成了

isXposedLoaded = xposed::initialize(zygote, startSystemServer, className, argc, argv);
if (zygote) {
    runtime.start(isXposedLoaded ? XPOSED_CLASS_DOTS_ZYGOTE : "com.android.internal.os.ZygoteInit",
          startSystemServer ? "start-system-server" : "");

如果Xposed初始化成功的话,就启动Xposed指定的XPOSED_CLASS_DOTS_ZYGOTE: "de.robv.android.xposed.XposedBridge".

Xposed的初始化

isXposedLoaded = xposed::initialize(zygote, startSystemServer, className, argc, argv);

在xposed.cpp

  1. 首先填充一个XposedShared的数据结构,用于保存一些启动参数,判断这些参数是否存在,SEAndroid等。
  2. 如果参数里指定开启system_server,则打开日志记录功能,主要就是为了将系统日志都记录下来。
  • 2.1 执行Xposed_logcat.cpp#start()
  • 2.2 首先fork一个子进程(1),并且将父进程(0)返回
  • 2.3 子进程(1)中再次fork一个子进程(2)。他们之间利用pipe进行通信。(1)利用logcat工具读出日志,并且将标准输出与标准错误输出重定向到管道。
  • 2.4 子进程(2)读取日志内容,并且将日志内容写到文件中。/log/error.log
  1. 打印手机信息
  2. 因为有boolean指出需要加载System_server,所以转去执行了xposed_service.cpp#startAll().这里面向servicemanager添加了xposed自己的service。
  3. 然后xposed启动了,我尚且没有搞清楚xposed是从那一条路调用androidruntime.start().是从zygote还是classname。但是不论哪一条路,最后都会走到XposedBridge.main().
  4. appruntime.start之后,系统会回调AppRuntime的onVmCreated,最后在这里调用libxposed_dalvik.cpp#onVmCreated()或者是art中的。这里分析dalvik。
  5. 根据 JIT 是否存在对部分结构体中的成员偏移进行初始化。xposedInitMemberOffsets ();
  6. 是否有MIUI,取消final修饰符。 然后加载了XposedBridge,再然后注册jni函数
int register_natives_XposedBridge(JNIEnv* env, jclass clazz) {
    const JNINativeMethod methods[] = {
        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, initNative, "()Z"),
        NATIVE_METHOD(XposedBridge, hookMethodNative, "(Ljava/lang/reflect/Member;Ljava/lang/Class;ILjava/lang/Object;)V"),
#ifdef ART_TARGET
        NATIVE_METHOD(XposedBridge, invokeOriginalMethodNative,
            "(Ljava/lang/reflect/Member;I[Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;"),
#endif
        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;"),
    };
    return env->RegisterNatives(clazz, methods, NELEM(methods));
}

XposedBridge分析

经过上文的一系列步骤,终于进入到了XposedBridge.main(),在这个函数中,xposed完成了很多的事情。

  1. 调用initNative()这个函数是在libxposed_dalvik.cpp中的,是xposed启动的时候注册的jni函数。
  2. 会根据modules.list加载module,这里会完成函数的hook。下文结合例子重点分析。
  3. 返回去调用原来的zygoitInit.main()或RuntimeInit.main()

编写自己的Xposed Module

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions