首页 > 其他分享 >lsposed运行流程分析

lsposed运行流程分析

时间:2023-01-08 13:11:06浏览次数:40  
标签:调用 函数 lsposed 流程 zygote so riru 运行 加载

xposed适用的最高版本为android 8.0,针对高版本的ART HOOK框架可以使用比较有名的lsposed。它使用了lsplant ART HOOK框架(早期使用YAHFA)并提供了和xposed一样的接口API与其进行了兼容,同时lsposed本身是一个基于magisk的riru/zygisk插件,所以在分析lsposed运行流程之前先分别分析一下riru和zygisk的运行流程。

riru运行流程分析

riru的目的就是为了能够将插件so在zygote刚开始启动的时候注入到此进程中,首先riru自己需要先注入到zygote进程中。不同版本的riru使用了不同的方法将自己注入到zygote进程中。

  • 早期:通过替换系统so库:libmemtrack.so来实现劫持注入。
  • 中期:使用public.libraries.txt,在zygote启动时会加载此文件中的所有so库。
  • 现在:修改系统属性ro.dalvik.vm.native.bridge进行注入,zygote会加载此系统属性值对应的so库。

libriruloader.so的.initarray

目前最新的riru版本(V26)通过修改系统属性ro.dalvik.vm.native.bridge将libriruloader.so注入到zygote进程中,然后查看此so的.initarray其会先调用dlopen将libriru.so加载,最后调用libriru.so的init函数。

libriru.so的init

libriru的init函数分别调用了PrepareMapsHideLibrary,InstallHooks和Load。

PrepareMapsHideLibrary

PrepareMapsHideLibrary加载libriruhide.so并获取其导出函数riru_hide

InstallHooks

XHOOK_REGISTER是一个宏,其通过GOT表hook libandroid_runtime.so的jniRegisterNativeMethods,因为libandroid_runtime.so的jni函数都是通过jniRegisterNativeMethods注册的,所以hook后可以主动调用原jniRegisterNativeMethods为libandroid_runtime.so注册回调函数并将nativeForkAndSpecialize ,nativeSpecializeAppProcess, nativeForkSystemServer这三个函数指针修改。这三个jni函数会在Zygote进程java层fork应用进程和系统进程时被调用,通过修改这三个函数的指针就可以在zygote fork新进程的时候得到执行时机。

Load

  • 调用LoadModule函数,通过dlopen加载所有的riru模块so并调用其init函数。
  • 调用HideFromMaps函数通过之前获取的libriruhide.so的导出函数riru_hide隐藏所有加载的riru模块so和libriru.so本身。
  • 调用所有加载的riru模块so的onModuleLoaded函数。

libriruhide.so的导出函数riru_hide,此函数会调用do_hide隐藏指定内存块,通过备份后再重新map会原地址的方法欺骗map表。

zygisk运行流程分析

zygisk目的和riru一样都是为了在zygote进程中运行自己的模块,其通过修改app_process程序的入口,通过设置环境变量LD_PRELOAD后运行原来的app_process程序从而注入zigisk自己的so。

zygisk自己的so注入到zygote进程中后和riru一样也会加载所有的模块so,同时也会利用相同的方式隐藏这些so模块。

整体流程大致和riru相似。

lsposed运行流程分析

由riru运行流程分析可知,其在加载模块so之后会先后进行如下几步操作:

  1. 加载完模块so后调用so中的init函数
  2. 隐藏模块so
  3. 调用模块so的onModuleLoaded函数
  4. 当zygote fork生成新apk时会调用模块so中设置的回调函数nativeForkAndSpecialize(pre/post) ,nativeSpecializeAppProcess(pre/post) , nativeForkSystemServer(pre/post)
    以nativeForkAndSpecialize(pre/post)为例,lsposed设置这两个回调函数后,当zygote fork一个新的app进程时会分别调用这两个回调函数。lsposed设置nativeForkAndSpecializepost回调函数会调用MagiskLoader::OnNativeForkAndSpecializePost,此函数会调用一系列函数在zygote fork的apk运行前进行一些初始化。

LoadDex

先调用PreloadedDex将lspd.dex文件从磁盘map到内存中。

LoadDex实例化一个InMemoryClassLoader并设置parent为系统类加载器systemClassLoader,同时加载了lspd.dex。

InitArtHooker and InitHooks

进行一些初始化,其中InitHooks内部会获取前面实例化的InMemoryClassLoader类加载器中加载的所有dex文件(实际就是lspd.dex)的DexFile对象,然后调用DexFile_setTrusted使此dex文件中的类能够绕过android 9.0开始的对私有系统frameword API的限制访问,但是查看DexFile_setTrusted源码发现,此函数只有在apk处于调试状态下才能生效。

SetupEntryClass

相当于找到lspd.dex的入口类org.lsposed.lspd.core.Main

forkCommon

forkCommon会调用initXposed和bootstrapXposed

initXposed

initXposed进行一些初始化,通过前面加载的lspd.dex中提供的xposed API进行一些hook操作。

bootstrapXposed

bootstrapXposed调用lspd.dex的loadModules。

loadModules调用getModulesList加载并所有的xposed模块,调用重载的loadModule(内部调用InitModule)初始化xposed模块中需要hook的函数。

loadModules调用getModulesList,getModulesList内部经过层层调用最后会调用LoadModule,此函数会读取xposed模块apk文件中的assets/xposed_init中注册的类名称。

loadModules调用重载的loadModule,此函数通过一个自定义的类LspModuleClassLoader继承于ByteBufferDexClassLoader ,ByteBufferDexClassLoader继承于BaseDexClassLoader,BaseDexClassLoader继承于ClassLoader,定义一个classloader设置parent为之前创建的InMemoryClassLoader并加载对应的xposed模块apk。最后还会调用InitModule对xposed模块中需要hook的函数进行初始化。

检测lsposed指纹

标签:调用,函数,lsposed,流程,zygote,so,riru,运行,加载
From: https://www.cnblogs.com/revercc/p/17034028.html

相关文章