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. 下载 http://secure-appldnld.apple.com/itunes12/091-33628-20170922-EF8F0FE4-9FEF-11E7-B113-91CF9A97A551/iTunes12.6.3.dmg ;
直接从越狱设备获取, 其实直接从各种助手中无需越狱设备即可下载越狱应用, 获取到 ipa 包;
应用包的构建过程:
compile: 使用 Clang 编译源文件;
link: 将编译生成的目标文件链接成一个可执行文件;
storyboard: 编译项目中的 storyboard 文件;
plist: 生成 plist 文件;
asset: 将需要的资源文件复制到 App 目录下;
dsym: 生成符号文件;
codesign: 对 App 进行签名;
package: 打包.
界面与事件传递
介绍了 iOS 中的 UI , 事件传递和事件响应.
类与方法
主要介绍了类的底层实现, OC 中的消息机制, runtime 的一些使用场景.
App 签名
正向开发中, 每个同学都会经历一次苹果的证书配置. 而作者在这里主要讲解了 App 签名的原理, 这样为逆向重签名做好铺垫.
第五章 分析与调试
前面四章主要为后四章做一个铺垫, 从接下来的章节中正式开启了逆向. 本章主要从静态分析和动态调试来介绍逆向.
静态分析, 指在不允许 App 的前提下对程序分析的一种方法. 一般有以下几种方式:
基于 ipa 和 app 包;
基于文件格式;
基于二进制反汇编;
反汇编
反汇编主要有两个工具: Hopper https://www.hopperapp.com/ 和 IDA https://www.hex-rays.com/products/ida/ . 而这两个工具可以查看源代码实现的汇编代码, 关键还可以查看伪代码. 以前一直觉得 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
https://github.com/AloneMonkey/MonkeyDev 是作者开发的一个工具, 主要用 Xcode 进行越狱开发. 具体使用可以查看 MonkeyDev 的 wiki .
第六章 逆向进阶
这一章, 看着比较吃力. 很多都没接触到, 这里简单的做个介绍, 如果以后用到这部分内容再继续深究.
程序加载
在程序执行 Main 函数之前, 都做了哪些事.
Mach-O 文件格式
对于每个 ipa 包, 都会包含一个可执行文件, 而这个文件就是 Mach-O 文件.
ARM 汇编
逆向如果想看懂代码, 那么必须学会汇编.
hook
hook 直译为 钩子, 通过 hook 可以改变程序执行逻辑. hook 最常见的有以下三种方式:
MethodSwizzle:
通过 runtime 交换方法的实现.
fishhook:
https://github.com/facebook/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, 注入动态库, 自动重签名等一系列重复性的工作, 可以直接在非越狱设备上进行逆向分析. 具体使用参考 https://github.com/AloneMonkey/MonkeyDev/wiki/开始使用
Frida 实战应用
Frida https://www.frida.re/ 是一款跨平台的注入工具, 通过注入 JS 与 Native 的 JS 引擎进行交互, 从而执行 Native 的代码进行 hook 和动态调用. 这个工具可以用于 Android 和 iOS, 它可以通过一段 JS 来调试应用.
第八章 安全保护
前面讲了这么多可以调试别人的 App 如同调试自己的一样, 这就需要在开发的过程中来保护我们自己的 App 免受攻击, 重要的数据需要进行加密处理. 而本章主要讲有哪些手段可以保护我们的 App 尽可能的不被破解. 主要采用的手段有:
- 数据加密: 静态字符串, 本地存储及网络传输加密
不管是本地的数据还是网络中传输的数据, 对敏感数据需要采用加密算法进行加密处理, 而常用的加密算法有 AES,RSA. 对于网络传输的数据可以使用 AES+RSA 的方式对数据进行加密, 如果使用 Https 的方式需要对证书进行校验. 而对于一些常量字符串有时候也需要加密处理, 以防止被静态分析. 这里作者提使用 libclang 方式, 具体 源码 https://github.com/AloneMonkey/iOSREBook/blob/master/chapter-8/8.1 数据加密/LibClangParse/LibClangParse/main.m .
- 静态混淆: 类名, 方法名, 属性的混淆;
使用 class-dump 导出的头文件很容易根据名字知道某个类, 方法的作用, 这时候需要对类名, 方法名进行混淆. 第一种方法: 通过宏定义混淆, 在 pch 文件中比如这样写
#define MyClass 89s343ss
. 网上有一个开源的库 https://github.com/Polidea/ios-class-guard . 第二种方法: 二进制修改, 修改可执行文件的 __obj_classname 和 objc_methname.
- 动态保护: 反调试, 注入检测, hook 检测, 越狱检测, 签名检测等;
虽然静态混淆后不能猜到类名方法名的作用, 但是如果采用动态的方式还是能知道某些方法的参数, 以及加密后的数据等. 这就是要防动态调试.
反调试: 主要通过阻止调试去附加和检测调试器是否存在. 主要有 ptrace,sysctl,syscall,ARM 等方式;
反反调试: 过滤掉反调试机制;
反注入: 检测当前有没有其它模块注入;
hook 检测: 检测是否被恶意的 hook 掉了;
完整性校验: load command, 代码校验, 重签名校验;
- 代码混淆: 提高分析难度
未混淆的代码可以通过 Hopper 和 IDA 等汇编工具得到汇编代码, 甚至可以得到对应的伪代码. 为了提高分析难度, 需要对代码进行混淆. 混淆主要通过 LLVM.
知识小集是一个团队公众号, 主要定位在移动开发领域, 分享移动开发技术, 包括 iOS,Android, 小程序, 移动前端, React Native,weex 等. 每周都会有 原创 文章分享, 我们的文章都会在公众号首发. 欢迎关注查看更多内容.
来源: https://juejin.im/post/5b31c6dee51d4558e3602270