MonkeyDev 解决什么问题
iOS 逆向有个天然矛盾:tweak 需要越狱环境,但目标 App 检测越狱;真机不越狱又没法注入代码。MonkeyDev 给出的方案是重打包注入——把 hook 代码编译成 dylib,塞进脱壳后的 IPA,修改 Mach-O 的加载命令让它启动时自动加载,重签名装回非越狱机。
等于把 App 和你的分析代码打包成一个"合体版"安装包,在非越狱设备上实现 tweak 的效果。
环境搭建与标准流程
# 安装(依赖 theos)
git clone https://github.com/AloneMonkey/MonkeyDev.git
# 按 wiki 配置 theos 路径
# Xcode 新建工程时选 MonkeyDev 模板:Logos Tweak / CaptainHook 等工程结构里两个关键目录:
TargetApp/:放脱壳后的 IPA(砸壳方法见 frida-ios-dump 篇)- 代码文件:写 Logos hook 代码
Build 一下,MonkeyDev 自动完成:解包 IPA → 注入 dylib → 插入 LC_LOAD_DYLIB → 重签名 → 安装到设备。
核心能力:Logos hook OC 方法
// Tweak.x
%hook SignManager
- (id)getSign:(id)arg1 {
NSLog(@"[MonkeyDev] getSign 入参: %@", arg1);
id result = %orig;
NSLog(@"[MonkeyDev] getSign 返回: %@", result);
return result;
}
%end
// 构造函数里做初始化
%ctor {
NSLog(@"[MonkeyDev] dylib 已注入");
}Xcode 真机运行,控制台直接看到 App 运行中签名方法的每次调用。在非越狱机上实现了 Frida 的核心能力。
精髓一:class-dump 头文件是 MonkeyDev 的弹药库
MonkeyDev 工程支持导入 class-dump 出的头文件,然后直接 hook 私有类:
// 导入砸壳时 class-dump 的头文件
#import "SignManager.h"
// 或者运行时按名字 hook(不知道头文件时)
%hook NSClassFromString(@"SignManager")配合头文件,App 的内部结构(私有类、私有方法)全部可 hook——这是 MonkeyDev 相对纯 Frida 的优势:编译期类型检查 + IDE 补全,写复杂 hook 逻辑效率高得多。
精髓二:重签名的坑
重签名是失败高发区:
- 证书描述文件要匹配:用开发者账号的 development 证书 + 包含目标设备的描述文件。企业证书可以装任意设备但有吊销风险
- bundle id 冲突:原 App 的 bundle id 被苹果签名绑定,重打包要改成自己证书能签的 id(MonkeyDev 默认处理)
- entitlements 丢失:推送、钥匙串共享等能力依赖 entitlements,重签名时丢了会导致对应功能异常——MonkeyDev 会保留大部分,但 App Group 类的要手动检查
- iOS 15+ 的签名加强:部分系统版本对重签名包的校验更严,装不上时换 AltStore/Sideloadly 侧载方案
精髓三:什么时候选 MonkeyDev 而不是 Frida
| 场景 | 选择 |
|---|---|
| 快速验证某个方法的行为 | Frida(即连即调) |
| 复杂 hook 逻辑、需要持久运行 | MonkeyDev(编译型,稳定) |
| 非越狱设备 | MonkeyDev(唯一解) |
| 需要修改 UI/加调试面板 | MonkeyDev(能加完整 ViewController) |
| 批量协议模拟 | 都不是,走 Frida RPC 或算法还原 |
MonkeyDev 的杀手锏是能给 App 加调试 UI——比如在 App 里插一个悬浮窗,实时显示签名结果、一键导出 cookie。长期分析一个 App 时,这种"内嵌调试器"的体验无与伦比。
总结
- MonkeyDev = 重打包注入,非越狱机实现 tweak 能力
- 输入是脱壳 IPA,输出是注入 dylib 的重签名包
- class-dump 头文件 + Logos = 带 IDE 支持的 hook 开发
- 重签名是主要坑点,entitlements 和 bundle id 要检查
交流微信:run1255