工具:
工欲善其事,必先利其器。因为平时拆包少,对某些好工具也了解不多,基本用了手工的方法来处理的。大家可以用什么APK改之理之类的工具。
apktool
:这个大家都知道,反编译利器,我下的是apktool_2.0.0b9版本dex2jar
:不是必须,但看smali代码太累,用这个工具好受一些jd-gui
:不解释Replace Studio
:文本搜索工具,可以搜索某文件夹下的文件是否有某文本,我一直用这个,不知道大家有没有其它好工具推荐。notepad++
:如果你用记事本也可以android环境
:这个必须,你看完它的代码了,你起码得自己写的试试吧
简单拆包分析
先copy一份apk出来,改后缀名为zip,直接解压,先瞧瞧里面的内容,发现在/lib/armeabi/下的so文件相当的多,有蹊跷!
出于习惯,立马就拿notepad++打开了,结果发现,在文本的最前边是PK
开头的两个字符,哈哈,这绝对的是一个zip文件,我们都知道apk其实就是一个zip,而且,真正的so文件应该是以ELF
开头的。随便找一个打开,发现了APK的结构:
该上工具了,一步到位。对支付宝主APK进行拆包,使用apktool d xxx.apk
命令,直接拆成smali,再使用dex2jar
命令拆成jar包,再保存成java文件。
打开AndroidManifest.xml
文件,找到application
com.alipay.mobile.quinox.LauncherApplication
用jd-gui打开jar包,找到该类,查看onCreate方法,找到这段代码
代码中反射的mPackageInfo
其实就是有名的LoadedApk
类。
使用Replace Studio
在生成的java文件目录下搜索pathClassloader
我发现在com.alipay.mobile.quinox.classloader下有两个类继承自该类。
通过对smali代码的注入log日志的跟踪,JAVA文件和smali文件相互对照(因为不是所有的class都能反编译回来),我大概整理了一些逻辑与类的结构。
安卓动态加载原理
支付宝把一个一个插件称为bundle,在application
的onCreate方法中,反射mPackageInfo
中的mClassloader
字段,该属性是一个pathClassloade,将其替换成自己的PathClassloader(这段代码在dex2jar后的代码中看不到,我是直接读的smali代码)。
在自定义的PathClassloader中处理,如果是自身dex中的类,则用原pathClassloader加载,如果是bundle,则用bundle的dexfile.loadClass
来加载
BundleClassloader
:继承自classloader,用于加载具体的某个插件,包含一个DexFile文件引用,重写了loadClass方法,通过调用dexFile.loadClass(“className” , classLoader);HostClasloader
:继承自PathClassloader,包含一个系统的pathClassloader,也就是加载apk本身的pathClassloaderBootstrapClassloader
:继承自PathClassloader
,该类中包含一个map集合,保存着一个一个的BundleClassloader
,同时包含一个HostClasloader,该类就是自定义的pathClassloader,通过反射将原来的mClassloader替换成该类。OriginClassLoader
:继承自classloader,也就是上图中new的c,ClassLoader.class的parent
成了该对象。重写了findClass方法,调用了对android原生的类和APK中的类加载做了分发处理,APK中的类调用BootstrapClassloader
的loadClass
方法返回。