不论是APK代码抽取加固还是热更新,亦或是Xposed/frida hook,都离不开ArtMethod这个结构体。
但该结构体从andorid 4.4开始一直到现在的9.0,或多或少都会update,这导致之前版本的脱壳或者热更新都需要实时适配……想想,还是针对该结构体进行一个总结,总结过程当中会顺便介绍一些常见的框架使用到该结构体的部分。
主要做个人的一个总结,有些地方可能表述不清……
目的:一方面是进行个人总结,加深印象,另一方面便于以后查询适配。
适用于:了解hook原理基础
谈到ArtMethod还是提下4.4之前Method。
因为本次是针对ArtMethod做各版本总结,这里简单列出对比,方便过渡。
针对Method结构体,不得不谈谈xposed,还有第一代指令抽取加固方式。实际就是找到Method 中的 insns指令码字段(加固时是在dex文件,hook则直接获取函数指针得到该指令码字段),然后运行时替换。
而ArtMethod,是ART下的产物。其结构教于Method发生了变化,当dex2oat的时候,还会有多种方法内联优化。而方法内联会改变原本的方法分布和调用流程,对加固、热修复、hook,实际上都有一定的影响。当然,这个是后话,就不再赘述。
先给出ArtMethod结构主要的字段。
英文是源码,中文是个人注释
版本:android-9.0.0_r30:
上面是最新的9.0的结构。以下重点介绍几个版本改动处,原因,以及适配点。
前面的结构几乎没有变化,但是要开始谈论,还是得溯源到5.0……
5.0地址在runtime/mirror/art_method.h中
关键结构
这个时候,还存在entry_point_fromjni,entry_point_frominterpreter,关键在于这两个字段的被广泛用于hook(frida,xposed)、加固以及热更新(所以版本更新就得适配了……)
下面重点介绍下PtrSizedFields结构,其版本做过多个改变,实际上是进行了精简,不过还是需要适配……
简单谈一下几个关键字段的作用与各版本改变,可以对照之上的看:
从上面就可以很清晰的看到一个7.0之前的hook流程:获取函数的入口,得到函数结构体,替换accessflags将方法native化,保存原函数信息在entry_point_fromjni,替换entry_point_from_quick_compiled_code。调用被hook的方法时,首先会跳转替换的方法,然后跳转到entry_point_fromjni所指向的原方法。
当然,每个版本的hook方式不同,有些会采用机器码执行,有些会采用解释器执行,同样的加固原理也不同。
这边可以发现两种指令抽取加固原理。
通过artmethod关键结构,可以发现,这都是可行的操作。
但这里仅从原理角度分析可行,但实际环境适配与汇编代码编写,都是需要处理的,因为Android N的混合编译,垃圾回收修改,会导致的诸多问题,而7.0以后的适配,实际也就是针对原函数存放地址的适配,只能简略提一提,不多提。
忽然想到,现在的vm加固,若采用ARM 虚拟化保护,需要制定汇编解释器,将原始函数转换成字节码,保存原始函数的寄存器以及堆栈信息,然后在运行当中,然后用自定义解释器解析,这一部分又是一块需要大量实验和适配的地方……当然只是闲扯一句。
以上,实际深入了解ArtMethod结构后,会对以往版本的hook、代码抽取加固技术等有一个更清晰的认识,通过源码理解字段的作用和功能,也可以帮助产品进行适配,不至于在版本更新时,无从下手。
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课