看了下看雪的帖子分布,Android 帖子比 iOS 的帖子多了五六倍啊。本人之前也是在 Android 平台下进行分析比较多,因此这也算面向 Android 安全工程师的一个 iOS 入门介绍吧。本文以微信扔骰子小游戏为例,详细记录了一次完整 iOS 逆向分析的过程,希望能对大家有所帮助。本文主要讨论的是应用安全,因此关于越狱实现的部分不做深入介绍。关于XNU内核漏洞的分析和利用网上有很多相关的文章或书籍,比如:看一些公开的漏洞利用代码对加深印象也很有帮助,比如oob_timestamp的利用。对于本文而言只需要站在巨人的肩膀上使用这些封装好的利用即可。iOS越狱和Android root的的一个很大不同是前者系统封闭性高,碎片化较低,因此提权的方法也相对单一,不支持刷机,大部分都是通过漏洞去获取更高的权限(tfp0)。既然是专注应用层安全,就抓大放小,使用现有的越狱工具,站在前人肩膀上即可。越狱之后总算可以通过 ssh 进入到系统中,也就是相当于安卓世界的 adb shell 而已。既然是逆向分析,下一步就是获取应用的安装包,这在安卓中是一条adb pull命令,但苹果里要复杂一些。iOS 中大部分应用都从 Apple Store 即应用商店下载,而从应用商店下载的 app 是通过苹果签名和加密保护的,这是苹果 FairPlay DRM 数字版权保护的重要部分。为了能使用逆向工具进行分析,需要先对其进行解密,即俗称的砸壳。网上关于砸壳的资料和工具都很多,比如:这里面有些工具已经年代久远年久失修了,比如我就注意到 dumpdecrypted 在文件沙盒的处理上有点问题导致无法保存文件,需要经过简单 patch 。上面的这些工具大部分都是基于内存 dump,也就是需要通过 exec 执行目标程序才实现砸壳,这可能会让一些 App 通过在初始化函数中自我检测来对抗砸壳。如果出现这种情况,可以通过基于 mremap_encrypted 的方式进行解密,直接调用内核接口,无需启动目标程序实现静态砸壳。狱也越了,壳也砸了,接下来呢?直接丢到 IDA 里分析?不是不可以,但 iOS 的应用主体是一个巨大的 mach-o 文件,直接分析是很难的。还是以微信为例,主程序解密后单 arm64 架构的可执行文件就有 218 MB,即便在逆向工具里分析也会让人无从下手。这时候就需要一个入手点,用互联网的黑话来说,就是需要一个抓手。一个最常见的入手点就是 UI 界面。在安卓应用分析中一般通过 Android Studio 提供的uiautomatorviewer可以进行目标应用的 UI 分析,并通过 UI 的 ID 在反编译的代码中查找引用。不过这个方法我一般不用,而是直接获取顶层 Activity 然后找对应的类去分析。在 iOS 中,UI 分析却是一个有效的入手点,因为 iOS 应用都是基于 MVC 结构,View 中触发的事件由对应的 Controller 去实现。不管是基于 Springboard 的拖拖拽拽还是通过代码布局,MVC 的基调是不变的。在 Xcode 中有视图层级调试功能(Debug View Hierarchy),但需要目标开启调试。除此之外,更为常用的是一些视图调试框架,比如 Reveal 或者开源的 FLEX。用 FLEX 直接注入到进程中可实现 UI 的分析:这里用到了 cycript,后文再细说。或者可以用 Reveal 在电脑端分析,当然还是需要将 RevealServer.dylib 注入到目标进程中并调用[IBARevealLoader startServer],参考官方的 lldb 脚本,启动后 PC 端界面如下:点击发送骰子的区域是一个 UIImageView,其本身是没有响应点击事件的,因此要找对应的 ViewController 或者 Gesture Recognizer。根据 UI 信息能知道的是当前界面的 Controller 类是 BaseMsgContentViewController,所以我们可以通过脚本去跟踪发送骰子时该类所有的函数调用,如下所示:其中SendEmoticonMesssageToolView是个值得关注的函数,可以直接用 frida 打印函数堆栈:输出结果如下:在 WeChat 部分的回溯没有符号,因为已经去掉了。在 lldb 中也可以看到类似的结果:有符号更好,没有也无所谓,我们还是可以通过地址在逆向工具中查看代码。不过考虑到 ASLR 的存在,需要确认一下镜像的加载地址: vmmap 是我自己定义的一个 lldb 命令,参考了 gef 和 pwndbg 在 gdb 中的实现这里加载地址是 0x000102790000,而在 IDA 中 text 段的加载地址是 0x100004000,可以在后者进行 rebase,但是因为函数不多,所以先手动查找。另外用 lldb 也可以直接查看对应函数地址的偏移:根据 lldb 中每个函数地址在 TEXT 段中的偏移,可以在 IDA 中直接跳转到对应函数(返回值),整理对应的调用函数分别是:既然 IDA 可以识别出对应 OC 函数的符号,那么理论上这些符号也是可以还原的,如果经常需要进行动态分析,那么可以通过一些方法自动化恢复对应的符号,可以参考 iOS符号表恢复 以及 restore-symbol 等项目。通过动态分析找到了着手点,以及通过回溯调用栈找到了一些相关函数,其中并没有一目了然的设置骰子点数的函数 setDiceValue,所以要想改点数还需要对上面的函数进行进一步分析。到这里,逆向工程是不可避免了,一般而言我是能躺着绝不坐着,能坐着绝不站着,不到万不得已是不去逆向的。花开两朵,各表一枝,在前面砸完壳的第一时间我就预感到需要逆向,所以早早地把 200MB 的 MachO 丢进了 IDA,在文章写到这里时已经过去了四个小时,期间看了两集动漫,但是 IDA 还是没有全部分析完。所以在等待的时间里,先来简单介绍些 ObjectiveC 的底层实现。在学习 OC 的时候,总会看到说 OC 语言实现面向对象是通过发送消息,具体是怎么发送呢?因此在实际逆向之前,我们先来自己写一个程序来进行分析,以便了解 OC 的调用原理。以下面简单的 helloworld 为例:主要调用了两个方法,一个类方法和一个成员方法,编译后查看其汇编代码如下:且不管初始化部分,后面两个函数调用最终都进入了 objc_msgSend 函数,在苹果官网可以看到其函数原型:其中各个参数为:回到上面的例子,第一次类方法调用的参数为:第二次成员方法的调用参数为:程序的输出如下:所以,ObjectiveC 在实现上还是挺接近 C 语言的,这对于我们逆向而言方便很多。了解了简单的 OC 逆向之后,IDA 也跑的差不多了。根据栈回溯对应 OC 函数的名称,逐级往上看。首先是 didSelectorSelfDefinedEmotcion这个函数,表示选中了某个自定义表情,里面只是一些发送操作,所以并不是我们想要的;然后是 -[EmoticonBoardView onTapEmoticonWrap:atIndex:maxCountPerLin
...(已截断)
---
来源: 看雪论坛
原文链接: https://bbs.kanxue.com/thread-266971.htm
从微信扔骰子看iOS应用安全与逆向分析
350 浏览
5 回复
很清楚,学习了
写的很好 mark
谢谢大佬。学习了,系统学习的话还是建议大家找专业的书 比如:《iOS应用逆向与安全之道》101K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6A6N6r3g2E0i4K6u0W2K9X3c8Q4x3X3g2U0L8$3#2Q4x3V1j5I4x3U0R3H3x3o6b7J5y4W2)9J5k6h3S2@1L8h3I4Q4x3U0k6F1j5Y4y4H3i4K6y4n7
对照Android做分析,写的真棒
写的真好