阅读 6530

《iOS 应用逆向与安全》读后感

by 知识小集 · Lefe_x

最近各大“媒体”都在报道《iOS应用逆向与安全》这本书,这是自“小黄书”出版后的又一本关于逆向安全的书。而目前很多 iOS 开发者对逆向还非常“小白”,以至于盲目地觉得逆向很难、很厉害。而这本书的出现,无疑为逆向这个世界打开了另一扇窗,我们一起看看这扇窗里究竟“藏”了什么。本文并不打算介绍书中具体细节,只是说明每一章都讲了哪些内容,点到为止。

第一章 概述

本章主要对逆向整体进行描述,分别从应用中存在的风险、如何保护应用的安全、和开发工具的使用来介绍。而我觉得本章的核心是掌握逆向的流程和作用,了解 APP 开发中需要注意的安全问题。

逆向流程: 逆向的整个流程基本是相同的,而这些流程可以总结为:

  • 获取应用的 ipa 包,解密(如果是越狱应用则不需要解密),导出头文件;
  • 通过界面查看 APP 的布局,从布局中找到对应的头文件,查看关键函数;
  • hook 相关函数,达到你的目的;
  • 静态分析加动态调试分析关键函数;
  • 模拟或篡改原有 APP 的逻辑;
  • 达到自己的目的。

**应用场景:**掌握逆向肯定非常有用,如果你想从事安全方面的工作,可以深究,否则不必投入太多的精力,毕竟正向开发中很少用到逆向知识。学习逆向知识可以总结为:

  • 借鉴第三方 APP 的实现思路,比如某个功能是如何实现的、界面使用了哪一类型的 View,数据库结构是什么样的等等;
  • 加深对正向开发的理解,比如 runtime;
  • 普及安全知识,了解逆向可以做什么后,在开发中你就会知道哪些信息会被别人获取到,比如某个 APP 根据本地的数据判断是否可以使用付费的资源,这明显使用逆向即可使用付费资源;

第二章 越狱设备

本章主要讲解越狱在逆向中的作用及越狱工具的使用。这里需要强调一点,逆向不一定需要越狱,而想要更好地掌握逆向的原理,一台越狱设备是必不可少的。目前市面上很多越狱工具,也提供了一键越狱,读者可自行搜索。

登录越狱设备:

手机越狱后,会安装一个 Cydia 的软件,它主要用来在越狱手机上安装各种工具,相当于越狱中的 “App Store” 。想要读取越狱设备中的资源文件,必须进行远程登录。搞服务器的同学都知道使用 SSH 进行远程登录,而登录越狱设备也可以使用 SSH 登录。通过 Cydia 搜索 OpenSSH 来安装即可,安装完后执行:

sudo ssh root@手机ip地址
复制代码

登录成功即可对越狱设备进行操作了。作者还介绍了其它登录越狱设备的方式,使用公钥匙登录,USB 登录。

文件目录:

如果想查看设备的文件系统,在 Mac 上可使用 iFunBox,手机端需要安装 Apple File Conduit 2 。安装成功后,即可通过 iFunBox 查看手机的目录结构,比如安装的 APP 沙盒目录,系统自代 APP 的沙盒目录,各种 Frameworks 等等。

越狱必备工具

  • adv-cmds: 执行 ps 命令报错,需要安装这个工具;
  • appsync: 让系统不再验证签名,以免安装应用失败;
  • iFile:在手机上查看文件目录;
  • scp:终端命令,把远程设备的文件复制到另一个设备;
  • Cydia Substrate:允许第三方开发者在越狱系统的方法中打一些补丁或扩展方法。

第三章 逆向工具详解

你可能仅仅停留在对这些工具(dumpdecrypted、Clutch、class-dump、Reveal、Cycript、Charles、Wireshark)的使用上,比如我。而作者却给我们讲解了原理,可见他的功力很深。

dumpdecrypted

AppStore 中的应用都是经过加密的,而逆向的前提需要把加密的内容解密出来。dumpdecrypted 这个工具就是专干这件事的。当然,如果你不想解密,可以直接从越狱市场上下载被解密的 APP。不过有时候越狱市场上没有你要的应用就不得不自行解密了。它的原理引用作者的原话:

dumpdecrypted 是一个开源的工具,它会注入可执行文件,动态地从内存中 dump 出解密后的内容。

Clutch

除了使用 dumpdecrypted 进行解密,Clutch 也可以做到。不过作者提到使用这个经常会出错,建议使用 dumpdecrypted。

class-dump

class-dump 的作用是从可执行文件中导出类、方法、属性信息的工具,这里需要强调一下可执行文件,被解密的 APP 应用中会有一个可执行文件(Mach-O)。可以从 xxx.app 中的 info.plist 文件找到 Executable file 它的值即是 xxx.app 的可执行文件。使用 MatchOView 可以查看 Mach-O 文件。

导出 We.app 的头文件:

