一、前言
在前两篇破解的文章中,我们介绍了如何使用动态调试来破解apk,一个是通过调试smali源码,一个是通过调试so代码来进行代码的跟踪破解,那么今天我们就这两篇文章的破解方法,来看看Android中开发应用的过程中如何对我们的应用做一层安全保护,当然现在市场中大部分的应用已经做了一些防护策略,但是没有绝对的安全,破解只是时间上的问题。所以攻破和防护是相生相克,永不停息的战争,没有绝对的安全,也没有万能的破解之道。
下面我们就来看看如何做到我们的应用更安全,我们主要从这五个方面来看看怎么操作:
1、混淆策略
2、应用的签名
3、修改Native函数名
4、反调试异常检测
5、应用的加固策略
当然还有其他防护方法,我们今天就介绍这五种,后续还有的话,继续补充
二、技术原理
第一种方式:混淆策略
混淆策略是每个应用必须增加的一种防护策略,同时他不仅是为了防护,也是为了减小应用安装包的大小,所以他是每个应用发版之前必须要添加的一项功能,现在混淆策略一般有两种:
1、对代码的混淆
我们在反编译apk之后,看到的代码类名,方法名,已经代码格式看起来不像正常的Android项目代码,那么这时候就会增加阅读难度,增加破解难度,像这样的代码混淆:
我们一般现在的破解查看Java层代码就是两种方式:
一种是直接先解压classes.dex文件出来,使用dex2jar工具转化成jar文件,然后再用jd-gui工具进行查看类结构
一种是使用apktool工具直接反编译apk,得到smali源码,阅读smali源码
不过这种代码混淆有时候在一定程度上能够增加混淆策略,但是有时候也不是很安全,因为我们知道我们在破解的过程中一般是找程序的入口,那么这些入口一般都是Application或者是MainActivity之类的,但是这些Android中的组件类是不能进行混淆的,所以我们还是有入口可寻,能够找到入口代码,然后进行跟踪。
2、对工程资源的混淆
我们上面说到了对代码的混淆能够增加一定的代码阅读难度,有时候我们为了防止资源的保护也是可以做混淆的,这个资源混淆原理这里就不多解释了,微信团队已经将这个功能开源,不了解的同学可以转战github查看:
https://github.com/shwenzhang/AndResGuard
当然资源混淆还有一个很大的好处就是减小apk包的大小,当然这个不是本文讨论的知识点,这里我们讨论的是混淆资源增加破解查找资源的难度,先来看一下混淆资源之后的结果:
这里我们可以看到,一个混淆资源的应用,反编译之后查看他的string.xml内容,发现他的name全是简单的混淆字母,那么这个对于我们之前的那种可以通过name的值,来查找对应的字符串内容来获取消息,这个将是很蛋疼的一件事,因为你这时候如果全局搜索一个name值的话,比如这里的name='a',那么得搜出多少个这样的name,查找也是很好时间的,其实在没有混淆之前,一般string中的name都是比较唯一的一种值,查找的话不会有那么多查找结果,而且查找时间也是很短的。
破解之道:
但是对于这种混淆资源也是绝对的防护安全,因为我们知道一般在反编译之后的Java代码中,看到的获取资源值的时候,并不是资源的name值了,而是资源对应的int类型的值,比如这样:
这里获取一个字符串的值,那么,这些int类型的值,我们可以在反编译之后的res/values/pulblic.xml中找到:
比如这里的2131230929变成16进制就是:0x0x7f0800d1,我们在public.xml中查找,找到了name='ey‘的一项,然后再去string.xml中进行name查找:
好吧,还是找到了这个字符串的值,反编译之后的public.xml中记录了所有资源的id和整型值对应值,混淆之后的代码中看到的都是资源id的整型值,那么这么一看混淆并没有什么用途。只能偏偏小白了。
从上面的两处混淆策略看到,混淆对于破解并没有什么太大的阻碍,也是只是一个障眼法,不过混淆的另外一个功能就是减少apk包的大小,这个也是每个应用添加混淆的最主要原因。
第二种方式:应用的签名
我们知道Android中的每个应用都是有一个唯一的签名,如果一个应用没有被签名是不允许安装到设备中的,一般我们在运行debug程序的时候也是有默认的签名文件的,只是IDE帮我们做了签名工作,一般在应用发