关于 ipsw
ipsw 是面向 Apple 固件研究人员和开发者的命令行工具,涵盖固件、二进制文件、内核及连接设备的分析。它通过多个命令组支持远程检查、提取、符号化和版本比较等工作。
主要功能
- 01检查并下载 Apple 固件
- 02提取固件组件
- 03分析 dyld 缓存和 Mach-O 文件
- 04检查内核与沙盒配置
- 05比较版本并符号化崩溃日志
适用场景
- 01下载完整固件前检查发布版本
- 02追踪 dyld 共享缓存中的符号和引用
- 03比较不同固件版本的 API 与组件
- 04解析崩溃日志和内核 panic 中的地址
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ blacktop/ ipsw-skill --skill ipsw安装后在 Claude Code 中输入/ipsw确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
LICENSE.txtreferences/class-dump.mddevice.mddiffing.mddownload.mddyld.mdentitlements.mdfirmware.mdkernel.mdmacho.mdsandbox.mdsymbolication.md详细介绍
ipsw
ipsw 是一款用于 Apple 固件工作的命令行工具,按命令组组织(download、
extract、dyld、kernel、macho、fw、sb、ent、diff、symbolicate、idev 等)。
使用 brew install blacktop/tap/ipsw 安装(其他平台:github.com/blacktop/ipsw
releases)。远程和下载命令需要网络访问;idev 需要通过 USB 连接设备。本技能介绍的是
提交 6e0291a8f(发布 3.1.725 之后)中的 ipsw;对于 3.1.725 及更早版本,请参考下方的“旧版”表格。各版本的标志会有所变化:
ipsw version 可查看已安装的构建版本,ipsw <group> <command> --help 是权威信息来源。
--help 中标记为 🚧 的命令仍在开发中。
示例使用以下 Shell 变量(POSIX sh/bash/zsh 语法):
IPSW=./iPhone18,1_26.4_23E246_Restore.ipsw # local IPSW or OTA
URL=https://updates.cdn-apple.com/... # remote IPSW or OTA (see "Triage a release")
DSC=./dyld_shared_cache_arm64e # main file of an extracted cache; subcaches beside it
KC=./kernelcache.release.iPhone18,1 # extracted kernelcache
DEVICE=iPhone18,1 # any product type from `ipsw device-list`
操作规则
以下是 Agent 使用 ipsw 时最容易出错的地方。
- 在命令行中明确指定所有选项。 没有终端时,ipsw 无法提示你选择:
命令会报错并停止,例如“使用 --confirm 以便在无人值守时继续”(旧版会静默跳过此步骤;见下方的“旧版”)。请直接传入选项:
- 能匹配多个映像的短 dylib 名称(
UIKit、SwiftUI、SpringBoard)会导致失败。 请传入完整安装路径,可通过以下命令查找:ipsw dyld info --dylibs --json "$DSC" | jq -r '.dylibs[].name' | grep -i <name>。 - Fat Mach-O 文件需要
--arch arm64e;包含多个设备的 IPSW 需要--device <product-type>。 - 下载和 payload 搜索需要
-y/--confirm(download、ota extract --pattern)。 ipsw mount会一直运行,直到按下 Ctrl+C:请传入--detach,然后运行它打印的hdiutil detach …命令。idev crash pull需要路径或--all;除非指定-t <seconds>,否则idev syslog会一直输出。
- 能匹配多个映像的短 dylib 名称(
- 下载前先远程读取。 当前的 IPSW 文件有 10–15 GB,但
--remote命令只会获取所需内容:info --remote(KB)、extract --kernel --remote(约 75 MB)、fw <component> --remote(数 MB 到数十 MB)。远程执行extract --dyld会获取数 GB。 只有需要对整个文件系统进行操作时,才下载完整映像。 - 不要将大量输出放进对话中。 优先使用
--json | jq,通过-o/--output将内容写入文件,并先查看开头或计数。转储整个 DSC 或内核会产生数百万行。 - 预留一次性开销并做好规划:
- 首次对缓存运行
dyld disass/xref时,会构建<DSC>.a2s(耗时数分钟,约 1.5 GB)。 sb graph export需要约 30 秒并会写入约 500 MB,此后查询约需 3 秒。- 文件系统扫描(
ent --fs、macho search <IPSW>、diff)会将数 GB 的 DMG 解包并解密到当前目录。 - 首次运行
download appledb会将约 600 MB 的内容克隆到~/.config/ipsw/appledb;--no-update(download tss也支持)会复用现有检出内容。
- 首次对缓存运行
- 报告前先验证。 使用对应的反向命令交叉核对地址与符号的结果(
a2s对symaddr);确认崩溃日志的构建版本与固件匹配后,再相信符号化结果;列出解压输出(或使用extract --json),不要想当然地认定文件名。
选择工作流
| 任务 | 从这里开始 | 详情 |
|---|---|---|
| 查找、远程读取、下载或提取固件 | ipsw download appledb ... --urls、ipsw extract | references/download.md |
| 协处理器、exclave、iBoot、SEP、IMG4、AEA、OTA 内部结构 | ipsw fw <component>、ipsw img4、ipsw ota | references/firmware.md |
| dyld_shared_cache 中的用户空间代码 | ipsw dyld a2s / disass / xref | references/dyld.md |
| 私有框架的 ObjC/Swift 接口 | ipsw class-dump、ipsw swift-dump | references/class-dump.md |
| 独立二进制文件:信息、权利、签名 | ipsw macho info / disass / search | references/macho.md |
| 内核缓存:KEXT、符号、C++ 类、系统调用 | ipsw kernel ... | references/kernel.md |
| 沙盒配置文件和能力相关问题 | ipsw sb ... | references/sandbox.md |
| 在固件映像中搜索权利 | ipsw ent ... | references/entitlements.md |
| 两个版本之间的变更 | ipsw diff、--diff/--delta 变体 | references/diffing.md |
| 崩溃日志和内核崩溃 | ipsw symbolicate | references/symbolication.md |
| 通过 USB 连接的 iPhone/iPad | ipsw idev ... | references/device.md |
不下载即可排查版本
URL="$(ipsw download appledb --os iOS --device "$DEVICE" --latest --release --urls | head -1)"
ipsw info --remote "$URL" # version, build, devices, CPU
ipsw info --remote --list "$URL" # every file in the IPSW, with sizes
ipsw fw exclave --remote "$URL" --info # exclave bundle sections (~50 MB fetched)
KC="$(ipsw extract --kernel --remote --json -o ./fw/ "$URL" | jq -r 'keys[0]')" # just the kernelcache
ipsw dtree --remote "$URL" --summary # DeviceTree identity
dl 和 db 分别是 download 和 appledb 的别名。单独使用 --latest 表示任意通道中的最新版本(通常是 beta):添加 --release、--beta 或 --rc,或指定 --build <BUILD>
/ --version <X.Y>;--type ota 会返回 OTA URL。ipsw download ipsw --device "$DEVICE" --latest --urls 可获取最新的已签名公开 IPSW,不访问 AppleDB。
用户空间:从地址到解释
ipsw dyld a2s "$DSC" 0x18ebfa9c8 # symbol + offset
ipsw dyld disass "$DSC" --vaddr 0x18ebfa9a8 --count 60 # first run builds the .a2s cache
ipsw dyld xref "$DSC" 0x18ebfa9a8 --imports # callers in this and dependent dylibs
ipsw dyld imports "$DSC" /System/Library/PrivateFrameworks/SpringBoardServices.framework/SpringBoardServices
ipsw class-dump "$DSC" /System/Library/PrivateFrameworks/UIKitCore.framework/UIKitCore \
--class '^UIApplication$' --re -V | grep -B1 'BackgroundTask'
--re(需要 -V/--verbose)会在每个方法上方一行,以 // 0x… 注释的形式打印其实现地址,因此筛选时要保留一行前置上下文。这些地址可用于 dyld disass --vaddr。UIKit 的类位于
UIKitCore;UIKit.framework/UIKit 是一个不含 ObjC 的垫片。
内核:命名、查找、反汇编
ipsw kernel version "$KC"
mkdir -p ./syms && ipsw kernel symbolicate --signatures symbolicator/kernel --json -o ./syms/ "$KC" # names for a stripped kernel
ipsw kernel cpp "$KC" --class IOSurfaceRootUserClient --inheritance # C++ classes (no ObjC in kernels)
ipsw kernel syscall "$KC" # also: mach, mig, kexts
ipsw macho disass "$KC" --fileset-entry com.apple.kernel --vaddr 0xfffffe000ab90040 --count 40
签名来自 git clone https://github.com/blacktop/symbolicator;不使用
--signatures 时,symbolicate 仍会为系统调用、Mach 陷阱、MIG 例程和 C++ 方法命名。
发布版内核已剥离符号,因此请用 --vaddr 进行反汇编。按完整 bundle ID 为 KEXT 命名:短名称会按后缀匹配
(IOKit 会解析为 com.apple.driver.ASIOKit)。
两个版本之间的变更
ipsw dyld info --dylibs --delta "$OLD_DSC" "$NEW_DSC" # added/removed/re-versioned dylibs
ipsw class-dump "$NEW_DSC" <DYLIB_PATH> --diff "$OLD_DSC" # ObjC API diff (new first, --diff old)
ipsw swift-dump "$NEW_DSC" <DYLIB_PATH> --diff "$OLD_DSC" > api.diff.md # Swift API diff (long)
ipsw kernel kexts --diff "$OLD_KC" "$NEW_KC"
ipsw sb opts --diff "$OLD_KC" "$NEW_KC"
ipsw diff "$OLD_IPSW" "$NEW_IPSW" -o ./diff/ --markdown --starts --ent # full report (slow, local IPSWs)
补丁排查清单请参阅 references/diffing.md。
能力:权利和沙盒
ipsw ent --fs --has com.apple.private.security.no-sandbox --file-only "$IPSW" # no database needed
ipsw sb graph export "$KC" -O graph.json
ipsw sb query iokit-open IOSurfaceRootUserClient --graph graph.json -O json \
| jq -r '.matches[] | select(.decision=="allow") | .profile' | sort -u
崩溃和内核崩溃
ipsw symbolicate panic-full-<date>.ips "$IPSW" --peek # kernel + userspace frames, with disassembly
ipsw symbolicate crash.ips "$DSC" --unslide # userspace, addresses usable in static tools
固件必须与日志标头中的版本完全一致(head -1 <log>.ips | jq -r .os_version)。
如果本地没有固件,--server <URL> 会查询 ipswd 符号服务;通过
IPSW_SYMBOLICATE_API_TOKEN 传递 bearer token(参阅 references/symbolication.md)。
易踩的坑
dyld symaddr和dyld disass --symbol匹配的是精确名称,而不是正则表达式;要匹配模式,请使用symaddr --in <json>。disass的符号查找提示是--symbol-image(--image用于选择要反汇编的整个 dylib)。- ObjC 实例方法名称以
-开头,会被解析为标志:请将它们放在--后面 (ipsw dyld symaddr "$DSC" --image <DYLIB> -- '-[UIApplication endBackgroundTask:]')。 dyld str会搜索整个缓存,且无法按映像筛选。dyld xref --all会反汇编每个映像(非常慢);请先不加此选项运行。- 不带
--dyld-arch的extract --dyld会提取映像中的所有架构。 class-dump --re需要-V;地址会以// 0x…行的形式打印在每个方法上方。- 在
sb命令中,-o表示操作列表,-O表示输出。 download git和device-info接受--product/--prod,而非位置参数。
较早版本(ipsw 3.1.725 及更早版本)
检查 ipsw version。这些版本的行为有所不同;请使用右侧的解决方法:
| 3.1.725 及更早版本中的行为 | 解决方法 |
|---|---|
在没有终端的情况下,提示会跳过该步骤并以状态码 0 退出(download appledb/ota 的“Continue?”、ota extract 的 payload 搜索) | 始终传入 --confirm/-y;检查输出,而不是退出状态 |
download tss --signed 在未签名时以状态码 0 退出;没有 --no-update | 在输出中匹配 Is still being signed / No longer being signed |
不带选择器的 download kdk 不执行任何操作且以状态码 0 退出 | 传入 --host、--build、--latest 或 --all |
dyld a2f <DSC> <ADDR> 失败并提示 failed to find image containing stub target | echo <ADDR> | ipsw dyld a2f "$DSC" --in /dev/stdin |
dyld webkit --diff 会拒绝第二个参数 | 对每个缓存运行 ipsw dyld webkit --json "$DSC" | jq -r .version |
dyld info --dylibs --diff/--delta 没有 --json;即使使用 --no-color,--diff 和 kernel kexts --diff 仍会输出 ANSI 控制码 | 使用 --delta(Markdown),以及 references/kernel.md 中的 kexts --json 方法 |
class-dump --diff 会忽略 @property 变更 | 从两个缓存中转储该类,然后运行 diff -u |
如果 <dir> 不存在,kernel symbolicate -o <dir> 会失败 | 先运行 mkdir -p <dir> |
fw exclave/dcp/c1 --info 会将获取的固件留在 ./<BUILD>__<DEVICE>/ 下 | 在临时目录中运行 |
extract --remote --kbag 会下载每个完整的 IM4P(约 150 MB) | 预留相应空间,或仅提取需要的 IM4P |
extract 没有 --json-format artifacts | 使用普通的 --json:在 --kernel 后运行 jq -r 'keys[0]',在 --sptm/--pattern 后运行 .[] |
ota ls --payload --json 会在 JSON 前输出横幅 | 在 jq 前运行 sed -n '/^\[/,$p' |
dyld search objc 会针对一个映像输出 relative method selectors 错误 | 忽略该错误;其他结果有效 |
device-info 和 download git 会静默忽略位置参数 | 使用 --prod / --product |
参考文件
阅读与任务相匹配的文件;每个文件都以目录表开头。
references/download.md:查找 URL、远程读取、下载、提取、AEA 密钥、配置references/firmware.md:info、mount、dtree、fw组件、IMG4、AEA、OTA payloadreferences/dyld.md:DSC 地址、反汇编、交叉引用、导入项、软链接、提取references/class-dump.md:ObjC/Swift 转储、标头生成、API 差异references/macho.md:Mach-O 信息、权利、签名、搜索、lipo/sign/patchreferences/kernel.md:内核符号、C++ 类、系统调用/MIG、KEXT 提取、KDK 类型references/sandbox.md:配置文件反编译、功能查询、沙盒差异references/entitlements.md:权利搜索和数据库references/diffing.md:版本差异和补丁搜寻清单references/symbolication.md:崩溃和内核崩溃符号化references/device.md:用于通过 USB 连接设备的idev命令