class-dump -H ~/Desktop/reverse/ipa/We.app -o ~/Desktop/reverse/header/we
复制代码

Reveal

是用来查看APP界面的工具,查看第三方 APP 不一定非用越狱设备。

Cycript

Cycript 是一个允许开发者使用 Objective-C++ 和 JavaScript 组合语法查看及修改运行时 APP 的内存信息的工具。在逆向中主要用来验证某些猜测是否正确,查看界面信息等。比如查看当前显示的 VC,某个对象执行某个函数后的结果,动态修改某个 UI 的信息。

Charles、Wireshark

介绍了这两个抓包工具的使用。

第四章 开发储备

这一章主要介绍正向开发的一些知识,而这些知识对逆向开发很重要。

ipa 包

获取应用的 ipa 包,主要可以通过两种方式获取:

  • 从 iTunes 中获取,目前的 iTunes 中已不支持,需要下载低版本的 iTunes。 下载
  • 直接从越狱设备获取,其实直接从各种助手中无需越狱设备即可下载越狱应用,获取到 ipa 包;

应用包的构建过程:

  • compile:使用 Clang 编译源文件;
  • link:将编译生成的目标文件链接成一个可执行文件;
  • storyboard:编译项目中的 storyboard 文件;
  • plist:生成 plist 文件;
  • asset:将需要的资源文件复制到 App 目录下;
  • dsym:生成符号文件;
  • codesign:对 App 进行签名;
  • package:打包。

界面与事件传递

介绍了 iOS 中的 UI 、事件传递和事件响应。

类与方法

主要介绍了类的底层实现,OC 中的消息机制,runtime 的一些使用场景。

App签名

正向开发中,每个同学都会经历一次苹果的证书配置。而作者在这里主要讲解了 App 签名的原理,这样为逆向重签名做好铺垫。

第五章 分析与调试

前面四章主要为后四章做一个铺垫,从接下来的章节中正式开启了逆向。本章主要从静态分析和动态调试来介绍逆向。

静态分析,指在不允许 App 的前提下对程序分析的一种方法。一般有以下几种方式:

  • 基于 ipa 和 app 包;
  • 基于文件格式;
  • 基于二进制反汇编;

反汇编

反汇编主要有两个工具:HopperIDA。而这两个工具可以查看源代码实现的汇编代码,关键还可以查看伪代码。以前一直觉得 Hopper 不好用就没用,今天下载了一个用起来发现比 IDA 用着舒服。

Hopper 只支持 Mac 和 Linux,相对于 IDA 比较弱一些。而 IDA 支持 Windows 平台。

静态库分析

有时候想看某个静态库的实现,其实也可以使用 Hopper 查看他的汇编代码。

➜  5.1 静态分析 ls
Crashlytics UserLogin
➜  5.1 静态分析 lipo -info Crashlytics
Architectures in the fat file: Crashlytics are: armv7 armv7s i386 x86_64 arm64
➜  5.1 静态分析 lipo Crashlytics -thin arm64 -output Crashlytics_arm64
➜  5.1 静态分析 mkdir Objects
➜  5.1 静态分析 cd Objects
➜  Objects ar -x ../Crashlytics_arm64
➜  Objects grep "Upload" -rn ./
Binary file .//CLSReportsController.o matches
Binary file .//CLSCrashReportingController.o matches
Binary file .//CLSNetworkClient.o matches
➜  Objects otool -l Crashlytics.o|grep bitcode
  sectname __bitcode
