fairplay-decrypt:离线解密 FairPlay IPA
一款公开工具从已越狱的 iPhone 提取可复用的 16 字节 FairPlay 账户凭据,然后离线解密该账户拥有的匹配 IPA。
TL;DR
fairplay-decrypt是一款 GPLv3 工具,无需启动应用即可解密 App Store 的 FairPlay 加密 IPA。它使用 IPA 所属 Apple 账户的 16 字节凭据。- 提取工具需要 iOS 10 或更高版本的已越狱 iPhone、root SSH,以及该账户安装的一款应用。随后可在 macOS 或 Linux 上用 Python 3.9 或更高版本离线解密。
- 弱点是一条可复用的账户凭据,它能解包每款匹配应用的密钥记录。一次提取即可解密该账户拥有的匹配 IPA。该工具没有分配 CVE,CISA KEV 目录 2026.11.10 也没有 FairPlay 条目。
- 当账户凭据可能被提取时,请把 IPA 视为公开信息。把机密留在服务器端,检测重新打包的构建版本,并且只从 App Store 安装应用。参见“如何修复?”。
我受影响吗?
如果您的应用以 FairPlay 加密的 arm64 IPA 分发,并且攻击者能获得拥有该应用的 Apple 账户的凭据,您就受影响。以下条件必须全部满足:
- 您的 App Store 构建版本使用 FairPlay 加密。该工具只处理带
LC_ENCRYPTION_INFO_64且cryptid非零的 arm64 Mach-O 切片。 - 攻击者持有拥有该应用的 Apple 账户的匹配类型的 16 字节凭据,或从与该账户关联的 Mac 注册中恢复的可复用模型。
- 攻击者拥有该 IPA。他们可以用该账户购买、从合作伙伴处收到或窃取。
- 他们可以在 macOS 或 Linux 上运行该工具。解密不需要访问 Apple 或您服务器的网络。
这不是应用中的远程漏洞。它是 IPA 外层 FairPlay 保护的一种属性,提取步骤需要一台被入侵的设备或一台已注册的 Mac。一个账户的凭据不能解密另一个账户拥有的应用。该工具不处理 FairPlay Streaming 视频、32 位二进制或未加密的 IPA。
普通凭据覆盖普通 App Store 应用。提取工具的 README 说 Apple Arcade 应用需要单独的 Arcade 凭据,因此一次提取不能同时覆盖两种类型。
| 提取途径 | 攻击者需要什么 | 能得到什么 |
|---|---|---|
已越狱 iPhone (fairplay-decrypt) |
iOS 10 或更高版本、root SSH、从目标账户安装的一款应用,以及一台装有 Xcode 和 ldid 的 Mac 来构建提取工具 |
16 字节账户凭据;离线解密该账户拥有的匹配 IPA |
已注册 Mac (UnfairPlay) |
一台登录 Mac App Store 的 Mac、一款已安装并打开过的 iPhone 应用,以及匹配的 IPA | 可复用的注册模型;解密同一注册的其他 IPA |
| 泄露的凭据 | 来自任一途径的 16 字节凭据,以及该账户拥有的 IPA | 无需设备的离线解密 |
检查 IPA 是否加密。在 macOS 上,提取主二进制并读取其加密加载命令:
unzip -p App.ipa Payload/App.app/App > /tmp/App
otool -l /tmp/App | grep -A4 LC_ENCRYPTION_INFO_64
codesign -dv --verbose=4 /tmp/App
cryptid 为 1 表示页面已加密。值为 0 表示二进制已经是明文。把 Payload/App.app/App 替换为 IPA 中的可执行文件路径。codesign 命令会打印签名的 TeamIdentifier,您可将其与自己的值比较。
如何修复?
该仓库不发布修复版本,因为它是解密工具,不是带补丁版本的产品。以下步骤可降低暴露面,并限制解密副本泄露的内容:
- 把解密后的 IPA 视为公开信息。移除必须保密的 API 密钥、签名机密和专有算法。页面一旦变成明文,客户端机密就可被读取。
- 把敏感决策移到服务器端。在服务器端用短期令牌授权操作,不要信任随二进制分发的值。
- 加入重新打包检测和服务器端验证。Apple 的 App Attest 和 DeviceCheck 可以标记被修改的客户端,但不能阻止解密。
- 对用户而言,只从 App Store 或 TestFlight 安装应用。对受管设备群,阻止从受管目录之外安装。
- 如果您认为账户凭据已被提取,请停止用该账户分发,并把来自该账户的每个 IPA 视为已暴露。检查其购买记录。
这些步骤不能阻止解密该账户拥有的 IPA。它们限制解密副本泄露的内容以及可能被滥用的方式。
根本原因是什么?
FairPlay 用从 SC_Info 中两个文件派生的密钥加密每个 4 KB 页面,而密钥链从一个 16 字节账户凭据开始。加密算法是 AES-128。弱点在于根密钥的保存位置,而不在于密码被攻破。
三个关键文件
<Name>.sinf是一棵 atom 树,包含账户name、16 字节iviv和 440 或 448 字节的priv记录。<Name>.supf或<Name>.v5.supf为每个加密页面保存一条 32 字节记录:一个 16 字节封装密钥和一个 16 字节 AES-CBC IV。- arm64 Mach-O 头中的
LC_ENCRYPTION_INFO_64带有cryptoff、cryptsize和cryptid,用于定位加密页面。
derive_work16() 把账户凭据和 priv 记录转换成 16 字节的每应用工作密钥。在代码片段中,name、iviv、credential 和 raw_priv 是解析器读取的 SINF 字段和 16 字节凭据。密钥是凭据与字节 0x30 异或的结果,而不是凭据本身。IV 是账户名与 iviv 的 MD5:
iv = hashlib.md5(name + iviv).digest()
op = Cipher(algorithms.AES(_xor(credential, b"0" * 16)), modes.CBC(iv)).decryptor()
clear = op.update(raw_priv) + op.finalize()
if clear[:4] != b"itun" or clear[20:24] != b"key " or clear[44:48] != b"iviv":
raise ValueError("credential does not decode this SINF priv record")
return clear[24:40]
derive_page_key() 接收 16 字节封装记录、页面索引和工作密钥。它用工作密钥对三个 16 字节源块做 AES-128-ECB 加密,然后通过名为 finish() 的自定义变换混合:
a, b, c = (
struct.unpack(">8H", block_transform(s, work))
for s in source_blocks(wrapped, absolute_index)
)
return struct.pack(">8H", *finish(_xor_int(finish(_xor_int(finish(a), b)), c)))
finish() 执行四轮 16 位和四轮 32 位的加法、平方和异或。代码注释标明一个进位被保留,另一个被丢弃。该变换是 AES 之上的混淆,不是第二个秘密。16 字节结果是页面的 AES-CBC 密钥,SUPF 记录接下来的 16 字节是它的 IV。
每应用的密钥由账户机密加密,因此一条凭据能解包该账户拥有的每款匹配应用的 priv 记录。提取工具在设备上恢复该凭据。它在 fairplayd 的选择器函数上设置硬件断点,并通过已安装应用触发一次许可证操作。
提取工具捕获选择器输出和 keybag 状态。随后把该状态与设备 UDID 以及该工具的表结合,生成 16 字节文件。该设计假定设备操作系统会保密 fairplayd 的状态。已越狱且拥有 root 访问权限的设备不提供这种信任边界。这就是设计弱点:凭据覆盖整个账户、可复用,并且能在被入侵设备的用户空间恢复。
如何被利用?
控制已越狱 iPhone 和拥有目标应用的 Apple 账户的攻击者,提取一条凭据并离线解密匹配的 IPA。该公开工具遵循以下路径:
- 准备一台 iOS 10 或更高版本、带 root SSH 访问权限的已越狱 iPhone,并从目标账户安装至少一款 App Store 应用。
- 在装有 Xcode、
ldid、idevice_id和iproxy的 Mac 上构建提取工具,然后对设备运行credential-retrieval/retrieve.py。 - 提取工具在
fairplayd中设置断点,启动已安装应用以触发许可证操作,捕获选择器输出和 keybag 状态,并写入credential.bin。 - 从同一 Apple 账户获取目标 IPA。
- 用 IPA 和凭据运行
decrypt.py。它解析 Mach-O 加密命令、SINF 记录和 SUPF 表,派生工作密钥和每个页面密钥,解密页面,清除cryptid,并写出新的 IPA。 - 如果输出需要安装,请重新签名。解密会清除加密标记,但不会生成有效的代码签名。
解密路径中的任何环节都不会联系 Apple。与设备的唯一交互是提取步骤。解密器是纯 Python,可在 macOS 或 Linux 上运行。
攻击如何展开?
已越狱设备观察 fairplayd 以恢复账户凭据,凭据解包每款应用的密钥,因此页面可以离线解密。
用于每款拥有的应用"] D --> E["从 SINF priv 解包应用工作密钥"] E --> F["从 SUPF 记录派生页面密钥"] F --> G["解密 arm64 页面并清除 cryptid"]
攻击者能做什么?
拥有凭据的攻击者可以离线、反复解密 Apple 账户拥有的匹配 IPA,然后读取或重新打包其代码和资源。影响是机密性和重新打包,而不是远程代码执行。
条件是影响的一部分:
- 应用必须属于凭据的账户并匹配其类型。README 说每条凭据适用于其来源的 Apple 账户的应用,而 Arcade 应用需要单独的 Arcade 凭据。
- IPA 必须包含受支持的 SINF 和 SUPF 组合所对应的加密 arm64 切片。
- 攻击者需要一份 IPA。
- 用于安装的重新打包需要签名身份。该工具不签名。
- 解密不会绕过服务器端认证、业务逻辑或 App Attest。重新打包的应用调用您的服务器时,这些检查仍会运行。
解密后的 IPA 会暴露 Swift 和 Objective-C 代码、字符串、嵌入配置、API 端点,以及随二进制分发的任何密钥或令牌。这会缩短漏洞研究时间,并使重新打包更容易。攻击者可以注入框架或更改资源,重新签名 bundle,并在 App Store 之外分发。
第二个公开项目 UnfairPlay 从已注册的 Mac 而不是已越狱 iPhone 恢复可复用模型。其 README 说,一个模型可以解密同一注册的其他个性化 IPA,并可将 iOS IPA 转换为 macOS 布局。这把门槛从已越狱手机降到 Mac App Store 账户。该项目于 2026 年 10 月 25 日出现,距 fairplay-decrypt 的首次提交 6 天。
UnfairPlay 还警告说,其输出会保留输入的 SC_Info 许可证和 iTunesMetadata.plist,这些文件会标识商店账户,除非操作者删除它们。粗心分享的解密 IPA 可能同时暴露账户身份和代码。
2026 年 11 月 12 日,fairplay-decrypt 仓库有超过 2,400 个星标和 375 个复刻。关注度不等于利用:项目或已核查来源中都没有报告使用该工具的攻击。
仅在您获准分析的应用上使用该工具。解密命令把输入描述为获准的 IPA。
为什么修复有效?
没有可引用的修复版本,因此项目中没有东西能关闭这一设计弱点。修复必须改变密钥层级,而不是一个解析函数。三项改动会提高成本:
- 把每应用的密钥绑定到操作系统无法读取的硬件机密(例如 Secure Enclave),并在释放密钥前验证操作系统。
- 由检查设备和账户的服务器下发每应用、每会话的密钥,而不是从保存在设备上的账户凭据派生。
- 轮换凭据方案,并在检测到滥用时使已提取的凭据失效。
这些都不是一行补丁,而且每一项仍在某种程度上信任设备。已越狱的操作系统即使密钥被封装,也能观察用户空间守护进程。在本例中,客户端 DRM 未能对拥有内核访问权限的设备所有者保密代码。
项目持续跟进 Apple 的变化。它增加了 iOS 10 到 12 提取、16 KB 页面支持、SUPF 版本 5、多个 arm64 切片和 Apple Arcade 凭据。fairplay-decrypt 没有分配 CVE,项目也没有移除账户凭据依赖的版本。
如何检查是否已遭入侵?
解密副本不会在您的服务器上留下痕迹,因此请检查重新打包的构建版本和账户凭据暴露。对每个分发的构建版本,寻找以下线索:
- 本应加密的构建版本中
cryptid为 0。 - TeamIdentifier 不是您的代码签名。
- 与您的发布版本不同的 bundle 标识符、
Info.plist或embedded.mobileprovision。 - 注入的框架或额外的
SC_Info文件。 - 在 App Store 或 TestFlight 之外分发。
提取主二进制并检查:
unzip -p Suspicious.ipa Payload/App.app/App > /tmp/App
otool -l /tmp/App | grep -A4 LC_ENCRYPTION_INFO_64
codesign -dv --verbose=4 /tmp/App
明文二进制加上另一团队的签名是强线索,但不是解密证据。未加密的二进制不能证明副本被解密。
在服务器端,检查 App Attest 和 DeviceCheck 失败、越狱设备信号,以及版本异常或缺少完整性标头的 API 客户端。这些也是线索,不是证据。项目没有发布入侵指标。解密是不联网的离线文件操作,因此失败的尝试可能不留痕迹。
时间线
- 2026-10-19:
EthanArbuckle/fairplay-decrypt仓库收到首次公开提交。 - 2026-10-22:README 确认支持 iOS 15。
- 2026-10-23:一次提交增加了 iOS 10 到 12 的凭据提取。
- 2026-10-25:macOS 项目
UnfairPlay创建。 - 2026-10-30:项目增加 GPLv3 许可证和 Apple Arcade 凭据提取。
- 2026-11-08:最新提交用 FairPlay IOKit 观察替换 Arcade 捕获。
常见问题
fairplay-decrypt 有 CVE 吗?
没有。该项目是研究工具,不是带修复版本的产品漏洞。截至 2026 年 11 月 12 日,NVD 没有该项目的 FairPlay 记录,CISA KEV 目录 2026.11.10 也没有 FairPlay 条目。
需要越狱吗?
对 fairplay-decrypt 来说,提取时需要。提取工具需要一台带 root SSH 的已越狱 iPhone。解密本身可在没有手机的情况下于 macOS 或 Linux 上运行。另一个项目 UnfairPlay 使用已注册的 Mac,而不是已越狱 iPhone。
一条凭据能解密所有应用吗?
它能解密该凭据所属 Apple 账户的匹配 IPA。普通凭据覆盖普通应用,README 说 Arcade 应用需要单独的 Arcade 凭据。它不能解密其他账户的应用,也不能解密 FairPlay Streaming 视频。
输出可以直接安装吗?
不能。该工具清除 cryptid,但不会重新签名二进制。iOS 要求有效签名,因此安装前必须用描述文件重新签名。
覆盖哪些应用和 iOS 版本?
提取工具称支持 iOS 10 或更高版本。解密器支持 arm64 Mach-O 切片、SUPF 版本 3 和 5,以及 440 或 448 字节的 SINF priv 记录。它不处理仅 32 位的应用或未加密的二进制。
它已在野利用吗?
没有。截至 2026 年 11 月 12 日,项目或已核查来源中都没有报告使用该工具的攻击。它也不在 CISA KEV 中。星标和复刻数表明关注度,而不是利用。
参考文献
EthanArbuckle/fairplay-decrypt仓库 README,包含 16 字节凭据、支持的格式和离线解密:https://github.com/EthanArbuckle/fairplay-decrypt/blob/main/README.md (2026 年 11 月 12 日核查)core.py,提交 d81d98b13656c9dbb340f04dd0838137278f44a5,SINF、SUPF 和页面密钥派生:https://github.com/EthanArbuckle/fairplay-decrypt/blob/d81d98b13656c9dbb340f04dd0838137278f44a5/core.py (2026 年 11 月 12 日核查)decrypt.py,同一提交,IPA 输入和输出路径:https://github.com/EthanArbuckle/fairplay-decrypt/blob/d81d98b13656c9dbb340f04dd0838137278f44a5/decrypt.py (2026 年 11 月 12 日核查)credential-retrieval/README.md,已越狱设备的先决条件、iOS 10 或更高版本,以及可复用账户凭据:https://github.com/EthanArbuckle/fairplay-decrypt/blob/main/credential-retrieval/README.md (2026 年 11 月 12 日核查)credential-retrieval/credential/observer.c,硬件断点和 FairPlay 观察器:https://github.com/EthanArbuckle/fairplay-decrypt/blob/main/credential-retrieval/credential/observer.c (2026 年 11 月 12 日核查)credential-retrieval/credential/credential.c,选择器、keybag 和凭据派生:https://github.com/EthanArbuckle/fairplay-decrypt/blob/main/credential-retrieval/credential/credential.c (2026 年 11 月 12 日核查)- 提交 5fdf16b48ea4a2a32950641aba23dd3063c34856,2026 年 10 月 19 日的首次公开提交:https://github.com/EthanArbuckle/fairplay-decrypt/commit/5fdf16b48ea4a2a32950641aba23dd3063c34856 (2026 年 11 月 12 日核查)
- 提交 9e5aa3ea290d79c3320190004dc512e034d99484,2026 年 10 月 30 日的 GPLv3 许可证:https://github.com/EthanArbuckle/fairplay-decrypt/commit/9e5aa3ea290d79c3320190004dc512e034d99484 (2026 年 11 月 12 日核查)
- 提交 8350383e2e9050f7a77197bf32545ddbef90b57c,2026 年 10 月 30 日的 Apple Arcade 凭据提取:https://github.com/EthanArbuckle/fairplay-decrypt/commit/8350383e2e9050f7a77197bf32545ddbef90b57c (2026 年 11 月 12 日核查)
- 提交 5e35c7a,2026 年 10 月 23 日的 iOS 10 到 12 支持:https://github.com/EthanArbuckle/fairplay-decrypt/commit/5e35c7a (2026 年 11 月 12 日核查)
EthanArbuckle/fairplay-decrypt提交历史,包含 iOS 10 到 12、16 KB 页面、SUPF v5、多切片和 Arcade 变更:https://github.com/EthanArbuckle/fairplay-decrypt/commits/main (2026 年 11 月 12 日核查)DrWhax/unfairplay仓库 README,已注册 Mac 途径和可复用模型:https://github.com/DrWhax/unfairplay/blob/main/README.md (2026 年 11 月 12 日核查)DrWhax/unfairplay仓库页面,2026 年 10 月 25 日创建:https://github.com/DrWhax/unfairplay (2026 年 11 月 12 日核查)vnc0/fairplay-scinfo,SINF 和 SUPF 格式以及封装页面密钥的文档:https://github.com/vnc0/fairplay-scinfo (2026 年 11 月 12 日核查)- Apple,
loader.h,LC_ENCRYPTION_INFO_64结构和cryptid字段:https://github.com/apple-oss-distributions/xnu/blob/main/EXTERNAL_HEADERS/mach-o/loader.h (2026 年 11 月 12 日核查) - CISA,Known Exploited Vulnerabilities 目录 JSON,版本 2026.11.10,没有 FairPlay 条目:https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json (2026 年 11 月 12 日核查)
- NVD 的 FairPlay 搜索,截至 2026 年 11 月 12 日没有该项目记录:https://nvd.nist.gov/vuln/search/results?query=fairplay&search_type=all (2026 年 11 月 12 日核查)
EthanArbuckle/fairplay-decrypt仓库页面,2026 年 11 月 12 日有超过 2,400 个星标和 375 个复刻:https://github.com/EthanArbuckle/fairplay-decrypt (2026 年 11 月 12 日核查)