
简介iOS渗透工具.zip 是一套面向移动应用安全测试人员与逆向工程学习者的工具集合聚焦于 iOS 应用的安全审计与渗透测试场景适合具备一定安全基础、希望系统接触 iOS 应用分析流程的从业者使用。压缩包共包含 8 个文件以 txt 说明文档、Python 脚本、classdumpz 与 clutch 可执行工具及一个跨平台 class-dump 压缩包为主整体约 1.32MB体积轻便便于携带与快速部署。其中 classdumpz 用于提取应用类与方法头文件Clutch 支持从越狱设备备份并提取 IPA两个重签名脚本可帮助测试者绕过部分运行环境限制README 与说明文本则提供安装配置指引。资源覆盖了从结构提取、应用备份到重签名的多个渗透测试环节读者可借此搭建起一套相对完整的 iOS 安全分析工具链理解各组件在真实审计流程中的定位与配合方式。目前已有 75 人学习关注适合作为入门与实操参考。1. iOS渗透工具.zip 里到底装了什么从砸壳到重签的完整链路你拿到一个叫「iOS渗透工具.zip」的压缩包解压后大概率是一堆命令行工具、脚本和几个 dylib而不是一个双击就能跑的 App。这类工具包解决的核心问题只有一个在非越狱或半越狱的 iPhone 上把别人写好的 App 拆开看、改掉、再装回去。典型场景是安全评估、竞品分析、私有 API 摸底或者单纯想搞清楚某个 App 到底往服务器发了什么。它适合两类人一是做移动端安全测试的工程师需要拿到脱壳后的 Mach-O 做静态分析二是做逆向和二次开发的从业者需要改 Bundle ID、换签名、注入自己的动态库。不适合只想「装个破解版」的人因为整条链路涉及证书、签名、脱壳、重签四个环节任何一环断了都装不上。热搜里常出现的 resignIPA、Clutch、classdumpz 正好对应这条链路的三个关键节点脱壳、重签、头文件导出。下面按真实操作顺序拆开讲。2. 环境准备与工具链选型为什么 Clutch 和 classdumpz 是绕不开的2.1 越狱环境与非越狱环境的取舍先决定你在哪种设备上干活。越狱设备Checkra1n、Palera1n、Dopamine 这类工具覆盖的版本能直接跑 Clutch、frida-ios-dump 做内存脱壳权限最高但设备版本受限iOS 16 以上越狱方案不稳定。非越狱设备只能走「重签 注入」路线用 Sideloadly、AltStore 或自签证书把改过的 IPA 装回去缺点是免费证书 7 天过期这就是热搜里「ios 自签 7 天」的由来。我的建议是静态分析为主就选越狱设备一次脱壳拿到干净 Mach-O后面随便折腾动态调试和注入为主就选非越狱 自签虽然麻烦但设备新、系统干净。两者不是互斥的很多团队是一台越狱机专门脱壳一台新机专门跑重签后的包。2.2 工具链清单与各自职责一个完整的工具包通常包含这几类东西缺哪个补哪个工具职责典型命令入口Clutch / frida-ios-dump内存脱壳还原加密的 Mach-OClutch -i/dump.pyclass-dump / classdumpz导出 Objective-C 头文件class-dump -Hldid / codesign重签名ldid -S/codesign -finsert_dylib / optool注入 dylib 并修改 Load Commandsinsert_dylibipa 打包脚本重压 Payload 成 IPAzip -rclassdumpz 是 class-dump 的一个封装版本对 Swift 混编和 arm64e 的支持更好导出头文件时不容易崩。选它而不是原版 class-dump主要原因是原版对高版本 iOS 的 Swift 符号解析经常报错。2.3 最小可复现的环境搭建在越狱设备上装好 Clutch 后先确认它能识别已安装的 App# SSH 登录越狱设备默认密码 alpine ssh rootdevice-ip # 列出可脱壳的 App-i 表示交互式选择 Clutch -i # 假设目标 App 编号是 3执行脱壳 Clutch -d 3脱壳产物默认落在/var/mobile/Documents/Dumped/下是一个解密后的 Mach-O 文件。逻辑说明Clutch 通过task_for_pid拿到目标进程内存把__TEXT段的加密部分 dump 出来再重组所以它必须在 App 运行状态下执行。参数-d后面跟的是 App 在列表里的序号不是 Bundle ID这点新手经常搞错。提示脱壳前先把目标 App 启动一次再切到后台保证进程还在否则 Clutch 会报Could not find pid。3. 脱壳与头文件导出把 Mach-O 和类结构拿到手3.1 Clutch 脱壳失败的三类原因Clutch 报错基本集中在三种情况。第一种是Failed to dump多半是 App 有反调试ptrace被 hook 了解决办法是先挂 frida 把反调试 patch 掉再脱。第二种是 dump 出来的文件大小和原始__TEXT对不上说明有部分页没读全换 frida-ios-dump 重试。第三种是 App 用了 FairPlay 之外的加密方案Clutch 直接不认这种只能上 frida 手动 dump 内存段。frida-ios-dump 的用法更直接在电脑上跑# 安装依赖 pip install frida-tools # dump.py 指定目标 App 的显示名或 Bundle ID python dump.py -o ./output TargetApp # 产物是一个解密后的 IPA直接可解压 unzip -o ./output/TargetApp.ipa -d ./decrypted逻辑说明dump.py 通过 frida 注入目标进程遍历内存中的 Mach-O 加载信息把每个加密段读出来写回文件。参数-o指定输出目录后面跟的字符串是 App 在设备上的显示名不是 Bundle ID写错了会提示找不到进程。3.2 classdumpz 导出头文件的正确姿势拿到解密后的 Mach-O 后导出头文件# 从解密 IPA 里取出可执行文件 cp ./decrypted/Payload/TargetApp.app/TargetApp ./TargetApp_bin # 用 classdumpz 导出所有头文件到 headers 目录 classdumpz -H ./headers -o ./TargetApp_bin # 只看某个类比如网络请求相关 classdumpz -H ./headers -k Network ./TargetApp_bin逻辑说明-H指定头文件输出目录-o后面是 Mach-O 路径-k是关键字过滤只导出类名含该关键字的头文件。导出后你会得到一堆.h里面能看到方法签名、属性、协议这对定位私有 API 和加密逻辑非常关键。注意classdumpz 对 Swift 类的导出不完整Swift 的符号被 mangle 过需要配合swift-demangle或 Hopper 反汇编看。别指望头文件里能看到全部逻辑。3.3 从 Mach-O 里提取字符串和 URL头文件之外字符串表是另一个金矿# 提取所有可打印字符串 strings -a ./TargetApp_bin strings.txt # 过滤出 URL 和域名 grep -Eo https?://[^] strings.txt | sort -u # 找硬编码的 key 或 token grep -iE api[_-]?key|secret|token strings.txt逻辑说明strings -a扫描整个文件的 ASCII 段-a表示不跳过任何 section。这一步能快速摸清 App 的后端接口和第三方 SDK配合 Charles 抓包热搜里的 charles 抓包 ios可以交叉验证。4. 重签名与注入让改过的包能装回手机4.1 重签名的完整命令链改完 Bundle ID 或注入 dylib 后必须重签才能安装。核心命令# 1. 解压原始 IPA unzip -o TargetApp.ipa -d ./work # 2. 删除旧签名 rm -rf ./work/Payload/TargetApp.app/_CodeSignature # 3. 替换 embedded.mobileprovision 为你自己的描述文件 cp ./my.mobileprovision ./work/Payload/TargetApp.app/embedded.mobileprovision # 4. 用 ldid 重签越狱设备常用 ldid -S ./work/Payload/TargetApp.app/TargetApp # 5. 重新打包 cd ./work zip -qr ../TargetApp_resigned.ipa Payload逻辑说明_CodeSignature目录存的是原签名必须删掉否则新签名不生效。embedded.mobileprovision是你的开发者证书对应的描述文件Bundle ID 必须和描述文件里的 App ID 匹配。ldid -S是给 Mach-O 打上伪签名越狱设备能直接跑非越狱设备要用codesign配合真实证书。4.2 用 codesign 做非越狱可用的签名非越狱设备必须用 Apple 认可的证书# 查看可用签名身份 security find-identity -v -p codesigning # 对 App 内所有 framework 和 dylib 先签 codesign -f -s iPhone Developer: Your Name (XXXXXXXXXX) ./work/Payload/TargetApp.app/Frameworks/* # 最后签主二进制 codesign -f -s iPhone Developer: Your Name (XXXXXXXXXX) --entitlements ./ent.plist ./work/Payload/TargetApp.app/TargetApp # 验证签名 codesign -vv ./work/Payload/TargetApp.app/TargetApp逻辑说明签名顺序必须从内到外先签所有动态库再签主二进制否则主二进制的签名会因为依赖库签名变化而失效。--entitlements指定权限文件注入调试类 dylib 时需要get-task-allow为 true。codesign -vv做验证输出valid on disk才算成功。4.3 注入 dylib 并修改 Load Commands想让 App 启动时加载你的库# 用 insert_dylib 把 dylib 路径写进 Mach-O 的 Load Commands insert_dylib --strip-codesig --inplace executable_path/MyHook.dylib ./work/Payload/TargetApp.app/TargetApp # 确认注入成功 otool -L ./work/Payload/TargetApp.app/TargetApp | grep MyHook逻辑说明--strip-codesig会先去掉旧签名--inplace直接改原文件。executable_path是相对路径指向 App 主二进制所在目录把 MyHook.dylib 放到同目录即可。otool -L列出所有依赖库能看到 MyHook 就说明注入成功。提示注入后必须重新签名顺序是「注入 → 签名」反过来会被签名校验拦住。5. 避坑与排查那些让你白干一晚上的问题5.1 脱壳后 App 闪退现象Clutch dump 出来的 Mach-O 替换回 IPA 后安装能成功但一启动就闪退。原因dump 时只拿到了__TEXT段__DATA段里的某些指针还是加密状态或者 dump 过程中 App 被系统挂起导致内存不完整。解决脱壳前关闭其他后台 App保证目标 App 在前台运行至少 10 秒再切后台用 frida-ios-dump 替代 Clutch 重试它的内存读取更稳。5.2 重签名后提示「无法安装」现象IPA 重签完用 Sideloadly 或 Xcode 安装时报Unable to install。原因Bundle ID 和描述文件不匹配或者 embedded.mobileprovision 里的设备 UDID 不包含当前手机。解决用security cms -D -i embedded.mobileprovision解出描述文件内容检查application-identifier和ProvisionedDevices是否对得上。免费证书只有 7 天有效期过期后必须重签。5.3 classdumpz 导出头文件为空现象命令跑完没报错但 headers 目录是空的。原因Mach-O 是 FAT 格式包含 arm64 和 arm64e 两个架构classdumpz 默认只读第一个架构而目标类可能在另一个架构里。解决先用lipo -info看架构再用lipo -thin arm64拆出单个架构对拆出来的文件跑 classdumpz。5.4 注入 dylib 后 App 启动卡死现象注入成功、签名也过了但 App 启动画面卡住然后闪退。原因dylib 的构造函数load或__attribute__((constructor))里做了耗时操作或调用了不存在的符号。解决把 dylib 里的初始化逻辑改成懒加载用dispatch_after延迟执行或者先用一个空 dylib 测试注入链路是否通再逐步加逻辑。5.5 抓包时 App 不走代理现象Charles 配好了其他 App 能抓目标 App 没流量。原因App 用了证书绑定SSL Pinning或者直接走 UDP/QUIC 绕过了 HTTP 代理。解决用 frida 脚本 hookSSL_CTX_set_verify或SecTrustEvaluate绕过 Pinning或者用tcpdump在设备上直接抓包再导出来分析。6. 进阶用 frida 做动态 Hook 和自动化验证静态分析拿到头文件后真正验证逻辑还得靠动态 Hook。frida 是这条链路上最灵活的工具能在不重签的情况下直接改运行时行为。下面是一个 Hook 网络请求的最小脚本// hook_network.js if (ObjC.available) { // Hook NSURLSession 的 dataTaskWithRequest var NSURLSession ObjC.classes.NSURLSession; var method NSURLSession[- dataTaskWithRequest:completionHandler:]; Interceptor.attach(method.implementation, { onEnter: function (args) { // args[2] 是 request 对象 var request new ObjC.Object(args[2]); var url request.URL().absoluteString().toString(); console.log([Request] url); // 打印请求头 var headers request.allHTTPHeaderFields(); console.log([Headers] headers); }, onLeave: function (retval) { console.log([Task created]); } }); } else { console.log(Objective-C runtime not available); }逻辑说明ObjC.classes.NSURLSession拿到类对象method.implementation是方法实现的地址Interceptor.attach在这个地址上下钩子。onEnter在方法执行前触发args[2]是第二个参数第一个是 self第二个是 selector第三个才是 request。new ObjC.Object(args[2])把裸指针包装成可调用的 OC 对象。跑起来用# 列出设备上的进程 frida-ps -U # 附加到目标进程并加载脚本 frida -U -f com.target.app -l hook_network.js --no-pause参数-U表示 USB 设备-f是启动并附加-l加载脚本--no-pause让 App 直接运行不暂停。跑起来后控制台会实时打印所有网络请求的 URL 和头信息比抓包更直接因为它在 SSL 加密之前就拿到了明文。验证 Hook 是否生效有个笨办法但很管用先 Hook 一个你确定会调用的方法比如UIApplication的openURL:看到日志输出再换目标方法。我一般会准备一个「探针脚本」只 Hook[NSObject alloc]如果这个都不触发说明 frida 没注入成功先排查 frida-server 版本和 App 的反调试。这套流程跑通一次之后后面就是重复劳动脱壳、导头文件、定位关键类、Hook 验证、改逻辑、重签、安装。真正花时间的不是命令本身而是定位「改哪里」——头文件里几百个类哪个才是你要的靠的是字符串搜索、调用栈回溯和一点直觉。我的习惯是先把所有网络相关的类和方法列出来按调用频率排序从最频繁的那个开始 Hook命中率最高。希望帮到你。本文还有配套的精品资源点击获取