1.不可或缺的混淆java
Java 是一种跨平台、解释型语言,Java 源代码编译成的class文件中有大量包含语义的变量名、方法名的信息,很容易被反编译为Java 源代码。为了防止这种现象,咱们能够对Java字节码进行混淆。混淆不只能将代码中的类名、字段、方法名变为无心义的名称,保护代码,也因为移除无用的类、方法,并使用简短名称对类、字段、方法进行重命名缩小了程序的大小。
ProGuard由shrink、optimize、obfuscate和preverify四个步骤组成,每一个步骤都是可选的,须要哪些步骤均可以在脚本中配置。 参见ProGuard官方介绍。android
上面三个步骤使代码size更小,更高效,也更难被逆向工程。c++
通常来讲优化和预检选项在Android中是关闭的,脚本以下:
-dontoptimize
表示不进行优化,建议使用此选项,由于根据proguard-android-optimize.txt中的描述,优化可能会形成一些潜在风险,不能保证在全部版本的Dalvik上都正常运行。
-dontpreverify
表示不进行预校验。这个预校验是做用在Java平台上的,Android平台上不须要这项功能,去掉以后还能够加快混淆速度。 (在安装apk过程当中系统会对dex校验及优化成odex)算法
做为防御来讲对于混淆的需求就是Obfuscate,增长阅读代码的难度。api
二、签名校验
校验各个文件的信息,好比微信的dex文件校验,阿里聚安全的签名文件校验等高强度操做。
第一:直接在本地作防御,若是发现签名不一致直接退出应用
第二:将签名信息携带请求参数中参与加密,服务端进行签名校验,失败就返回错误数据便可安全
Android的签名机制能够有效防止应用二次签名后不能覆盖安装,具体原理这里不分析了,但也致使安装了二次签名的apk,没法覆盖安装正常签名的apk,因此在很容易被二次签名的防御基础上进行签名校验是有必要的,固然若是很难被反编译破解就能够酌情考虑了。
三、反调试异常检测
1)so跟踪调试是基于进程的注入技术,而后使用Linux中的ptrace机制,进行调试目标进程的微信
ptrace提供了一种使父进程得以监视和控制子进程的方式,它还可以改变子进程中的寄存器和内核映像,于是能够实现断点调试和系统调用的跟踪
ptrace机制有一个特色,就是若是一个进程被调试了,在他进程的status文件中有一个字段TracerPid会记录调试者的进程id值,能够选择两种方式:
1.轮训查看文件:/proc/[myPid]/status,读取TracerPid字段的值,发现大于0,就立马退出程序
2.通常一个进程只能被附加一次,咱们在破解调试的时候都会附加须要调试应用的进程,若是咱们先占坑,父进程附加本身,那么后面在附加调试就会失败
2) 调试状态检查
1.检查应用是否属于debug模式
直接调用Android中的flag属性:ApplicationInfo.FLAG_DEBUGGABLE,判断是否属于debug模式,为了防止如今破解者为了调试应用将应用反编译在AndroidManifest.xml中添加:android:debuggable属性值,将其设置true。而后就能够进行调试。
2.检查应用是否处于调试状态
借助系统的一个api来进行判断:android.os.Debug.isDebuggerConnected();这个就是判断当前应用有没有被调试
3.循环检查端口
查看设备的tcp端口使用状况 cat /proc/net/tcp
好比Frida框架,他的端口号是27042和27043,以及进程名是frida-server
四、加固方案
加固的基本步骤以下:
1. 从App原始apk文件里获取到原始dex文件
2. 对原始dex文件进行加密,并将加密后的dex文件和相关的存放到assert目录里
3. 用脱壳dex文件替换原始apk文件里的dex文件;脱壳dex文件的做用主要有两个,一个是解密加密后的dex文件;二是基于dexclassloader动态加载解密后的dex文件
4. 由于原始apk文件已经被修改,因此须要删除原始apk的签名信息,即删除META-INF目录下的.RSA、.SF 和MANIFEST.MF文件
5. 生成加固后的apk文件
6. 对加固后的apk文件进行签名,apk加固完成。数据结构
dex加固主要是防止被静态反编译,进而获取源码并修改架构
除了以上业务相关性弱的防御方案,还有防被抓包,防被hook等和业务密切相关的防御方案,如传输数据加密,防做弊等策略。并发
以上每一个防御策略都有对应的破解之道,固然破解了不表明不能防,防御只是增长破解的难度和时间,攻防没有永远的胜利方,有人攻就有人防,防御策略也在不断的升级更新换代。
要深刻理解Android安全防御,就必须了解Android应用的结构。
assets目录:
用于存放须要打包到APK中的静态文件,和res的不一样点在于,assets目录支持任意深度的子目录,用户能够根据本身的需求任意部署文件夹架构
lib目录:
程序依赖的native库(so库)
META-INF目录:
存放应用程序签名和证书的目录,包含的文件有CERT.RSA,CERT.DSA,CERT.SF和MANIFEST.MF,其中CERT.RSA是开发者利用私钥对APK进行签名的签名文件,CERT.SF,MANIFEST.MF记录了文件中文件的SHA-1哈希值
res目录:
存放应用程序的资源,存在这个文件夹下的全部文件都会映射到Android工程的.R文件中,生成对应的ID,res文件夹下能够包含多个文件夹,其中anim存放动画文件;drawable目录存放图像资源;layout目录存放布局文件;values目录存放一些特征值,colors.xml存放color颜色值,dimens.xml定义尺寸值,string.xml定义字符串的值,styles.xml定义样式对象;xml文件夹存听任意xml文件,在运行时能够经过Resources.getXML()读取;raw是能够直接复制到设备中的任意文件,他们无需编译。
resources.arsc:
资源配置文件,用来记录资源文件和资源ID之间的映射关系,用来根据资源ID寻找资源
AndroidManifest.xml:
应用程序的配置文件,程序打包时,会把AndroidManifest.xml进行简单的编译,便于Android系统识别,编译以后的格式是AXML格式。
classes.dex:
dex可执行文件,传统的Java程序,首先先把Java文件编译成class文件,字节码都保存在了class文件中,Java虚拟机能够经过解释执行这些class文件。而Dalvik虚拟机是在Java虚拟机进行了优化,执行的是Dalvik字节码,而这些Dalvik字节码是由Java字节码转换而来,通常状况下,Android应用在打包时经过AndroidSDK中的dx工具将Java字节码转换为Dalvik字节码。dx工具能够对多个class文件进行合并,重组,优化,能够达到减少体积,缩短运行时间的目的。
对于逆向首入门槛就是dex,了解dex的数据结构对防御和逆向都是极其重要的,dex文件结构分析文章很是多,这里很少赘述,不了解的先去了解下。
对于Android防御目前流行的最后方案就是加固,某些应用市场已经把加固和上架进行了绑定,说明加固的逆向难度公认度是很高的。
上面介绍了加固的基本步骤,市面上的加固方案都大同小异,最核心的部分就是对apk/dex进行加密-解析-动态加载,对dex加密各有各的方式和算法,了解dex结构和动态加载以后就能够对不一样加固方案进行具体分析了,不过度析大厂的apk以后发现都没有对dex进行加固就使人深思,也许在客户端的防御只是门槛,服务端的防御及防做弊才是终极防御策略,而加固会增长崩溃的几率,做为大流量的app来讲万分之一的几率也是很高的,而对dex加固的安全性并非最高的,因此放弃对dex加固也是有迹可循的。
做为Android应用开发者来讲,navite层的代码具备更高的挑战性,大部分Android开发者并不熟悉c/c++开发,因此so的加固应运而生。
动态连接库so:
动态连接库是程序运行时加载的库,当动态连接库正确安装后,全部的程序均可以使用动态库来运行程序。动态连接库是目标文件的集合,目标文件在动态连接库中的组织方式是按照特殊方式造成的。库中函数和变量的地址是相对地址,不是绝对地址,其真实地址在调用动态库的程序加载时造成。
so文件是基于ELF(Executable and Linking Format)文件格式。而so是共享目标文件,因此要想对so文件进行加密就必须了解ELF文件格式。
可执行连接格式(Executable and Linking Format)最初是由 UNIX 系统实验室(UNIX System Laboratories,USL)开发并发布的,做为应用程序二进制接口(Application Binary Interface,ABI)的一部分。工具接口标准(Tool Interface Standards,TIS)委员会将还 在发展的 ELF 标准选做为一种可移植的目标文件格式,能够在 32 位 Intel 体系结构上的 不少操做系统中使用。
目标文件有三种类型:
可重定位文件(Relocatable File) .o)包含适合于与其余目标文件连接来建立可执行文件或者共享目标文件的代码和数据。
可执行文件(Executable File) .exe) 包含适合于执行的一个程序,此文件规定了exec() 如何建立一个程序的进程映像。
共享目标文件(Shared Object File) .so) 包含可在两种上下文中连接的代码和数据。首先连接编辑器能够将它和其它可重定位文件和共享目标文件一块儿处理, 生成另一个目标文件。其次动态连接器(Dynamic Linker)可能将它与某 个可执行文件以及其它共享目标一块儿组合,建立进程映像。
目标文件所有是程序的二进制表示,目的是直接在某种处理器上直接执行。
了解ELF格式分析移步ELF文件格式与动态连接/静态连接与动态库/静态库。
经过对so中的section和函数进行加密来加固对逆向的难度会提升不少,虽然对于了解so的人来讲并非难事,好比动态调试一下,或者dump出内存中运行的dex,因此没有绝对的安全,只有相对的攻防。