Xposed原理简介及其精简化

Xposed是⼀个很强⼤的Android平台上的HOOK⼯具,⽽且作者为了⽅便开发者使⽤开发了⼀个APP(Xposed Installer,下⽂称为Installer)
来使⽤开发者⾃⼰开发的模块。开发者安装⾃⼰的模块后需要在Installer中勾选⾃⼰的模块然后重启⼿机⾃⼰的模块才会起作⽤。但是这样有点不
利于开发者测试,每次都要点开Installer操作⼏下尤其是还要重启就显得有点⿇烦了。
读过Xposed的源码后会发现仅通过更改XposedBridge.jar的源码就可以更简便⼀些:

  1. 不需重启⼿机
  2. 不需操作Installer这个App,且不⽤安装hook模块,只需push到⼿机即可⾸先需要下载源码,rovo89链接⾥⾯有Xposed所有源码,我们只需要下载XposedBridge就好。
    原版的Xposed并不适⽤于三星⼿机,wanam改过的Xposed可以⽤,所以如果是三星⼿机的话就下载wanam的。

1. Xposed原理简介

现在安装Xposed⽐较⽅便,因为Xposed作者开发了⼀个Xposed Installer App,下载后按照提⽰傻⽠式安装(前提是root⼿机)。其实它的
安装过程是这个样⼦的:⾸先探测⼿机型号,然后按照⼿机版本下载不同的刷机包,最后把Xposed刷机包刷⼊⼿机重启就好。刷机包下载 ⾥⾯
有所有版本的刷机包。
刷机包解压打开⾥⾯的问件构成是这个样⼦的:

META-INF/    ⾥⾯有⽂件配置脚本 flash-script.sh 配置各个⽂件安装位置。
system/bin/   替换zygote进程等⽂件
system/framework/XposedBridge.jar jar包位置
system/lib system/lib64 ⼀些so⽂件所在位置
xposed.prop xposed版本说明⽂件

所以安装Xposed的过程就上把上⾯这些⽂件放到⼿机⾥相同⽂件路径下。
通过查看⽂件安装脚本发现:
system/bin/下⾯的⽂件替换了app_process等⽂件,app_process就是zygote进程⽂件。所以Xposed通过替换zygote进程实现了控制⼿机
上所有app进程。因为所有app进程都是由Zygote fork出来的。
Xposed的基本原理是修改了ART/Davilk虚拟机,将需要hook的函数注册为Native层函数。当执⾏到这⼀函数是虚拟机会优先执⾏Native层函
数,然后再去执⾏Java层函数,这样完成函数的hook。如下图:

通过读Xposed源码发现其启动过程:

  1. ⼿机启动时init进程会启动zygote这个进程。由于zygote进程⽂件app_process已被替换,所以启动的时Xposed版的zygote进程。
  2. Xposed_zygote进程启动后会初始化⼀些so⽂件(system/lib system/lib64),然后进⼊XposedBridge.jar中的XposedBridge.main中
    初始化jar包完成对⼀些关键Android系统函数的hook。
  3. Hook则是利⽤修改过的虚拟机将函数注册为native函数。
  4. 然后再返回zygote中完成原本zygote需要做的⼯作。
    这只是在宏观层⾯稍微介绍了下Xposed,要想详细了解需要读它的源码了。下⾯两篇写的挺好,要想深⼊理解的可以看看。
    Android Hook框架Xposed原理与源代码分析
    深⼊理解Android之Xposed详解

2. Xposed精简化

上⾯稍微介绍了下它的原理,下⾯就介绍如何精简化Xposed。下⾯只修改了XposedBridge.jar包中的XposedBridge.java这个⽂件,修改完重
新Build apk然后把apk重命名为XposedBridge.jar然后替换刷机包中的jar包,刷⼊⼿机即可。

2.1 取消重启⼿机

看下XposedBridge.jar的源码
代码⽂件de.robv.android.xposed.XposedBridge.java

