xposed原理
zygote进程是android系统第一个apk进程,其他所有的apk进程都是通过zygote进程fork的。xposed是一个hook框架,其通过修改zygote进程的native层代码和java层代码在zygote进程启动时将xposed框架使用的jar包(XposedBridge.jar)加载到android虚拟机中,然后将所有xposed插件模块也加载进android虚拟机中。因为zygote之后fork其他进程的时候会共享这些资源,所以所有的apk都会加载所有的xposed模块(这也是卡顿和费电的原因)。另外因为这些操作是在zygote进程启动的时候加载的,所以如何要更改或添加新的xposed模块就需要重新启动手机,因为zygote fork其他apk进程的时候并不会重新执行这些加载xposed模块的代码了。
xposed源码分析
app_process.main
zygote进程对应的native层代码的入口在app_process模块中,此模块对应的代码为app_process.cpp文件。查看xposed源码中也有app_process.cpp文件,来到入口点main函数处。
- 其会调用xposed::initialize进行初始化,此函数通过设置环境变量CLASSPATCH预先加载xposed的XposedBridge.jar,这样后续加载的xposed模块就可以使用此jar包中的api进行hook操作了。
- 接着判断xposed(就是上一步的jar包)是否加载,如果加载了就通过反射调用
de.robv.android.xposed.XposedBridge
类的入口main函数。如果没有加载xposed就还调用原始zygote进程的java层代码com.android.internal.os.ZygoteInit类的入口main函数。
de.robv.android.xposed.XposedBridge.main
- 调用loadModules加载所有的xposed插件模块。
- 此函数会调用initForZygote函数进行初始化,initForZygote函数内部会hook一些系统框架层的函数:例如会hook handleBindApplicaton函数并在此函数调用之前调用回调函数。
- 最后执行zygote进程原始的执行流程。
loadModules
- loadModules函数会动态加载xposed插件apk,然后获取apk中的xposed_init文件每一行设置的hook接口名称并实例化类。
- 因为这些xposed_init文件中的类都需要实现handleLoadPackage接口函数,调用hookLoadPackage函数将所有的handleLoadPackage接口函数都保存到一个全局的回调函数链表sLoadedPackageCallbacks中。
initForZygote
initForZygote函数会hook handleBindApplicaton()并设置回调函数。在调用handleBindApplication函数调用之前此回调函数被调用,回调函数会获取当前加载apk的包名packageName,进程名processName,classLoader等信息并作为参数调用sLoadedPackageCallbacks全局回调函数链表中的所有回调函数。sLoadedPackageCallbacks链表中的回调函数就是handleLoadPackage接口函数。所有在编写xposed模块时编写handleLoadPackage接口函数是在handleBindApplication函数调用前调用的。
因为加壳apk都是在handleBindApplication函数调用的Application.attachBaseContext函数中修正classloader为自定义的classloader,并利用此自定义的classloader动态加载原始apk的dex文件。而xposed编写的handleLoadPacked函数是在handleBindApplication函数调用之前调用的所以这个时候获取到的classloader是壳的并不是原始apk的,因此利用此classloader是无法hook原始apk中的java类的,需要通过反射获取修正后的classloader进行hook。
标签:分析,调用,函数,xposed,zygote,apk,源码,加载 From: https://www.cnblogs.com/revercc/p/17015140.html