技术文档
iOS 应用加固推荐方案
面向 IPA/Mach-O 的源码级与构建产物加固组合:符号与字符串处理、反调试、越狱检测、完整性校验与分发约束。
最后更新于 2025-06-06预计阅读 6 分钟
1. 现实约束
iOS 与 Android 的加固前提不同,先理解约束再选方案:
- 分发签名:IPA 必须签名(开发、Ad Hoc、企业、App Store),任何字节修改都会导致签名失效,必须重新签名。
- App Store 加密:从 App Store 下载的二进制由 Apple 使用 FairPlay 加密,越狱设备可解密后分析。
- 审核限制:动态下发可执行代码、热更新和隐藏功能受审核规则限制,加固不能改变审核可见的功能。
- 语言差异:Swift 与 Objective-C 的元数据、符号和运行时机制不同,保护手段也不同。
- 系统封闭:无法像 Android 一样自由注入或修改系统;越狱设备才是主要动态分析环境。
因此 iOS 加固通常是 源码级改造 + 构建配置 + 关键逻辑 native 化 + 运行时检测 的组合,而不是单一的“加壳”。
2. 保护面
| 层 | 风险 | 推荐手段 |
|---|---|---|
| 符号与元数据 | 类名、方法名、Swift mangling 暴露业务结构 | Strip、重命名、避免语义化命名 |
| 字符串 | 接口地址、密钥、提示语被 strings 提取 | 字符串加密、分段拼接、运行时解密 |
| 关键逻辑 | 授权、支付、协议签名被定位 | 下沉到 C/C++ 或独立静态库 |
| 资源 | 配置、模型、素材被提取 | 资源加密、完整性校验 |
| 运行时 | 调试器附加、Frida / Cycript 注入 | ptrace / sysctl 反调试、注入检测 |
| 设备环境 | 越狱、模拟器、重签名 | 越狱检测、签名与 Team ID 校验 |
| 完整性 | Mach-O、资源、配置被替换 | 代码段哈希、资源哈希、服务端校验 |
3. 推荐方案
3.1 基础档:通用 App
| 措施 | 说明 |
|---|---|
| Release 构建开启 Strip | 移除调试符号,减少信息暴露 |
| 字符串处理 | 敏感字符串不硬编码,使用运行时拼接或加密 |
| 关键逻辑 native 化 | 授权、签名、核心算法放入 C/C++ |
| 基础反调试 | PT_DENY_ATTACH 或 sysctl 检测 |
| 服务端校验 | 授权、支付、风控以服务端为准 |
3.2 标准档:商业 App
在基础档之上增加:
| 措施 | 说明 |
|---|---|
| 符号重命名 | 对 Swift / ObjC 业务类做构建期重命名 |
| 越狱检测 | 常见越狱路径、fork、cydia://、可写系统目录 |
| 注入检测 | 扫描异常动态库、DYLD_INSERT_LIBRARIES |
| 完整性校验 | 校验 Mach-O 代码段与关键资源哈希 |
| 反截屏 / 反录屏 | 敏感页面使用安全图层 |
3.3 强化档:金融 / 高价值
在标准档之上增加:
| 措施 | 说明 |
|---|---|
| 多态字符串 | 每个版本生成不同的解密常量 |
| 控制流混淆 | 关键 C/C++ 函数做控制流扁平化 |
| 反 Hook | 检测常见 Hook 框架与函数序言修改 |
| 设备风控 | DeviceCheck / App Attest + 服务端评分 |
| 灰度与降级 | 检测命中时按风险等级降级,而非直接崩溃 |
4. 关键实现
4.1 构建配置
在 Xcode 中确认:
Deployment Postprocessing = YES
Strip Installed Product = YES
Strip Style = All Symbols
Enable Bitcode = NO(按当前工具链要求)
- Release 包不要携带
.dSYM到分发渠道,单独归档用于崩溃符号化。 - 关闭不必要的调试日志与断言。
- 使用
-fvisibility=hidden隐藏 C/C++ 符号,只导出必要接口。
4.2 反调试
#import <sys/sysctl.h>
#import <sys/ptrace.h>
static int isBeingDebugged(void) {
int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid()};
struct kinfo_proc info;
size_t size = sizeof(info);
memset(&info, 0, sizeof(info));
if (sysctl(mib, 4, &info, &size, NULL, 0) != 0) return 0;
return (info.kp_proc.p_flag & P_TRACED) != 0;
}
static void disableDebugger(void) {
ptrace(PT_DENY_ATTACH, 0, 0, 0);
}
注意:
PT_DENY_ATTACH会让调试器附加失败,也可能影响合法的客服排障。- 反调试逻辑本身容易被 patch,建议多点校验并配合服务端风控。
4.3 越狱检测
常见信号:
- 越狱工具与应用路径:
/Applications/Cydia.app、/bin/bash、/usr/sbin/sshd - 可写系统目录:
/private/var/lib/apt、/etc/apt - 异常 URL Scheme:
cydia:// fork()成功(非越狱环境通常失败)- 动态库列表中出现注入框架
4.4 字符串与符号
- 不要在代码中直接写接口密钥、加密盐和完整 URL。
- 使用构建脚本生成每版本不同的字符串表,运行时解密。
- Swift 类型名会进入 mangled name,业务命名避免
PaymentValidator这类语义化名称。 - Objective-C 类名和方法名可以通过构建期脚本重命名,但要处理
NSClassFromString、KVC、Storyboard 和序列化引用。
4.5 完整性校验
- 校验 Mach-O
__TEXT段哈希,或校验签名信息中的 Team ID / Bundle ID。 - 校验关键资源与配置文件哈希。
- 校验逻辑放在 native 层,并由服务端下发挑战值,避免固定哈希被替换。
4.6 与服务端配合
- 登录、授权、支付、优惠券等关键判断由服务端完成。
- 客户端上报环境风险信号(越狱、调试、注入、重签名),服务端按风险等级处理。
- 使用 App Attest / DeviceCheck 提升设备可信度(按业务需要)。
5. 与 Sugo 的结合
iOS 产物是 Mach-O。当前建议:
- 对 IPA 中的 Mach-O 与关键
.dylib/ 静态库做保护能力评估。 - 关键逻辑尽量下沉到 C/C++ 或独立静态库,再按 Native 方案评估符号移除、混淆与虚拟化。
- Swift / ObjC 层以源码级混淆、字符串加密和运行时检测为主。
- IPA 重签名、资源校验和服务端风控按发布流程补齐。
6. 签名与分发
| 渠道 | 签名 | 注意事项 |
|---|---|---|
| App Store | Apple 分发签名 | 上传前验证 Archive,避免保护后签名失效 |
| TestFlight | App Store 签名 | 与正式包一致,注意审核 |
| Ad Hoc | 设备 UDID + 描述文件 | 设备数量有限,适合内测 |
| 企业分发 | 企业证书 + 描述文件 | 证书风控严格,禁止公开分发 |
| 越狱 / 自签 | 自签工具 | 仅用于安全研究,不用于正式发布 |
流程建议:
Archive → 保护 / 混淆 → 重签名 → 导出 IPA → 真机回归 → 上传 / 分发
- 任何对 Mach-O 的修改都要在签名前完成。
- 保留原始
.xcarchive和.dSYM。 - 记录每次发布的证书、描述文件与保护配置。
7. 测试矩阵
| 维度 | 覆盖建议 |
|---|---|
| 系统版本 | 最低支持版本、当前主流版本、最新 beta |
| 设备 | 小屏、刘海屏、灵动岛、iPad |
| 架构 | arm64、arm64e(按设备) |
| 场景 | 冷启动、登录、支付、推送、分享、后台恢复 |
| 环境 | 未越狱真机、越狱真机、模拟器、重签名包 |
| 网络 | Wi-Fi、蜂窝、弱网、代理 |
| 分发 | TestFlight、Ad Hoc、企业包、App Store 包 |
8. 常见问题
8.1 加固后无法安装
- 签名失效:确认所有修改都在重签名之前完成。
- 描述文件不包含设备 UDID(Ad Hoc)。
- Bundle ID、Entitlements 与证书不匹配。
- IPA 结构不完整,
Payload/*.app缺失或权限异常。
8.2 加固后启动崩溃
- 检查是否修改了
__TEXT段导致签名校验失败。 - 检查反调试逻辑是否在启动早期误判。
- 检查注入检测是否把系统库当成异常库。
- 用原始 Archive 对比崩溃栈。
8.3 越狱检测误报
- 部分企业设备、开发设备、无障碍环境会命中。
- 提供风险分级与降级策略,不要直接闪退。
- 收集误报设备的系统版本、机型与越狱工具信息。
8.4 App Store 审核被拒
- 检查是否包含动态代码下发、热更新或隐藏功能。
- 检查隐私描述是否覆盖设备信息收集。
- 加固不能改变审核可见的功能或规避审核。
8.5 Swift 符号仍然暴露
- Swift 元数据与 mangled name 无法完全消除。
- 通过命名规范、关键逻辑 native 化、字符串加密降低信息价值。
- 不要依赖“改类名”作为唯一保护手段。
9. 相关文档
这份文档有帮助吗?欢迎反馈文档问题或补充场景。提交文档反馈