为什么 iOS 逆向第一步是砸壳
App Store 下载的 IPA 里,二进制被苹果的 FairPlay DRM 加密——直接拖进 IDA/Hopper 看到的代码段全是密文,无法静态分析。砸壳(decrypt)的本质:利用系统加载器解密后的内存镜像,把明文 dump 出来重打包。
前提:一台越狱设备(iOS 13-15 的 checkra1n/palera1n 时代设备最顺手)。
frida-ios-dump 标准流程
# 1. 设备上起 frida-server(iOS 版),USB 连接
# 2. 电脑上
pip install frida-ios-dump
cd frida-ios-dump
# 3. 端口转发(USB 映射 frida 端口)
iproxy 2222 22 # 或 usbfluxd
# 4. 列出设备上的 App
python3 dump.py -l
# 5. 砸壳(-H 指定本机,走 SSH 隧道)
python3 dump.py -H 127.0.0.1 -p 2222 com.target.app跑完得到脱壳后的 IPA。原理:Frida attach 到目标进程,等系统完成 FairPlay 解密(进程启动时内核自动解密代码段),然后从内存把明文的 __TEXT 段抠出来,写回二进制文件,同时修改 cryptid 标志为 0(告诉系统"这是未加密二进制")。
验证砸壳成功
# 解开 IPA 看主二进制
unzip -o dumped.ipa -d dumped/
cd dumped/Payload/Target.app
# 检查加密标志:cryptid 0 = 已脱壳
otool -l Target | grep -A 4 LC_ENCRYPTION_INFO
# 输出 cryptid 0 即成功
# 拖进 Hopper 能看到正常汇编,class-dump 能出头文件
class-dump -H Target -o headers/精髓一:framework 和扩展也要砸
主二进制砸完只是开始——现代 App 大量代码在动态库里:
Payload/Target.app/Frameworks/*.framework:Swift 库、三方 SDKPayload/Target.app/PlugIns/*.appex:分享扩展、小组件
frida-ios-dump 会尝试一起砸,但经常漏。检查方法:对每个 framework 二进制跑 otool -l | grep cryptid,非 0 的单独补砸。漏砸的 framework 在静态分析时是黑盒,关键逻辑(比如签名)很可能就藏在里面。
精髓二:砸壳时机的坑
FairPlay 解密发生在代码段被加载进内存时——懒加载的代码页在第一次访问时才解密。frida-ios-dump 通过遍历内存映射强制加载所有页来规避,但极端情况下(超大 App、内存压力导致页被换出)会砸出不完整的二进制。
对策:砸壳前在 App 里把主要功能页面都点一遍(让更多代码页驻留内存),再执行 dump。
精髓三:M 系列 Mac 的"免越狱"路线
没有越狱设备时的替代方案:M1/M2/M3 Mac 可以直接运行 iOS App(开发者允许的话),用 poormans 类工具或 bagbak`(需越狱)……实际上 M 系列上的主流方案是:
- 用 Apple Configurator 2 或第三方工具从 App Store 抓 IPA(加密状态)
- 在 M 系列 Mac 上运行该 IPA(需要绕过签名限制)
- 用 frida macOS 版 attach 进程,从内存 dump 解密后的二进制
这条路绕开越狱但限制多(App 开发者可以禁止 Mac 运行),能走越狱设备还是优先越狱设备。
砸壳之后干什么
拿到明文二进制 + class-dump 头文件,iOS 逆向才算真正开始:
- 头文件是地图:
SignManager.h、CryptoUtils.h这种类名直接指路 - Hopper 伪代码:OC 方法按 F5 看伪 C,比汇编友好十倍
- Frida hook OC 方法:
ObjC.classes.SignManager['- getSign:']直接拦截
总结
- FairPlay 加密的 IPA 必须砸壳才能静态分析,原理是 dump 解密后的内存镜像
- frida-ios-dump + 越狱设备是标准流程,cryptid=0 验证成功
- framework 和 appex 要逐个检查补砸
- 砸壳后 class-dump 头文件是分析地图
交流微信:run1255