Android热补丁技术—dexposed原理简析(手机淘宝采用方案)

上篇文章《Android无线开发的几种常用技术》我们介绍了几种android移动应用开发中的常用技术,其中的热补丁正在被越来越多的开发团队所使用,它涉及到dalvik虚拟机和android的一些核心技术,现在就来介绍下它的一些原理。

本篇先介绍dexposed方案:https://github.com/alibaba/dexposed,它是手机淘宝团队使用的热补丁方案,后来开源到github上,取的名字dexposed表明了自己是基于大名鼎鼎的xposed
hook方案,有饮水思源、回馈开源项目的意思。与xposed不同的是,dexposed是自己hook自己的应用,因此不需要root权限。

它的关键点是:在native层中先找到要修复的Java函数对应的Method对象,修改它变为native方法,把它的nativeFunc指向hookedMethodCallback。这样对这个java函数的调用就转为调用hookedMethodCallback这个native函数了,然后再用这个native函数回调java层自己实现的统一接口来处理。这个统一接口是XC_MethodReplacement类,它主要有beforeHookedMethod、afterHookedMethod和replaceHookedMethod等几个方法,前两个在执行原java函数前后做一些事,replaceHookedMethod则是替换原java方法。下面来详细分析下这个hook的过程。

一、DexposedBridge.findAndHookMethod

findAndHookMethod是hook原java方法的入口,它传入的参数是类Class和方法名,最后一个可变参数parameterTypesAndCallback,是用户实现的用于替换原方法的XC_MethodReplacement的实例。

 

先调用XposedHelpers.findMethodExact找到要hook的java方法,再用hookMethod进行真正的hook。

1.findMethodExact根据类名和方法名,用反射找到Method,并把它的属性改为可访问。

2.hookMethod先把hook成功后的callback、要hook的方法的参数和返回值类型保存到AdditionalHookInfo中,把它作为参数传给hookMethodNative。hookMethodNative是一个native方法,它的第3个参数slot表示该Method在class的方法表中所处的位置,在native的实现中会用到这个slot。

 

hookMethodNative的实现环境分dalvik和art,因为dexposed对art的支持不完善,同时art本身的原理和机制也是一个难点,所以本篇只介绍dalvik下的实现,art的有关内容以后有机会再作介绍。

 

 

二、hookMethodNative

每一个java的类在虚拟机的实现中都对应着一个C++的ClassObject。dvmDecodeIndirectRef是libdvm中的方法,它可以从java对象的间接引用获得ClassObject对象,再根据slot,用dvmSlotToMethod找到Method对象。这里的ClassObject和Method都是虚拟机内部用来表示class和Method的数据结构。

然后把原来的Method结构先备份到XposedHookInfo中,

 

XposedHookInfo的结构如下:

可见,它用originalMethod保存原来java方法的Method,用reflectedMethod保存原java方法在native的引用,注意这跟originalMethod中保存的Method对象不同。originalMethod中保存的Method可以理解为执行字节码的地址,而reflectedMethod中保存的是用来描述原java方法的一个ClassObject对象。它们两个在第五部分重新调用原java方法时会用到。

additionalInfo用来保存附加信息AdditionalHookInfo。接着使用SET_METHOD_FLAG宏把该方法设为native,让nativeFunc指向hookedMethodCallback,这样对该java方法的调用就会转为对hookedMethodCallback这个native方法的调用了。Insns指向这个方法的字节码,在这里把它改为指向hookInfo,实际上也就是originalMethod的字节码的地址。

 

 

三、hookedMethodCallback

hookedMethodCallback会回调java层的方法handleHookedMethod,最终会调用到前面说过的,在findAndHookMethod中传入的XC_MethodReplacement里的before、after方法。

 

这里首先把在hookInfo中保存的信息作为传给java层的handleHookedMethod的参数,然后用dvmCallMethod这个dalvik的函数调用xposedHandleHookedMethod这个java的方法。xposedHandleHookedMethod在初始化时已经被设置好了。