protected static void main(String[] args) {// Initialize the Xposed framework and modulestry {if (!hadInitErrors()) {initXResources();SELinuxHelper.initOnce();SELinuxHelper.initForProcess(null);runtime = getRuntime();XPOSED_BRIDGE_VERSION = getXposedVersion();if (isZygote) {XposedInit.hookResources();XposedInit.initForZygote();}//修改时需注释下⾯这⾏代码XposedInit.loadModules();//*********load hook 模块*******************} 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 codeif (isZygote) {  //****代码修改位置****           ZygoteInit.main(args);} else {RuntimeInit.main(args);}}

注意上⾯的XposedInit.loadModules()这个函数,这个函数的作⽤就是load hook模块到进程中。
因为zygote启动时先跑到java层XposeBridge.main中,在main⾥⾯有⼀步操作是将hook模块load进来,模块加载到zygote进程中,zygote
fork所有的app进程⾥⾯也有这个hook模块,所以这个模块可以hook任意app。(编写hook模块的第⼀步就是判断当前的进程名字,如果是要
hook的进程就hook,不是则返回)。所以修改模块后,要将模块重新load zygote所以修改的逻辑是不把模块load到zygote⾥⾯,
⽽是load到⾃⼰想要hook的进程⾥⾯,这样修改模块后只需重启该进程即可。
在上⾯代码的代码修改位置添加如下代码,并将上⾯XposedInit.loadModules()注释掉即可。

if (isZygote) {XposedHelpers.findAndHookMethod("com.android.internal.os.ZygoteConnection", BOOTCLASSLOADER, "handleChildProc","com.android.internal.os.ZygoteConnection.Arguments",FileDescriptor[].class,FileDescriptor.class,PrintStream.class,new XC_MethodHook() {@Overrideprotected void afterHookedMethod(MethodHookParam param) throws Throwable {// TODO Auto-generated method stubsuper.afterHookedMethod(param);String processName = (String) XposedHelpers.getObjectField(param.args[0], "niceName");String coperationAppName = "指定进程名称如:com.android.settings";if(processName != null){if(processName.startsWith(coperationAppName)){log("--------Begin Load Module-------");XposedInit.loadModules()}}}});ZygoteInit.main(args);} else {RuntimeInit.main(args);}

2.2 取消操作Installer A

通过读Install App的源码发现其实勾选hook模块其实app就是把模块的apk位置写到⼀个⽂件⾥,等load模块时会读取这个⽂件,从这个⽂件中
的apk路径下把apk load到进程中,看下loadmodules的源码。

XposedInit.java
/*** Try to load all modules defined in <code>BASE_DIR/conf/modules.list</code>*//*package*/ 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;}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;while ((apk = apks.readLine()) != null) {loadModule(apk, topClassLoader);}apks.close();}

apk配置⽂件就是installer app⽂件路径下的conf/modules.list这个⽂件data/data/de.robv.android.xposed.installer/conf/modules.list
或者data/user_de/0/de.robv.android.xposed.installer/conf/modules.list(不同⼿机版本位置不同)
所以我们改下,直接给他个确定的apk路径及名称。就定为/data/local/tmp/module.apk。
所以再把之前的代码改成如下的样⼦就好了。

if (isZygote) {XposedHelpers.findAndHookMethod("com.android.internal.os.ZygoteConnection", BOOTCLASSLOADER, "handleChildProc","com.android.internal.os.ZygoteConnection.Arguments",FileDescriptor[].class,FileDescriptor.class,PrintStream.class,new XC_MethodHook() {@Overrideprotected void afterHookedMethod(MethodHookParam param) throws Throwable {// TODO Auto-generated method stubsuper.afterHookedMethod(param);String processName = (String) XposedHelpers.getObjectField(param.args[0], "niceName");String coperationAppName = "指定进程名称如:com.android.settings";if(processName != null){if(processName.startsWith(coperationAppName)){log("--------Begin Load Module-------");String path = "/data/local/tmp/module.apk";//注意由loadModules换成了loadModule,记得改XposedInit.loadModule(path, BOOTCLASSLOADER);}}}});ZygoteInit.main(args);} else {RuntimeInit.main(args);}

每次修改模块后直接修改名字为module.apk然后push到/data/local/tmp/下,然后重启app就好

Xposed原理简介及其精简化相关推荐

  1. DeepLearning tutorial(4)CNN卷积神经网络原理简介+代码详解

    FROM: http://blog.csdn.net/u012162613/article/details/43225445 DeepLearning tutorial(4)CNN卷积神经网络原理简介 ...

  2. Google搜索引擎工作原理简介

    实在是写不出来高质量的原创文章,今天再次转载一篇网络上看到的文章吧,叫Google搜索引擎工作原理简介,其中比较详细的介绍和分析了google搜索引擎相关工作机制,下面是原文内容: 这篇文章是基于Go ...

  3. 遗传算法(GA)的原理简介与应用【python实现】

    遗传算法(GA)的原理简介与应用[python实现] 算法原理简介与实现 算法框架 关于GA求解过程中一些结果的讨论 SA-GA总结与体会 算法原理简介与实现 遗传算法(Genetic Algorit ...

  4. Cache原理简介及cache miss

    Cache原理简介及cache miss CPU体系结构之cache小结 1.What is cache? Cache是用来对内存数据的缓存. CPU要访问的数据在Cache中有缓存,称为" ...

  5. javascript原理_JavaScript程序包管理器工作原理简介

    javascript原理 by Shubheksha 通过Shubheksha JavaScript程序包管理器工作原理简介 (An introduction to how JavaScript pa ...

  6. Nginx 反向代理工作原理简介与配置详解

    Nginx 反向代理工作原理简介与配置详解 测试环境 CentOS 6.8-x86_64 nginx-1.10.0 下载地址:http://nginx.org/en/download.html 安装 ...

  7. DeepLearning tutorial(1)Softmax回归原理简介+代码详解

    FROM: http://blog.csdn.net/u012162613/article/details/43157801 DeepLearning tutorial(1)Softmax回归原理简介 ...

  8. DeepLearning tutorial(3)MLP多层感知机原理简介+代码详解

    FROM:http://blog.csdn.net/u012162613/article/details/43221829 @author:wepon @blog:http://blog.csdn.n ...

  9. 【Android 异步操作】Handler ( 主线程中的 Handler 与 Looper | Handler 原理简介 )

    文章目录 一.主线程中的 Handler 与 Looper 二.Handler 原理简介 一.主线程中的 Handler 与 Looper Android 系统中 , 点击图标启动一个应用进程 , 就 ...

最新文章

  1. 6、UmbracoNewsSite:添加新闻分类
  2. mysql dml ddldcl权限_MySQL中的DML、DDL、DCL到底是什么呢?
  3. 文件系统管理 之 Linux 创建文件系统及挂载文件系统流程详解
  4. Spring思维导图(MVC篇)
  5. leetcode算法题--最接近的三数之和
  6. MySQL在单表上创建视图
  7. deeplearning4j
  8. Android版添加phonegap--websocket客户端插件教程
  9. FAQ系列 | 几种常见MySQL无法启动案例
  10. mysql中最新7天的数据_mysql中最新7天的数据库
  11. Java使用Selenium几个例子
  12. JS 中类型和类型转换
  13. 前缀(波兰表达式) 中缀 后缀(逆波兰表达式)
  14. GDB调试时的参数设置
  15. C#技术分享【PDF转换成图片——11种方案】
  16. 提高性能及操作硬件的能力
  17. 实用———springmvc接收参数校验
  18. 全网首发:No package ‘usbutils‘ found
  19. ab测试工具结果分析
  20. 基于STM32的智能小区安保管理系统设计

热门文章

  1. RGB、LVDS、MIPI和EDP接口液晶屏
  2. 云电竞的服务器,雷风科技电竞云桌面解决方案
  3. hiredis中lua脚本调用
  4. 关于“System.Data.OleDb.OleDbException,外部数据库驱动程序 (1) 中的意外错误。”的解决方案
  5. 如何使你的项目有国际范
  6. What is WPK (PowerShell Kit) ?
  7. 基于Android社区生鲜O2O订购系统设计与实现 毕业设计-附源码231443
  8. springboot 04 jsr303验证
  9. 电视机@2022:降价、焦虑与机遇
  10. Mac系统配置环境变量保姆级教程