加密混淆,应用就安全了嘛?

作者:dfqin

地址:https://www.jianshu.com/p/fe0206f8be5b

前言

昨天dfqin同学给我们分享了移动端加密和混淆的相关知识。今天让继续跟着他学习其他移动端的安全知识。

NDK

NDK全称为Native Development Kit,翻译过来叫原生开发工具包,官方解释是可以在Android中使用C/C++的工具。我没找到这里Native的详细解释,个人理解常规Android程序是运行在虚拟机上面的,而Native指直接运行在操作系统上面的程序,可以调用操作系统的API。

一般情况下我们没有必要使用NDK,官方也提到了使用native开发会增加开发过程的复杂性。但是对于一些计算密集型的应用,例如游戏、图像处理,使用NDK能提高运算性能。还有一些情况为了复用现有库或者跨平台库,也会选择NDK。上面提到的一些核心算法和秘钥,大家选择放到native层,潜意识中也是默认native的破解难度比java高,还有欺负大部分Android程序员不会写C/C++代码:)


我们可以创建一个新工程,创建时勾选上"Include C++ support",如下图:

这时会创建一个支持NDK的默认工程,项目里包含从C++代码中获取一个字符串的demo:

我们编译出apk并反编译这个程序如下图,会发现包里面多了一堆libnative-lib.so(其实只是一个库,为了支持不同的CPU架构编程出了多个版本)。

字符串的生成的实现放到了这个so库里面,相比较直接在java代码中生成字符串,破解起来的确麻烦了些。这个时候如果想破解拿到这个字符串,该怎么办呢?


一个简单的办法,直接写java代码,通过jni调用这个so的方法。这尼玛就尴尬了,本来封装so是为了隐藏数据,结果倒好,别人才不管你怎么实现,把你直接拿来用。为了避免这种尴尬,我们可以在so中判断当前应用的签名,前面分析过,只要别人拿不到你的keystore就没办法伪造你的签名。如果没办法直接调用这个so,只能想办法破解才能洞察到里面隐藏的秘密了,下面我们谈一下怎么来破解。

PE/ELF和反汇编

上面提到了我们需要破解so文件才能获取里面的信息,在破解之前我们要先理解so文件到底是什么。这里我们我们需要了解一种文件格式,即Windows系统中的PE(Portable Executable)和Linux系统下的ELF(Executable Linkable Format),看全称基本了解这种文件的用途。

其实在Windows系统上我们平时运行的.exe安装文件和使用共(破)享(解)软件时用来覆盖的.dll动态链接库文件,都是PE格式文件。在Linux系统上(我们可以把Android理解为Linux系统)的.o目标文件、.a静态连接库和.so动态连接库,都属于ELF文件。如下图所示,一段C程序编译生成ELF文件后的结构

当然我们直接用文本编辑器打开so文件,看到的是如下二进制文件:

根据ELF文件格式的定义,可以把这个二进制文件还原为图3.4右边的结构。这些细节很复杂我们也没必要去全部弄清楚,我们可以使用一些命令直接查看ELF文件。以图3.2中的C++代码生成的so为例,我们输入:

readelf -a libnative-lib.so

可以看到结果:

内容很长,不了解ELF格式的话很难看懂(我这里在使用“greadelf”是因为使用的mac系统自己安装的类似工具),我们可以先大概看一下,这里的“节头”其实就是对应的图3.4中的p,我们可以查看第12个segment——.rodata:

我们发现了之前辛苦藏到so中的字符串"Hello from C++"。如果想看代码实现,可以使用objdump命令,能看到反汇编后的代码。


现在我们可以理解ELF文件已经是机器指令了,我们如果想看一些代码逻辑,要么像机器一样读机器指令,要么把这些机器指令反编译成人类方便阅读的汇编代码(汇编语言人类也很难读的好吧),这个过程我们就是反汇编。


当然真正去破解一些so文件时,使用上面的办法效率太低,这是可以去使用一些专业的破解工具,里面集成了很多很强大的功能,可以大大提高工作效率,例如使用IDA直接把so打开,我们可以很方便的定位到jni函数:

从这个例子的分析,我们为了增加破解难度,可以动态注册jni函数并且自定义函数名,避免破解者一眼就找到Java_com_xxx这样的native函数。另外一点就是要隐藏在字符串,不可以直接明文写在代码中,至少做个拼接吧,或者添加一定的逻辑动态生成。大家可以想一下,还有没有其他的办法增加破解难度?

加壳与脱壳

通过上面的分析我们可以知道,无论是编译java代码生成的dex文件,还是编译C/C++代码生成的so文件,反编译成本都不是特别的高,如果想增加破解难度,还能做什么呢?其实这个问题一直存在,大家想想从十几年前的PC时代,大部分人使用的都是windows,当时大家使用的office、photoshop有几个不是破解版的?因为当时网络不发达,很多游戏和工具软件都是本地验证授权的,再加上法律监管空白,软件破解行业甚是红火。


在当时就有了加壳脱壳这个说法,看一些破解软件的文章时,第一步基本都是脱壳。加壳直观理解就是给程序加一层壳,可以用来对原程序进行资源压缩、防调试、防注入、防反编译,也就是说通过一个壳把原来的程序保护了起来。

我们知道一个常规Android程序它的所有代码都在dex文件中,程序启动时要先把这个dex文件载入到内存中,所以如果要加壳的话,主要工作就是把原dex文件加密或者隐藏起来,放一个新的壳dex到apk中,程序启动时运行这个壳dex,然后这个壳dex在运行时再加载原dex,用一张图表示如下:

其实这时候我们发现,破解原dex的工作变成了破解壳dex了,最终的原理是一样的,早期的梆梆、360等公司的加固方案都被人破解,网上能查到破解步骤。当然他们的加固方案升级很快,网上看的破解方案对于新的加固方案基本已经无效。我们使用腾讯的乐固加密一个不包含so库的APK后反编译后可以看到如下:

我们可以看到程序一开始就加载了libshella.so库,这里我们可以推测我们的原dex被加密为了mix.dex和mixz.dex,dex的动态还原方案的实现放到了libshell.so库中,即dex的加壳方案放到了so实现,再次佐证了大家公认so的破解难度比较高。这里我测试发现这两个so使用IDA反汇编工具已经无法直接打开了,很显然这个so是加过壳的。

关于so的脱壳,我也是小白,就不班门弄斧了,这里乐固.so V2.8版本的脱壳方案(乐固目前最新是V2.10),可以证明上面我们的推测是正确的,大家有兴趣可以看一下

https://bbs.pediy.com/thread-217556.htm

补充: 这是一年前的文章,当时认为加固是比较安全的方案,毕竟逆向so成本非常高,后面发现使用像xposed框架这样的hook技术,类似于降维打击,可以绕过加固技术轻松获取到dex文件。目前的乐固、360等大厂加固都可以绕过,从原理上看,加固技术对于这种hook技术获取dex也没有什么好办法,作为APP的作者,需要加强hook方面的防御来提高加固技术的安全性,后面有时间的话我会写一篇文章介绍这方面的攻防。

近期文章:

今日问题:

你的应用出过安全事故嘛?

打卡格式:

打卡 X 天,答:xxx 。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值