目录

1 前言

2 热修复技术

2.1 Dexposed

2.2 AndFix

2.3 QZone

2.4 Tinker

2.6 epic

2.7 YAHFA

2.8 FastHook

2.9 美团Robust

3 总结


1 前言

对热修复技术做一个总结,也是告一个段落(几年前的研究,有些可能过时了)

以AndFix入门,具体可以参考以前的使用步骤。

热修复系列——AndFix使用教程基础篇_疑是银河落九天的博客-CSDN博客_andfix使用

2 热修复技术

2.1 Dexposed

详情参考

Android中免Root实现Hook的Dexposed框架实现原理解析以及如何实现应用的热修复_尼古拉斯.赵四的博客-CSDN博客_dexposed

工作原理

  1. 基于Xposed的AOP框架
  2. 免root实现方法级粒度hook
  3. 通过JNI注册,从Java转Native,然后在native中修改被hook方法的一些信息,最后通过反射调用handleHookedMethod回到Java
  4. 立即生效

限制

不支持ART(xposed重新编译了自己的libart.so,并阻止内联,需要对不同版本兼容)

2.2 AndFix

详情参考

Android热修复框架AndFix原理解析及使用_尼古拉斯.赵四的博客-CSDN博客

工作原理

AndFixManager.java类的replaceMethod方法

