Android应用加固原理

一、前言

Android开发者常常面临的一个问题就是防破解、 防二次打包。现如今安全问题越来越重要,越来越多的Android开发者也开始寻求安全的保护方案。

二、什么是加壳?

移动平台攻防技术的发展基本是沿着PC端发展轨迹在进行,从windows平台的加壳脱壳反调试到Andriod的平台apk加固,反调试代码混淆等。

加壳是在二进制的程序中植入一段代码,在运行的时候优先取得程序的控制权,做一些额外的工作。大多数病毒就是基于此原理。PC EXE文件加壳的过程如下:
在这里插入图片描述

三、加壳作用和分类

作用:

加壳的程序可以有效阻止对程序的反汇编分析,以达到它不可告人的目的。这种技术也常用来保护软件版权,防止被软件破解。

分类:

从App的加固技术来看:主流分为dex加密和so加密,目前来看保护dex文件更为重要,应为dex反编译后的java代码可读性更强。

四、APK文件结构

在这里插入图片描述
每个文件及文件夹的作用如下表所示。

文件或目录 说明
assets文件夹 存放资源文件的目录
lib文件夹 存放ndk编译出来的so文件
META-INF文件夹 1.该目录下存放的是签名信息,用来保证apk包的完整性和系统的安全性 2.CERT.RS 保存着该应用程序的证书和授权信息 3.CERT.SF 保存着SHA-1信息资源列表 4.MANIFEST.MF 清单信息
res文件夹 存放资源文件的目录
AndroidManifest.xml 一个清单文件,它描述了应用的名字、版本、权限、注册的服务等信息。
classes.dex java源码编译经过编译后生成的dalvik字节码文件,主要在Dalvik虚拟机上运行的主要代码部分
resources.arsc 编译后的二进制资源文件

五、DEX文件格式

5.1什么是DEX文件?

他是Android系统的可执行文件,包含应用程序的全部操作指令以及运行时数据

由于dalvik是一种针对嵌入式设备而特殊设计的java虚拟机,所以dex文件与标准的class文件在结构设计上有着本质的区别

当java程序编译成class后,还需要使用dx工具将所有的class文件整合到一个dex文件,目的是其中各个类能够共享数据,在一定程度上降低了冗余,同时也是文件结构更加经凑,实验表明,dex文件是传统jar文件大小的50%左右
在这里插入图片描述

5.2dex文件结构

Dex文件整体结构如下:
在这里插入图片描述
Dex文件整体结构说明:

数据名称 解释
dex_header dex文件头部记录整个dex文件的相关属性
string_table 字符串数据索引,记录了每个字符串在数据区的偏移量
type_table 类似数据索引,记录了每个类型的字符串索引
proto_table 原型数据索引,记录了方法声明的字符串,返回类型字符串,参数列表
field_table 字段数据索引,记录了所属类,类型以及方法名
method_table 类方法索引,记录方法所属类名,方法声明以及方法名等信息
class_def 类定义数据索引,记录指定类各类信息,包括接口,超类,类数据偏移量
data_section 数据区,保存了各个类的真是数据

下面是DEX文件目录:
在这里插入图片描述
这里面,有3个成员我们需要特别关注,这在后面加固里会用到,它们分别是checksum、signature和fileSize。

checksum字段

checksum是校验码字段,占4bytes,主要用来检查从该字段(不包含checksum字段,也就是从12bytes开始算起)开始到文件末尾,这段数据是否完整,也就是完整性校验。它使用alder32算法校验。

signature字段

signature是SHA-1签名字段,占20bytes,作用跟checksum一样,也是做完整性校验。之所以有两个完整性校验字段,是由于先使用checksum字段校验可以先快速检查出错的dex文件,然后才使用第二个计算量更大的校验码进行计算检查。

fileSize字段

占4bytes,保存classes.dex文件总长度。

这3个字段当我们修改dex文件的时候,这3个字段的值是需要更新的,否则在加载到Dalvik虚拟机的时候会报错。

