前言
主要代码参考于jiangwei大佬以及github上的一位大佬,我在编写加固的过程中,加深了对动态加载的理解,虽然现在这种java层的加固非常少了,但是还是具有学习意义。
简要讲述加固流程图
- 先放下加固流程的图(从看雪嫖的图
- 发现图上的流程,首先是执行自定义application的attachBaseContext和onCreate方法,至于为什么会执行
这两个方法,这个需要去查看app的启动流程,在我另一篇博客,app的启动流程中,有写,这里就不赘述了,
总而言之,就是先执行,自定义的application中的attachBaseContext方法,该方法中,主要是解密源apk,并
自定义DexClassLoader,加载源apk中的dex,然后将加载组件类的mClassLoader替换成我们自定义的DexClassLoader
,而onCreate方法,就是通过反射生成源apk的application对象,将壳的application去除,替换成源apk的application对象
实现了控制权的转换
详细的加固流程
-
加固图
发现我们首先需要准备一个源apk就是我们真正代码所在的地方,然后在准备一个壳apk,这个apk的功能就是做上面的说的
,解密apk,并加载apk,将控制权转换成我们的源apk,实际上壳这种东西就是自解密的,否则你的代码是被加密的,不解密
如何执行,所以脱壳这种东西找准时机很重要,找到解密后的,直接dump出来,就不多说了,继续,接下来就是我们需要
将源apk加密后,塞进壳apk的dex的后面,其实我感觉塞哪里都可以,只是这里比较方便,同时又具有迷惑性,你要塞到其他地方
也容易被找到,然后注意这时候壳apk由于塞进去了新东西,那么文件的唯一性就发生了变化,所以前面的三个字段是需要重新
计算,并填充的 -
源apk就不放了,代码类似hello world,主要放下壳apk的代码,这样对理解动态加载是有好处的
发现反射用的非常多,实际上反射真的强,反射是可以任意通过加载类,返回一个类对象,同时还可以对类对象的属性
进行修改,主动调用等,非常强,实际上xposed api底层全是反射写的,这个方法,上文讲过是新建dexclassloader,并
替换mclassloader的,下面跟到系统源码中分析
-
源码分析
有这个sCurrentActivityThread字段,发现是一个ActivityThread的对象,再接下来
发现这个方法是可以返回这个对象的,那么我们就拿到了这个对象
拿到这个对象,那么我们可以通过反射再拿到这个字段,里面包名加一个WeakRerference 键值对,发现
这个WeakRerference是一个列表,里面的内容是LoadedApk对象,实际上这个对象有个字段就是我们一直
要找的mClassLoader -
所以说attachBaseContext就是通过不断通过反射,拿到对象,再修改了mClassLoader,这里反射我个人的理解
是这样的,首先那个scurrentActivity字段是一个static字段,意味着这个字段只属于类的,而不是归于实例,所以
反射得到始终是那个ActivityThread对象,那个mClassLoader,而mClassLoader是系统组件类的加载,只有修改了
这里,才可以让加载源apk的dex中的,四大组件具有生命周期!