private void replaceMethod(ClassLoader classLoader, String clz,String meth, Method method) {try {String key = clz + "@" + classLoader.toString();//key为新类名@默认类加载器名Class<?> clazz = mFixedClass.get(key);if (clazz == null) {// class not load//使用默认类加载器加载修复类对应的原始类Class<?> clzz = classLoader.loadClass(clz);...
}

ArtMethod结构替换代码

void replace_7_0(JNIEnv* env, jobject src, jobject dest) {art::mirror::ArtMethod* smeth =(art::mirror::ArtMethod*) env->FromReflectedMethod(src);art::mirror::ArtMethod* dmeth =(art::mirror::ArtMethod*) env->FromReflectedMethod(dest);//  reinterpret_cast<art::mirror::Class*>(smeth->declaring_class_)->class_loader_ =
//          reinterpret_cast<art::mirror::Class*>(dmeth->declaring_class_)->class_loader_; //for plugin classloaderreinterpret_cast<art::mirror::Class*>(dmeth->declaring_class_)->clinit_thread_id_ =reinterpret_cast<art::mirror::Class*>(smeth->declaring_class_)->clinit_thread_id_;reinterpret_cast<art::mirror::Class*>(dmeth->declaring_class_)->status_ =reinterpret_cast<art::mirror::Class*>(smeth->declaring_class_)->status_ -1;//for reflection invokereinterpret_cast<art::mirror::Class*>(dmeth->declaring_class_)->super_class_ = 0;smeth->declaring_class_ = dmeth->declaring_class_;smeth->access_flags_ = dmeth->access_flags_  | 0x0001;smeth->dex_code_item_offset_ = dmeth->dex_code_item_offset_;smeth->dex_method_index_ = dmeth->dex_method_index_;smeth->method_index_ = dmeth->method_index_;smeth->hotness_count_ = dmeth->hotness_count_;smeth->ptr_sized_fields_.dex_cache_resolved_methods_ =dmeth->ptr_sized_fields_.dex_cache_resolved_methods_;smeth->ptr_sized_fields_.dex_cache_resolved_types_ =dmeth->ptr_sized_fields_.dex_cache_resolved_types_;smeth->ptr_sized_fields_.entry_point_from_jni_ =dmeth->ptr_sized_fields_.entry_point_from_jni_;smeth->ptr_sized_fields_.entry_point_from_quick_compiled_code_ =dmeth->ptr_sized_fields_.entry_point_from_quick_compiled_code_;LOGD("replace_7_0: %d , %d",smeth->ptr_sized_fields_.entry_point_from_quick_compiled_code_,dmeth->ptr_sized_fields_.entry_point_from_quick_compiled_code_);}

限制

  1. 以Field为切入点,使用自定义类加载器生成新的ArtMethod,使用默认类加载器生成旧ArtMethod,再进行结构内字段的替换。
  2. AndFix采用的是替换结构体中的字段,但由于厂商可能会修改ArtMethod结构体,因此会有兼容问题。Sophix(是阿里推出的移动热修复方案,闭源,有本书《深入探索Android热修复原理》介绍了Sophix,支持)采用的是替换整个ArtMethod结构体,这样就不会存在兼容问题。
  3. 立即生效
  4. 目前支持2.3 - 7.0
  5. 《深入探索Android热修复原理》讲述sophix的对比图如下

2.3 QZone

详情参考

安卓App热补丁动态修复技术介绍

工作原理

  1. classloader可以包含多个dex文件,排成一个有序数组dexElements,当查找类时会按顺序遍历dex文件,如果不同的dex有相同的类存在,那么会优先选择排在前面的dex文件中的类
  2. 如果一个类与它直接引用的类在同一个dex文件中,那么该类会被打上preverify标签。因此如果需要修复类与引用类所在dex文件不同则会报错。解决方案是往所有类的构造函数插桩引用一个不存在的类,防止被打上标签
  3. 重启生效,因为已经加载过的类无法被卸载,想要重新加载新的类就需要重启APP。

限制

  1. 由于插桩导致所有类都非preverify,因此加载类时会触发verify与optimize操作,由于启动时会加载大量的类,因此效率影响较大
  2. 存在art下内存地址混乱问题,因为dex2oat将类能确定的各个地址写死,运行时补丁包的地址改变,原始类调用就会出错

2.4 Tinker

详情参考

GitHub - WeMobileDev/article: articles by WeChat Mobile Development Team

工作原理

使用DexDiff算法,在编译时通过新旧Dex生成差异包,将差异包与旧Dex还原为新Dex,重启生效

限制

  1. 占用Rom体积,大约是修改Dex数量的1.5倍(dexopt与dex压缩成jar)的大小
  2. 需要额外进程合成新的Dex,合成时间的长短与内存消耗也会影响最终的成功率

2.6 epic

详情参考

我为Dexposed续一秒——论ART上运行时 Method AOP实现 | Weishu's Notes

https://github.com/tiann/epic/blob/master/README_cn.md

工作原理

通过callee的ArtMethod对象得到方法的entrypoint,根据方法入口点找到对应地址,直接将内存的前8个字节修改为一段跳转指令,然后在跳转指令中执行二段跳板,进而跳转到新方法中执行

限制

  1. 受限于dynamic callee-side rewrite机制,如果被Hook函数的code段太短以至于一个简单的trampoline跳转都放不下,那么epic无效
  2. 如果ART中有深度内联,直接把本函数的代码内联到调用者,那么epic无效
  3. 仅支持Android 5-11
  4. 当前仅支持thumb2/arm64指令集,arm32/x86/x86_64/mips/mips64还没有适配
  5. 在支持硬浮点的cpu架构,比如(armeabi-v7a, arm64-v8a)上,带有double/float参数的函数Hook可能有问题,没有充分测试
  6. 还有一些其他机型上可能存在的闪退
  7. 目前已测机型:5.0, 5.1, 6.0, 7.0, 7.1个别机型,以及这些机型的thumb2指令集,和6.0/7.1 的arm64指令集(作者博客所述)
  8. 无法修改类初始化过程中执行的函数

2.7 YAHFA

详情参考

YAHFA--ART环境下的Hook框架 - 记事本

在Android N上对Java方法做hook遇到的坑 - 记事本

工作原理

修改目标方法的ArtMethod结构体,将hook方法的ArtMethod地址保存在原方法的entry_point_from_jni,并修改原方法的entry_point_from_quick_compiled_code,使其指向一段辅助代码,在这里完成eax的设置和跳转,即时生效。

从原理上看,还是走的虚拟机调用流程,与AndFix的不同之处在于,AndFix直接替换了Method,而YAHFA使用一种简单方式实现了AOP,能够实现方法的hook并回调原始方法

限制

  1. 无法解决方法直接跳转,也就是不走ArtMethod入口,目标方法地址直接写死(其实这种情况在高版本里比较少了,特别是第三方应用的方法更少)
  2. 由于class加载后才进行的结构替换,因此field在class中的相对地址已经确定,无法进行字段的新增与删除
  3. 因为直接替换方法,此时已经执行了loadClass初始化,因此在该过程中执行的方法如构造函数、静态成员都有问题

2.8 FastHook

详情参考

[原创]FastHook——一种高效稳定、简洁易用的Android Hook框架-Android安全-看雪论坛-安全社区|安全招聘|bbs.pediy.com

[原创]FastHook——实现.dynsym段和.symtab段符号查询-Android安全-看雪论坛-安全社区|安全招聘|bbs.pediy.com

[原创]FastHook——远超YAHFA的优异稳定性-Android安全-看雪论坛-安全社区|安全招聘|bbs.pediy.com

[原创]FastHook——巧妙利用动态代理实现非侵入式AOP-Android安全-看雪论坛-安全社区|安全招聘|bbs.pediy.com

https://github.com/turing-technician/FastHook

工作原理

这个框架很优秀,其实还是native替换,fasthook支持内联替换和entrypoint两种方式,而且手动jit的过程中处理了很多细节,值得参考。

限制

还是native替换的通病,不能新增类/字段,以及类初始化过程中执行的函数

2.9 美团Robust

详情参考

Android热更新方案Robust - 美团技术团队

工作原理

Instant Run类型方案,基于编译过程进行插桩,有代码侵入,对运行效率,包体积,方法数有一定影响。

限制

插桩原始代码,因此会有代码冗余

3 总结

总结,具体对比我就略过了,技术参考链接已经很详细了。

总的来说,就是Java整体替换的方式可以新增类/字段,native内存替换只能修改方法体本身。

整体全面的热修复方案以Sophix为代表,不过它不开源。

native替换以FastHook为代表,不过有点黑科技,处理适配和兼容应该会花不少时间。

Robust插桩方案除开对代码有侵入性的话,从稳定性和兼容性来说,应该是最好的(但是这套方案没有详细了解)

有错误欢迎指正,也欢迎技术交流!

热修复系列——Android热修复技术进阶篇相关推荐

  1. 1000篇干货好文!量子技术——进阶篇

    阅读原文 1000篇干货好文!量子技术--入门篇  https://bbs.aliyun.com/read/581500.html    1000篇干货好文!量子技术--进阶篇  https://bb ...

  2. android热补丁作用,Android热修复之 - 阿里开源的热补丁

    这里就有一个概念那就AndFix.apatch补丁用来修复方法,接下来我们看看到底是怎么实现的. 1.2 生成apatch包 假如我们收到了用户上传的崩溃信息,我们改完需要修复的Bug,这个时候就会有 ...

  3. Android工具修复属性,Android 热修复介绍之代码修复

    什么是Android热修复技术 简单来说就是不重新安装apk的情况下,通过补丁,修复bug 正常开发流程 热修复开发流程 目前主流的热修复技术框架 阿里系的: Andfix.Hotfix.Sophix ...

  4. 跟着小马哥学系列之 Spring IoC(进阶篇:Environment)

    学成路更宽,吊打面试官. --小马哥 简介 大家好,我是小马哥成千上万粉丝中的一员!2019年8月有幸在叩丁狼教育举办的猿圈活动中知道有这么一位大咖,从此结下了不解之缘!此系列在多次学习极客时间< ...

  5. 跟着小马哥学系列之 Spring IoC(进阶篇:类型转换)

    学成路更宽,吊打面试官. --小马哥 简介 大家好,我是小马哥成千上万粉丝中的一员!2019年8月有幸在叩丁狼教育举办的猿圈活动中知道有这么一位大咖,从此结下了不解之缘!此系列在多次学习极客时间< ...

  6. android 热修复视频,Android热修复

    所谓热修复,简单来说就是不以下载新版本apk的方式来修改应用的bug,而是在应用启动后从服务器下拉补丁包实现动态修复bug.所以在应用出现bug后,我们只需要打一个补丁,用户无需下载安装新的版本.主要 ...

  7. android中热更新模式,Android热更新与开启Instant Run

    配置完热更新后,直接run模式运行,程序会报以下错误: Tinker does not support instant run mode, please trigger build by assemb ...

  8. android adb修复工具,Android——adb修复build.prop

    从昨天开始就在刷手机,换了各种rom,今天中午总算刷了一个还算不错的rom,用了不到半天,晚上突发奇想修改了以下/system/build.prop文件,哪知手机重启后再也进不了系统,真是悲剧.不想再 ...

  9. 《Android插件化技术——原理篇》

    | 导语 插件化技术最早从2012年诞生至今,已经走过了5个年头.从最初只支持Activity的动态加载发展到可以完全模拟app运行时的沙箱系统,各种开源项目层出不穷,在此挑选了几个代表性的框架,总结 ...

最新文章

  1. 微信小程序自定义组件Component的简单使用
  2. 看看Entity Framework 4生成的复杂的分页SQL语句
  3. MySQL 中主键的几种表设计组合的实际应用效果
  4. python教程:Json模块中dumps、dump、loads、load函数用法讲解
  5. QML 性能优化建议(一)
  6. python语言语句快的标记是什么_一文搞懂Python程序语句
  7. 怎么在linux下查看gpu版本号,linux.查看gpu版本
  8. C/C++内存分配方式 .
  9. 使用ETag识别ajax,如何使用jQuery AJAX请求访问ETag头?
  10. ArcEngine由点生成TIN
  11. 二叉树的之字形层序遍历
  12. iOS分段选择器、旅行App、标度尺、对对碰小游戏、自定义相册等源码
  13. Scala深入浅出实战经典---001-Scala开发环境搭建和HelloWorld解析
  14. 音乐专业如何利用计算机思维,太神奇了!带学生“玩音乐”居然可以打开思维创新...
  15. JavaScript之Ajax Util
  16. python图片,大家来找茬
  17. 小米平板2(2015716)官方线刷包_救砖包_解账户锁
  18. QML之gradient
  19. PyTorch搭建LSTM实现多变量多步长时间序列预测(四):多模型滚动预测
  20. python在excel中数据画线_python中操作excel数据

热门文章

  1. linux crash,系统崩溃 - crash工具介绍
  2. Astro VG876图像信号发生器控制软件
  3. Linux下暴力破解弱密码的工具
  4. JavaSE-类和对象基础
  5. 北京的十大尾货批发市场【接近生活】
  6. 麦克风阵列声源定位解决方案
  7. (1分钟突击面试) 高斯牛顿、LM、Dogleg后端优化算法
  8. MASM32 v11 汇编、连接及运行程序的方法
  9. 互联网巨头吃小鱼:终端背后的十亿消费者
  10. 硅谷创业教父Paul Graham:如何创造财富