本文对dex加壳机制中的DexClassLoader部分做了稍微详细的介绍,解决了我的一些疑问,收藏之!
原文地址:http://blog.csdn.net/beyond296089727/article/details/45418803
JAVA 运行所需要依赖的API的是动态链接的,这个跟C/C++不一样,C/C++开发的程序可以是静态链接的也可以是动态链接的,其中静态链接是在编译时已经做好的,
动态链接的运行时才链接的,也就是window 的DLL文件,linxu的SO文件都是动态链接库。java是动态链接,也就是说我们代码中 new一个对象,这里只介绍DexClassLoader,那我们怎样用她来加壳免杀?
先看看API文档的说明他有四个参数,dexpath表示所要加载DEX文件的路径,
箭头指向的就是原DEX,就是被加密保护的,至于加密解密其实很简单,我举个最简单的例子,把要保护的DEX文件
的每个字节值+1,解密时-1,这样即使拿到DEX也没用。加密我们可以事先通过算法加密,然后才放到APK里,
关键是解密,我们都知道APK的入口是application类,这时我们这样在applicatian类里运行加密程序完成DEx的解壳然后用dexclassloader加载并运行,
当然了处于安全,解壳和加载DEx的算法应该放在SO,在application里通过JNI调用,其实爱加密也是这样做
图中的箭头指向就是他的解密SO
关于爱加密详细原理可以参考这里
http://blog.csdn.net/chengyingzhilian/article/details/38372601
所以用dexclassloader加壳就这么简单
至于包名的跟不用说了,每个APK都有自己唯一的包名,没有源码情况下
改包名麻烦,也就是说包名一般不该,所以给杀毒软件提供了很好的特征
依据,也就是说这个包名的APK如果被检测为木马的,哪怕代码在修改
包名不改很容易看出。
不过这里我不提倡大家用于实质非法活动,这是供大家学习研究,对杀毒
安全的研究和理解
关于用dexclassloader动态加载DEx存在的问题,我们知道dexclassloader
加载的类生命周期是虚拟机直接管理,但是对于组件类比如activity他们的声明周期不是由虚拟机直接管理,而是由各种对应的框架层manager管理,比如activity是有activitymanger
管理这就是为什么我们不能new activity的原因,只能通过startActivity()反射加载。
但是最终activity也是用户classloader加载的。之所以这个组件类是用各框架层管理器
管理是有原因的,因为这些类的声明周期是随机的,不可预知的,比如接受短信的
BroadcastRecivier,当有短信来时系统收到了,交给广播管理器广播intent,如果我们的
的androimainfest.xml定义了一个<recivier>,来接受短信,这是广播管理器会通知我们APP的主线程new 我们的BroadcastRecivier类并且调用onReciver()函数,这一切都是通过反射加载的。也就是new BroadcastRecivier是有短信来了才NEW,而 短信是随机的,所以我们不可能在代码中new ,你知道短信仕么时候来吗?!那么你NEW?!
这里就关键了,BroadcastRecivier组件类最终也是用classloader加载的,如果这个classloader是我们定义的Dexclassloader那么不管我们的组件类放在哪里都会被正常加载并且不存在生命周期问题,然而加载这些组件类的都是都APK的主线程ActivityThread来做,他用的是他自己的classloader加载,我们只把他的classloader替换成我们移动一的就得了
关于实现方案我是参考jack_jia的来做http://blog.csdn.net/androidsecurity/article/details/8809542
红色箭头是包含有activity等组件类的DEX,椭圆椭圆圈是替换classloaderder