➜  Objects ld -r -arch arm64 -syslibroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk -bitcode_bundle ./*.o -o ../output
复制代码

动态调试

动态调试是在程序运行的时候执行一系列操作,比如获取某个对象的值,执行上下文等。

LLDB 动态调试:正向开发中常会使用到 LLDB 来调试程序,而在逆向中它也发挥很大作用。

用 Xcode 调试第三方应用:使用 Xcode 在非越狱设备中调试第三方应用、进行符号的还原、查看带符号的堆栈调用。不过调试的时候需要一个第三方应用。

Theos

越狱开发中除了 Thoes 外还有一个叫 iOSOpenDev 的工具,功能和 Thoes 是一样的,不同点是iOSOpenDev 是整合到 Xcode 中使用的,而 MonkeyDev 和 iOSOpenDev 属于同一类型的工具。

MonkeyDev

MonkeyDev 是作者开发的一个工具,主要用 Xcode 进行越狱开发。具体使用可以查看 MonkeyDev 的 wiki 。

第六章 逆向进阶

这一章,看着比较吃力。很多都没接触到,这里简单的做个介绍,如果以后用到这部分内容再继续深究。

程序加载

在程序执行 Main 函数之前,都做了哪些事。

Mach-O 文件格式

对于每个 ipa 包,都会包含一个可执行文件,而这个文件就是 Mach-O 文件。

ARM 汇编

逆向如果想看懂代码,那么必须学会汇编。

hook

hook 直译为 钩子,通过 hook 可以改变程序执行逻辑。hook 最常见的有以下三种方式:

  • MethodSwizzle:

通过 runtime 交换方法的实现。

  • fishhook:

fishhook 是 facebook 开源的一个库。

A library that enables dynamically rebinding symbols in Mach-O binaries running on iOS.

  • Cydia Substrate:

动态库

特点:

  • 存在形式有 .dylib,.framework 和链接符号 .tdb;
  • 它的格式和普通二进制文件没有区别;
  • 它的好处是可以只保留一份文件和内存空间,从而能够被多个进程使用,例如系统动态库;
  • 可减小可执行文件的体积,不需要链接到目标文件。

在逆向中会经常用到动态库,比如使用 Reveal 调试第三方应用时需要把 RevealServer. framework 注入到 APP 程序中。可以通过引入头文件的方式调用 和 dlopen 动态加载的方式调用动态库。

第七章 实战演练

这章主要应用前几章学到的知识。而逆向开发可以在越狱设备和非越狱设备中开发。

越狱设备

目标是给 WhatsApp 长按消息添加一个收藏菜单,并在设置中添加已收藏的消息。分别在越狱设备、非越狱设备进行分析。

  • 下载 WhatsApp 使用 dumpdecrypted 解密;
  • 使用 class-dump 导出头文件,导出头文件时加上 -A 参数可以显示方法在文件中的实现地址;
  • 符号还原,方便后续使用 lldb 进行调试;
  • 分析某个应用时,需要从界面入手,使用 Reveal 查看界面的层级结构,定位到具体的视图控制器,从头文件找到对应的方法;
  • 根据找到的方法,使用 lldb 添加断点,验证是否会调用对应的方法,以确定是否为需要找的方法;
  • 使用 Hopper 查看伪代码,猜测具体的实现方式;

非越狱设备

目标是给 WhatsApp 添加自动回复功能。越狱设备分析有诸多繁琐的工作,比如导出头文件,使用 Reveal,使用 LLDB 调试不方便等。所以作者把这些功能都集成到了 MonkeyDev 这个工具中,通过 MonkeyDev 新建工程将自动集成 class-dump、符号还原、Reveal、Cycript、注入动态库、自动重签名等一系列重复性的工作,可以直接在非越狱设备上进行逆向分析。具体使用参考

Frida 实战应用

Frida 是一款跨平台的注入工具,通过注入 JS 与 Native 的 JS 引擎进行交互,从而执行 Native 的代码进行 hook 和动态调用。这个工具可以用于 Android 和 iOS,它可以通过一段 JS 来调试应用。

第八章 安全保护

前面讲了这么多可以调试别人的 App 如同调试自己的一样,这就需要在开发的过程中来保护我们自己的 App 免受攻击,重要的数据需要进行加密处理。而本章主要讲有哪些手段可以保护我们的 App 尽可能的不被破解。主要采用的手段有:

- 数据加密:静态字符串、本地存储及网络传输加密

不管是本地的数据还是网络中传输的数据,对敏感数据需要采用加密算法进行加密处理,而常用的加密算法有 AES,RSA。对于网络传输的数据可以使用 AES+RSA 的方式对数据进行加密,如果使用 Https 的方式需要对证书进行校验。而对于一些常量字符串有时候也需要加密处理,以防止被静态分析。这里作者提使用 libclang 方式,具体 源码

- 静态混淆:类名、方法名、属性的混淆;

使用 class-dump 导出的头文件很容易根据名字知道某个类,方法的作用,这时候需要对类名,方法名进行混淆。第一种方法:通过宏定义混淆,在 pch 文件中比如这样写 #define MyClass 89s343ss。网上有一个开源的库 ios-class-guard。第二种方法:二进制修改,修改可执行文件的 __obj_classnameobjc_methname

- 动态保护:反调试、注入检测、hook 检测,越狱检测、签名检测等;

虽然静态混淆后不能猜到类名方法名的作用,但是如果采用动态的方式还是能知道某些方法的参数、以及加密后的数据等。这就是要防动态调试。

  • 反调试:主要通过阻止调试去附加和检测调试器是否存在。主要有 ptrace、sysctl、syscall、ARM 等方式;
  • 反反调试:过滤掉反调试机制;
  • 反注入:检测当前有没有其它模块注入;
  • hook 检测:检测是否被恶意的 hook 掉了;
  • 完整性校验:load command、代码校验、重签名校验;

- 代码混淆:提高分析难度

未混淆的代码可以通过 Hopper 和 IDA 等汇编工具得到汇编代码,甚至可以得到对应的伪代码。为了提高分析难度,需要对代码进行混淆。混淆主要通过 LLVM。

知识小集是一个团队公众号,主要定位在移动开发领域,分享移动开发技术,包括 iOS、Android、小程序、移动前端、React Native、weex 等。每周都会有 原创 文章分享,我们的文章都会在公众号首发。欢迎关注查看更多内容。

文章分类
iOS