为什么说我们只需要关注这三个字段呢?

因为我们需要将一个文件(加密之后的源Apk)写入到Dex中,那么我们肯定需要修改文件校验码(checksum).因为他是检查文件是否有错误。那么signature也是一样,也是唯一识别文件的算法。还有就是需要修改dex文件的大小。

不过这里还需要一个操作,就是标注一下我们加密的Apk的大小,因为我们在脱壳的时候,需要知道Apk的大小,才能正确的得到Apk。那么这个值放到哪呢?这个值直接放到文件的末尾就可以了。

所以总结一下我们需要做:修改Dex的三个文件头,将源Apk的大小追加到壳dex的末尾就可以了。

六、加固原理

在这里插入图片描述
Dex文件整体加固原理如下:
在这里插入图片描述
在该过程中涉及到三个对象,分别如下:

  • 源程序

源程序也就是我们的要加固的对象,这里面主要修改的是原apk文件中的classes.dex文件和AndroidManifest.xml文件。

  • 壳程序

壳程序主要用于解密经过加密了的dex文件,并加载解密后的原dex文件,并正常启动原程序。

  • 加密程序

加密程序主要是对原dex文件进行加密,加密算法可以是简单的异或操作、反转、rc4、des、rsa等加密算法。

该加固过程可以分为如下4个阶段:

(1) 加密阶段

(2)合成新的dex文件

(3)修改原apk文件并重打包签名

(4)运行壳程序加载原dex文件

6.1 加密阶段

加密阶段主要是讲把原apk文件中提取出来的classes.dex文件通过加密程序进行加密。加密的时候如果使用des对称加密算法,则需要注意处理好密钥的问题。同样的,如果采用非对称加密,也同样存在公钥保存的问题。
在这里插入图片描述

6.2 合成新的dex文件

这一阶段主要是讲上一步生成的加密的dex文件和我们的壳dex文件合并,将加密的dex文件追加在壳dex文件后面,并在文件末尾追加加密dex文件的大小数值
在这里插入图片描述
在壳程序里面,有个重要的类:ProxyApplication类,该类继承Application类,也是应用程序最先运行的类。所以,我们就是在这个类里面,在原程序运行之前,进行一些解密dex文件和加载原dex文件的操作。

6.3 修改原apk文件并重打包签名

在这一阶段,我们首先将apk解压,会看到如下图的6个文件和目录。其中,我们需要修改的只有2个文件,分别是classes.dex和AndroidManifest.xml文件,其他文件和文件加都不需要改动。

首先,我们把解压后apk目录下原来的classes.dex文件替换成我们在0x02上一步合成的新的classes.dex文件。然后,由于我们程序运行的时候,首先加载的其实是壳程序里的ProxyApplication类。所以,我们需要修改AndroidManifest.xml文件,指定application为ProxyApplication,这样才能正常找到识别ProxyApplication类并运行壳程序。
在这里插入图片描述

6.4运行壳程序加载原dex文件

Dalvik虚拟机会加载我们经过修改的新的classes.dex文件,并最先运行ProxyApplication类。在这个类里面,有2个关键的方法:attachBaseContext和onCreate方法。ProxyApplication显示运行attachBaseContext再运行onCreate方法。

在attachBaseContext方法里,主要做两个工作:

读取classes.dex文件末尾记录加密dex文件大小的数值,则加密dex文件在新classes.dex文件中的位置为:len(新classes.dex文件) – len(加密dex文件大小)。然后将加密的dex文件读取出来,加密并保存到资源目录下

然后使用自定义的DexClassLoader加载解密后的原dex文件

在onCreate方法中,主要做两个工作:

通过反射修改ActivityThread类,并将Application指向原dex文件中的Application

创建原Application对象,并调用原Application的onCreate方法启动原程序

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

猜你喜欢

转载自blog.csdn.net/weixin_42600398/article/details/124704748