GetStaticMethodId是dvm中用来获取静态方法地址的函数,可见在初始化时,已经把java的静态方法handleHookedMethod的地址赋给了xposedHandleHookedMethod了。这里需要注意两点,一是这个时候已经不能像没hook之前那样,通过jni从native调java的函数,或者从java调native的函数,因为原来java方法的上下文已经被改变了(已经被保存在hookInfo中),所以后面只能通过libdvm中的方法,手动修改函数的指向。二是dvmCallMethod的第5和第6个参数originalReflected和original就是第二部分中保存的方法的引用和方法的字节码地址(original被直接转成了int型),后面第五部分中这两项还会被重新传回native层用来找到原java函数的入口。

四、handleHookedMethod

前面说到从native中调回java的方法handleHookedMethod,handleHookedMethod会根据需要,选择是否还调用原来的java方法,或者只调用XC_MethodReplacement里自己实现的before、after方法。

其中beforeHookedMethod方法默认会调用replaceHookedMethod,我们只要实现它即可替代对原方法的调用。

 

如果param.returnEarly为false才会调invokeOriginalMethodNative执行原来的方法。

默认的beforeHookedMethod中会调setParam,把param.returnEarly的值设为为true,这样就不会再调用原来的java方法了。

最后还要把返回值返回。

 

 

五、invokeOriginalMethodNative

如果在java层需要重新调用原java函数,那么在第二部分中把原java函数的信息备份到hookInfo中就能起到作用了。Java层的invokeOriginalMethod方法会调一个native的方法invokeOriginalMethodNative来实现这个过程。

这个native函数同样在初始化时就被设置好了:

要调用的invokeOriginalMethodNative在虚拟机中Method是dexposedInvokeOriginalMethod,这里传入了第二部分中备份的原java方法的对象引用reflectedMethod和字节码地址int型的original。

dvmSetNativeFunc的第2个参数是DalvikBridgeFunc类型的指针,这个函数会把dexposedInvokeOriginalMethod的nativeFunc指向xxx_invokeOriginalMethodNative。再次注意此时不能像平常的jni调用那样,java层的invokeOriginalMethodNative经过jni注册后能直接调到com_taobao_android_dexposed_DexposedBridge_invokeOriginalMethodNative了。

dvmInvokeMethod跟dvmCallMethod一样,都是dalvik中用来直接调Method的函数,这样就完成了对原java方法的调用。

 

最后一句话概括这种hook方法,就是通过把原java方法的类型改为native来把对java函数的调用转到native层,在native层用dvm的各种函数来操作Method的指针和对象来控制函数流程。

百分百原创,每周两篇,阿里、魅族、nvidia、龙芯、炬力、拓尔思等顶级企业资深工程师分享----嵌入式、Linux、物联网、GPU、Android、自动驾驶等技术,欢迎扫码关注微信公众号:嵌入式企鹅圈,实时推送原创文章!

时间: 2024-12-22 14:54:11

Android热补丁技术—dexposed原理简析(手机淘宝采用方案)的相关文章

OneSDK与手机淘宝技术能力开放

该文章来自阿里巴巴技术协会(ATA)精选集  7月16日,阿里巴巴集团在杭州召开阿里百川无线开放大会,来自阿里巴巴的技术专家向与会观众介绍了百川无线开放背后的技术细节. 阿里百川阿里巴巴集团无线开放平台,为移动开发者(涵盖移动创业者)提供快速搭建APP.加速APP商业化.提升用户体验的解决方案.在阿里百川无线开放大会的技术专场,阿里技术专家分享了关于TAE 2.0.OpenIM.移动安全等方面的技术细节,InfoQ之前已对TAE和OpenIM的技术负责人做过采访,今天就让我们来了解一下阿里百川无

腾讯Android自动化测试实战3.2 Robotium原理简析

3.2 Robotium原理简析 如前文所述,一个基本的自动化测试用例主要分为获取控件.控件操作.断言三个步骤,而在实际编写测试用例的过程中,我们常常会遇到各种各样的问题,比如: 在这样的UI结构下该如何获取控件? 为何报这样或那样的错? 明明滑动了为何没有效果? 因为不同的项目有其自身的独特性与复杂性,没有任何书籍可以解决实际过程中遇到的所有问题,甚至即使求助Google搜索也可能得不到自己想要的答案.因此,对于任何一门技术而言都很有必要知其然并知其所以然,只有了解了其原理实现,才能更高效地运

