苹果系统的封闭性导致 iOS APP 安全性比较高,但是实际上 iOS 应用本身被破解的难度并不高,一旦在越狱设备上,ipa 被分析就会变得很容易,本文通过讲解 iOS APP 的破解分析过程来引出我们要如何的保护我们的应用。经过保护,iOS APP 的安全性会获得很大的增强,大大提高了破解者破解的难度。对于 iOS 开发者来说,有必要了解这些措施,特别是针对一些金融、游戏类 APP 的开发。
世所公认,iOS 系统安全性非常高,很少出现漏洞,几乎不会中毒的情况。然而随着各种 iOS 安全隐患的频频出现,人们逐渐认识到,iOS 跟 Android 一样也面临严重的安全问题。苹果宣称所有的 iPhone 都很安全,不会被恶意软件攻击,其实这只不过苹果封闭式的系统管理能够及时处理漏洞罢了,这也正是苹果不敢开放的原因。
我们已经习惯,每个新的 iOS 系统出来没多久,就会有大牛找到越狱的方法。比较有名的越狱团队如 iH8Sn0w、Geohot、Comex 等,以及国内的盘古团队。就像最新 iOS 10.1.1 版本,刚出来一个星期,安全研究员 Luca Todesco 就在推特上晒图自曝越狱成功,iH8Sn0w 和盘古团队也取得了不错的进展。只要越狱了,iPhone 手机就处于完全裸奔状态,很多平时不能做的事情就可以做了,比如破解分析 APP、大范围泄露用户隐私数据等。
其中,跟我们 iOS 开发者息息相关的问题,主要就是被破解、分析。APP 被破解分析进而刷单作弊,或者 APP 被山寨以次充好等。APP 一直以来存在的 "山寨" 现象,引起越来越多开发者的不满,山寨泛滥的后果将是劣币驱逐良币,打击创新者的积极性,造成恶性循环。
下面举几个例子:
比如上面的《神庙逃亡》应用,左边是合法的,右边是山寨的,山寨的 APP 就把图标的背景色以及局部做了一些修改,看起来和正品是如此的相似。
这类 APP 在淘宝上都有销售。正常情况,一个手机只能有一个微信账号在线,但是微信分身版让用户可以在同一个手机上同时登录多个微信号,这样可以满足一些用户的不同需求,比如进行公众号营销、用不同的微信号联系不同的人等。同时这些破解后的微信还有一键转发小视频、一键评论、一键点赞等强大的功能。
下面是一款红包神器的运行页面:
打开这款神器后再登录微信,如果微信群里有人发出红包,它就会第一时间帮你抢到红包了,从此 "发家致富,迎娶白富美,走上人生巅峰",哈哈!
那么,看起来如此高级的东东又是怎么实现的呢?下面我们做简要的介绍,只有在了解了它们的实现原理后,我们才能更好地保护我们的 APP 不被分析、破解。
懂得如何攻击才会懂得如何防御,一切都是为了之后的防御作准备。这里总结一下为 hack 而做的准备工作。
(1)otool 可查看可执行程序都链接了哪些库。
(2)nm 可以显示程序符号表。
- nm -g DeviceInfo
(3)ldid:iPhoneOS.platform 提供的签名工具。
我们自己编译的程序需要签上名才能跑在 iPhone/iPad 上。
它通常是和 Clutch 一起使用的,因为 APP Store 上的 APP 都是加密过的,需要先解密。Clutch 解密后,就可以得到 APP 的源码结构,包括资源文件、二进制文件等,下面以 XX 新闻 APP 为例:
"class-dump NewsBoard",就可以得到应用的类信息,包括函数名,下面是该 APP 的一个登陆页面的头文件:
静态分析 iOS APP 的工具除了 IDA,还有一款强大的工具– Hopper Disassembler,在某些方面,它比 IDA 更强大。
上图显示,从 IDA 工具就可以看到该 APP 使用的一些类名和方法名,进而就可以分析到方法里面的实现逻辑了。
我们在开发一款 SDK 的时候,想了解下公司外部竞品 SDK 的使用情况,到底有多少 APP 在集成他们的 SDK。那么,这到底该怎么做呢?
去竞品那里打听?好像不太现实,唯一的办法就是 "自动动手,丰衣足食"。我们从 XX 助手上获取一定数量的 APP,一般是拉取榜单的数据,比较有意义,然后分析拉到的 APP 里包含了哪些 SDK。当然这得基于概率统计学的原理,获取足够多的样本,比如一万、十万都是可以的。那么又如何从 XX 助手服务器拉取这些数据呢?
大家可能都会想到,那就是分析 XX 助手的网络协议,然后通过代码模拟网络协议,请求数据,获取 APP,再分析 APP 的符号。分析网络协议,最简单的就是网络抓包,但是估计现在很难再有裸奔的网络包了,XX 助手确实也没有明文的网络包,所以只有逆向分析了。值得庆幸的是,它的 APP 没有做加固、保护,分析起来就简单多了。、
我们首先从界面分析程序的大体逻辑结构。
来到 XX 助手的榜单页面,使用 cycript 打印界面布局:
- [[UIAppkeyWindow]recursiveDescription].toString()
找到每一个下载控件,这里随便找一个:
通过 UITableViewCellContentView 这个控件,找它的包含关系。
使用 [#0x15baf520nextResponder] 往上找,可以得到:TRTableMultipleViewCell。
TRTableMultipleViewCell 分为 3 列,每一列包含一个 TRAppListSubCell,而每个 TRAppListSubCell 对应一个 TRAppInfo 对象,猜测这个 TRAppInfo 就是下载后的数据对象,Hook 这个类的方法可以看到:
TRAppInfo 对应一个 App 的相关信息,包括下载地址,为了得知这些信息是怎么初始化的。在 -[TRAppInfosetAdsite:] 下断点: b-[TRAppInfosetAdsite:],然后查看调用堆栈:
其中的一个类 TRApiServices 很像是网络请求的接口。Hook 该类的调用输出,点击榜单,并有了以下 log 输出:
至此,我们基本确定了我们需要的函数名了。
接下来,就是逆向分析 getChartsAppListForCountryId 和 parseGetChartsAppListData 这两个函数了。
使用 IDA 工具打开 XX 助手 APP,定位到 getChartsAppListForCountryId 这个函数:
再进一步去分析 "writeBodyHeader" 方法以及 "getBody" 等方法,就可以知道网络请求的发送格式了;要想知道网络数据返回的格式,还得去分析 "parseGetChartsAppListData:error" 这个方法,一切准备妥当后,就可以下载了。
从上面的分析来看,我们可以从以下几个方面来保护我们的 APP:
1. 字符串混淆
对应用程序中使用到的字符串进行加密,保证源码被逆向后不能看出字符串的直观含义。
2. 类名、方法名混淆
对应用程序的方法名和方法体进行混淆,保证源码被逆向后很难明白它的真正功能。
3. 程序结构混淆加密
对应用程序逻辑结构进行打乱混排,保证源码可读性降到最低。
4. 反调试、反注入等一些主动保护策略
这是一些主动保护策略,增大破解者调试、分析 APP 的门槛。
字符串会暴露 APP 的很多关键信息,攻击者可以根据界面显示的字符串,快速找到相关逻辑的处理函数,从而进行分析破解。加密字符串可以增加攻击者阅读代码的难度以及根据字符串静态搜索的难度。
比如一个 APP 中有如下的一些字符串定义在代码文件中:
经过加密后,代码文件变成如下的形式:
里面已经没有明文的字符串了,全是用 byte 的形式保存的,打包生成 APP 后,他们也就无法直观的看出实际内容了, 这对破解者会造成巨大的难度:
符号混淆的中心思想是将类名、方法名、变量名替换为无意义符号,提高应用安全性;防止敏感符号被 class-dump 工具提取,防止 IDA Pro 等工具反编译后分析业务代码。
比如一款混淆后的 APP, 用 IDA 等工具打开,如下图所示:
"Labels" 栏里,显示的这些符号,不管是类名还是方法名,谁也看不出来到底什么意思,这个函数到底是什么功能,就有点丈二和尚摸不着头脑的感觉,这就大大增加了破解者分析 APP 的难度。
代码逻辑混淆有以下几个方面的含义:
对方法体进行混淆,保证源码被逆向后该部分的代码有很大的迷惑性,因为有一些垃圾代码的存在;
对应用程序逻辑结构进行打乱混排,保证源码可读性降到最低,这很容易把破解者带到沟里去;
它拥有和原始的代码一样的功能,这是最最关键的。
混淆前后的对比如下(左边是原始结构,右边是混淆后的结构):
下面以 iOS APP 中的 main 函数为例:
它就只有一行有效代码,包含两个关键函数,已经算最简单的函数体了,混淆前的汇编代码如下:
这里主要包含两个 API 的符号: NSStringFromClass、UIApplicationMain。其余就是一些消息发送以及内存管理的相关符号,但如果进行一定的代码逻辑混淆后,这个结构就会变得大不一样了。
NSStringFromClass、UIApplicationMain 这两个函数,逻辑结构已经变得非常复杂了,如果一个函数中,包含更多的代码的话,那这个结构将更加复杂,对破解者来说将是一个很耗时间、精力的过程,一般早早就会放弃分析了。
对程序中出现的 URL 进行编码加密,防止 URL 被静态分析。
对客户端传输数据提供加密方案,防止通过网络接口的拦截获取数据。
除了上面的一些被动保护方法,我们还可以加入一些主动的防护机制,比如反调试等。
iOS 平台下的 Anti-Debug 方法一般有以下一些:
检查进程的状态是否为 P_TRACED。
调用 ptrace 请求来检查进程是否被调试。由于可能被攻击者绕过该方法的调用,在应用的多处增加 ptrace 函数会提高应用的安全性。
通过 sysctl 查看信息进程里的标记,判断自己是否正在被调试。sysctl 是用以查询内核状态的接口,并允许具备相应权限的进程设置内核状态。
iOS 下的这些方法,相对于 Linux 下的方法要少很多,例如 fork 一个子进程,ptrace 父进程进行检测方式不再奏效。而且,要完全防止程序被调试或者被逆向,理论上是不可能的,但可以增加破解者调试的难度。
总之,添加以上的一些保护措施后,iOS APP 的安全性会获得很大的增强,大大提高了破解者破解的难度。对于 iOS 开发者来说,有必要了解这些措施,特别是针对一些金融、证券类 APP 的开发,保护方面的需求比较大,比如国内某知名移动支付工具就添加了一些调试检测以及反调试的功能。
来源: http://www.tuicool.com/articles/z6ZbAzf