Android中apk加固完善篇之内存加载dex方案实现原理 不落地方式加载

               

一、前言

时隔半年,困扰的问题始终是需要解决的,之前也算是没时间弄,今天因为有人在此提起这个问题,那么就不能不解决了,这里写一篇文章记录一下吧。那么是什么问题呢?

就是关于之前的一个话题:Android中apk加固技术实现

关于这个问题,之前的一篇文章已经说过了,没有了解的同学可以点击这里:Android中apk加固技术实现  

请务必仔细的看完这篇文章,不然今天说的内容会感觉很蛋疼的,因为今天的文章就是为了解决当初的加固技术遗留的问题,这里先大致来说一下加固apk的原理吧,先来看一张图:


看到这张图其实,还是很好理解的,就是我们把需要加固的apk,外部包装一层壳,而这个壳的作用是为了解密源apk的,比如现在360加固都是采用这种思想,我们可以看一个简单的360加固之后的程序的AndroidManifest.xml文件:


看到了吧,这里StubApplication就是360加固给需要加壳的apk添加的一层Application。这样启动加壳之后的apk,其实是先启动这个Application,然后这个Application就开始解密apk操作,然后动态加载apk运行源程序,所以这里我们还看到有一个加密apk的过程,可以看这张图:


这个就是把源程序的apk塞到壳apk的dex文件中,这样壳Application就可以读取dex中的数据,进行解密即可。

从上面的加固思想来看,还是有一些风险的,那就是对于加固的apk,他启动的时候实际上是先启动壳程序,所以这样就会把我们的一些数据暴露给了这些加固程序,所以在加固apk的时候还是要考虑慎重。


二、加固遗留的问题

好了,上面就简单说了一下如何加固apk的大体流程,那么在这个实现过程中当初有一个问题,就是我们解密之后的apk程序是放在/data/data/xxx/cache目录下的,然后在用DexClassLoader进行加载apk,然后运行程序,那么这里就存在两个问题了?

1、解密之后的apk源程序放在指定目录的话,还是存在被破解的风险,因为这种落地方式解密,是很容易获取解密之后的apk的

2、在解密得到源程序apk,然后再用DexClassLoader进行加载,这里相当于两次把apk加载到内存中,第一次是解密的时候,第二次是加载apk的时候,那么这效率就会大大降低了

好了看到了有这两个问题,那么其实我们的解决思路很简单,就是如何做到不落地的解密apk程序,在解密完之后得到apk数据,立马进行内存数据的字节码加载,不需要在保存到本地的apk作为中转站了。


三、解决问题思路

我们先来猜想一下,系统既然能够加载dex文件,那么他会不会有一个能够直接加载文件字节码的方法呢?因为不管怎么样,加载一个文件到最后还是需要解析dex文件,然后map到内存中的,那么我们可以通过源码来看看有没有这样的方法?

那么我们既然最后都是要加载,肯定是用DexClassLoader类,那么我们看看这个类的源码:

源码位置:Android源码目录\libcore\dalvik\src\main\java\dalvik\system\DexClassLoader.java


擦,我们看到,他只有一个构造方法,就是需要传入加载文件的路径,没有能够直接出入字节数据的方法,那怎么破呢?不急,我们继续看他的父类BaseDexClassLoader源码:

源码位置:Android源码目录\libcore\dalvik\src\main\java\dalvik\system\BaseDexClassLoader.java

其实这个类,就是PathClassLoader和DexClassLoader的共同父类,关于这两个加载器的区别,不了解的同学可以看这里:

Android中的类加载器详解 这里就介绍了这两个类加载的区别和联系。


看到,在BaseDexClassLoader的构造方法中,有一个重要的类DexPathList,他就是解析加载文件的类,

源码位置:Android源码目录\libcore\dalvik\src\main\java\dalvik\system\DexPathList.java


看到了,这里知道了Android中能够加载的四种文件格式:dex/jar/zip/apk

查看他的构造方法:


有一个makeDexElements方法,进入查看:


在这里,用loadDexFile方法来加载文件,返回一个DexFile对象,那么我们再去查看这个类

源码位置:Android源码目录\libcore\dalvik\src\main\java\dalvik\system\DexFile.java


调用loadDex方法,返回DexFile对象:


在进入看构造方法:


这里有一个核心的地方,调用了openDexFile方法,然后返回一个int值:

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值