Android热修复技术原理详解与升级探索

在2017云栖大会-上海峰会上手机淘宝资深无线开发工程师甘晓霖(万壑)作了题为<Android热修复技术原理详解与升级探索>的分享,如何实现客户端与开发节奏最快同步,阿里云为此开发了移动热修复框架Sophix.它在代码修复.资源修复.SO库修复中都展示了极高的能力,在于其他竞品的对比中,Sophix展示出来极大的优势,并且非常容易上手.

Android热修复技术总结

插件化和热修复技术是Android开发中比较高级的知识点,是中级开发人员通向高级开发中必须掌握的技能,插件化的知识可以查我我之前的介绍:Android插件化.本篇重点讲解热修复,并对当前流行的热修复技术做一个简单的总结. 热修复 什么是热修复? 简单来讲,为了修复线上问题而提出的修补方案,程序修补过程无需重新发版! 技术背景 在正常软件开发流程中,线下开发->上线->发现bug->紧急修复上线.不过对于这种方式代价太大. 而热修复的开发流程显得更加灵活,无需重新发版,实时高效热修复,无需

Android热修复技术选型——三大流派解析

文章作者:所为 淘宝无线开发专家 2015年以来,Android开发领域里对热修复技术的讨论和分享越来越多,同时也出现了一些不同的解决方案,如QQ空间补丁方案.阿里AndFix以及微信Tinker,它们在原理各有不同,适用场景各异,到底采用哪种方案,是开发者比较头疼的问题.本文希望通过介绍QQ空间补丁.Tinker以及基于AndFix的阿里百川HotFix技术的原理分析和横向比较,帮助开发者更深入了解热修复方案. 技术背景 一.正常开发流程 从流程来看,传统的开发流程存在很多弊端: 重新发布版本

Java Annotation 及几个常用开源项目注解原理简析

文简单介绍下 Annotation 示例.概念及作用.分类.自定义.解析,并对几个 Android 开源库 Annotation 原理进行简析. PDF 版: Java Annotation.pdf, PPT 版:Java Annotation.pptx, Keynote 版:Java Annotation.key 一.Annotation 示例 Override Annotation Java 1 2 @Override public void onCreate(Bundle savedIns

PHP的错误报错级别设置原理简析

原理简析 摘录php.ini文件的默认配置(php5.4): ; Common Values: ; E_ALL (Show all errors, warnings and notices including coding standards.) ; E_ALL & ~E_NOTICE (Show all errors, except for notices) ; E_ALL & ~E_NOTICE & ~E_STRICT (Show all errors, except for

基于Oracle的面向对象技术入门基础简析开发者网络Oracle_oracle

正在看的ORACLE教程是:基于Oracle的面向对象技术入门基础简析开发者网络Oracle.一.概述 对象是Oracle8i以上版本中的一个新的特性,对象实际是对一组数据和操作的封装,对象的抽象就是类.在面向对象技术中,对象涉及到以下几个重要的特性:  封装性 通过对数据和操作的封装,将用户关心的数据和操作暴露出来作为接口,其他数据和操作则隐藏到对象内部,这样便于用户使用和维护.  继承性 对象具有继承性,通过这一特性可以增强程序的可扩展性,适合大型项目的开发.  多态性 同一操作在运行时刻有

android 购物-类似于手机淘宝中的功能

问题描述 类似于手机淘宝中的功能 我想实现一个类似于淘宝中那种看到商品后一点开就可以看到商品详情的功能.android版的.大概的实现思路是什么.求大神指教 解决方案 直接用按钮或者textview跳转到另一个fragment或者activity,并且传商品的id 参考:http://www.cnblogs.com/allenzheng/archive/2013/05/02/3054484.html 解决方案二: 点击按钮跳转页面 做好viewpage就可以了