android 的虚拟机是加载dex,并不是像java虚拟机那样加载class。
简单说一下原理:
public class Test{
public static void main(String[] args){
Mik mik = new Mik();
mik.doIt();
}
}
当一个应用启动,首先开辟一个方法区,然后加载Test.class类的字节码,这些字节码当然包括main方法的字节码,当走到main时,会把main方法做压栈操作,得到main栈帧,再去加载Mik.class的字节码,Mik mik = new Mik();分为三步,第一步:在方法区申明一个 Mik的mik符号变量,第二步再去开辟堆内存,第三步,给mik这个变量赋值。调用的时候在方法表查询对应的方法索引,然后根据索引找到方法的结构体指针,所以只要替换掉这个结构体指针,就把方法切换了。
Dalvik虚拟机:
1、Dalvik虚拟机采用JIT技术,字节码都需要通过即时编译器(just in time JIT)转换为机器码,发生在运行时。
2、把dex文件转换为odex来运行
ART虚拟机:
1、把字节码转换成机器码的过程放在了安装时
2、安装时把dex使用系统的dex2oat工具把dex转化为OAT文件,OAT是一种android私有的ELF文件格式,它不仅包含从dex翻译过来的本地机器指令,还办含有原来的DEX文件的内容。
所以在后面修复的时候改成class的加载状态ART就不需要了。
只是简单的 说一下区别而已
流程:(模仿AndFix)
1 发现bug 并修改bug,将修复的java文件 编译成class 然后打包成dex 放到服务器 供客户端下载
2 将修复的方法体 Method 从dex 文件取出,将会出现bug的方法 Method 也取出来
3 将取出的正确的 和 错误的method 一并传到底层做替换操作
4 底层替换 (指针替换)
先在客户端写一个有bug的方法。
![](https://img.haomeiwen.com/i11592336/0177e080b9b822d4.png)
1、再模仿写一个修改好的方法
![](https://img.haomeiwen.com/i11592336/5bbb1bdfa15b6a61.png)
2、把修复好的java编译成class,因为包名要跟错误的class文件一致,所以错误的class有多少文件夹层级,正确的class也要有多少层。
至于生成class文件可以javac,也可以把修复好的项目运行一下把class拷贝出来像这样:
![](https://img.haomeiwen.com/i11592336/46f6592eea6ef2cf.png)
3、生成dex,androidSdk/build-tools/27.0.3/dx.bat(27.0.3随便一个版本号)当然要配置环境变量啦。
![](https://img.haomeiwen.com/i11592336/5783f896fefe16e7.png)
路径1是输出dex的目录,路径2是java文件所在的文件夹(因为文件夹层级跟项目对应),得到out.dex复制到SD卡中(假装是下载的),接下来就解析这个dex得到class最后得到具体的方法。
![](https://img.haomeiwen.com/i11592336/2f9f103860b5ca0f.png)
通过class得到正确的方法和错误的方法,最后调用native方法替换
![](https://img.haomeiwen.com/i11592336/a364e9e127e64bb0.png)
底层替换涉及到虚拟机,所以就有dalvik和art的区别,先说dalvik:
因为要修改指针的指向,所以得用到虚拟机中的部分功能啦,主要从这两个头文件中拷贝代码,组成自己的头文件(怎么知道拷贝这些的,我也不知道。。。大神研究之后的结果,从android 源码里面拷贝的)
android4.4/dalvik/libdex/DexFile.h
android4.4/dalvik/vm/Object.h
![](https://img.haomeiwen.com/i11592336/105bb314516eb6cd.png)
![](https://img.haomeiwen.com/i11592336/a0223f6f45897f5a.png)
ART虚拟机:
![](https://img.haomeiwen.com/i11592336/d27fb2c08401bbb5.png)
7.0的兼容:
![](https://img.haomeiwen.com/i11592336/c8e7c27e6b465144.png)
混淆问题:
混淆时候类名,方法名改变了,所以做不到修复的,上面是通过系统的dx.bat生成dex现在使用阿里的工具生成dex。
下载andfix 里面有工具ApkPath,使用这个工具生成两个包的差分。
apkpatch.bat -f new.apk -t old.apk -o output -k 签名.jks -p 123456 -a mik -e 123456 (MAC 和 Linux 是apkpatch,sh)
-f 修复好的apk -t 出现bug的apk -o输出的文件 -k签名 -p签名密码 -a别名
-e 别名密码
网友评论