乐于分享
好东西不私藏

macOS 26 原生运行任意版本 iOS 越狱虚拟机 —— vphone-cli 技术架构深度分析

macOS 26 原生运行任意版本 iOS 越狱虚拟机 —— vphone-cli 技术架构深度分析

vphone-cli 是一个通过 Apple Virtualization.framework 引导虚拟 iPhone (iOS 26) 的研究工具,利用 PCC (Private Cloud Compute) 研究虚拟机基础设施实现完整的 iOS 虚拟化。


目录

  1. 项目起源与技术演进
  2. 系统全景
  3. 固件组装流水线
  4. 混合身份签名架构
  5. 动态二进制补丁系统
  6. Metal GPU 加速——核心技术突破
  7. 越狱机制深度剖析
  8. Swift 虚拟机运行时
  9. Host-Guest 控制协议
  10. Guest Daemon 架构
  11. GUI 与交互系统
  12. 构建系统
  13. 技术风险与未来挑战

术语与核心概念

本文档涉及大量 iOS 安全研究领域的专有术语,此处集中解释以便理解后续章节:

术语
全称
说明
SHSH Blob
Signature HaSH Blob
Apple 设备固件恢复时的签名票据。每次通过 DFU/Recovery 模式恢复固件时,设备会向 Apple 的 TSS (Ticket Signing Server) 发送请求,TSS 返回一个包含 APNonce、ECID 等设备唯一标识的签名数据包——即 SHSH blob。它证明"Apple 允许该设备安装此版本固件"。在本项目中,restore_get_shsh 阶段获取该票据,从中提取 IM4M (IMG4 Manifest) 签名清单,用于对补丁后的引导链组件重新签名,使 Secure Boot 链信任我们修改过的 iBSS/iBEC/内核等。
CFW
Custom FirmWare
定制固件
。泛指对 Apple 原始固件进行修改后的版本。在本项目中特指通过 cfw_install.sh 安装到虚拟 iPhone 上的一系列用户空间补丁集合,包括:Cryptex 文件系统注入、设备激活锁绕过(mobileactivationd)、launchd 缓存验证禁用、SEP 工具修补(seputil)、GPU 驱动注入、SSH 守护进程部署等。CFW 安装分 7 个阶段,通过 SSH Ramdisk 在恢复完成后写入根文件系统。
IPSW
iPhone Software
Apple 设备的固件包格式(实为 ZIP 压缩包),包含引导链、内核、根文件系统、Cryptex 分区等全部组件。本项目需要两个 IPSW:iPhone IPSW(提供 iOS 用户空间)和 cloudOS IPSW(提供 PCC 虚拟机引导链与内核)。
DFU
Device Firmware Upgrade
设备固件升级模式。iOS 设备的最底层恢复模式,在此模式下设备仅运行 BootROM 代码,等待 USB 传输固件。本项目通过 Virtualization.framework 的 _setForceDFU 私有 API 使虚拟机直接进入 DFU 模式。
IM4P / IM4M / IMG4
Image4 格式族
Apple 的固件镜像签名格式。IM4P (Image4 Payload) 是载荷容器;IM4M (Image4 Manifest) 是签名清单,从 SHSH blob 中提取;IMG4 是最终的签名镜像,= IM4P + IM4M。引导链中的每个组件(iBSS、iBEC、内核等)都以 IMG4 格式存储。
Cryptex
Cryptographic Extension
iOS 16+ 引入的加密扩展分区机制。将系统库(dyld_shared_cachelibSystem.B.dylib 等)和应用运行时从主系统分区中分离出来,独立签名和更新。分为 SystemOS Cryptex(系统库)和 AppOS Cryptex(应用运行时)。使用 AEA (Authenticated Encryption Archive) 格式加密。
Ramdisk
RAM Disk
完全运行在内存中的临时文件系统。本项目构建一个注入了 SSH 工具的 Ramdisk,在恢复完成后通过 DFU 引导启动,提供 SSH 访问以手动修补根文件系统(安装 Cryptex、注入驱动、部署 daemon 等)。
MACF
Mandatory Access Control Framework
macOS/iOS 内核的强制访问控制框架,Sandbox、AMFI 等安全策略都注册为 MACF 策略模块。内核补丁中需要绕过多个 MACF 钩子以禁用沙盒限制。
AMFI
Apple Mobile File Integrity
Apple 的文件完整性验证守护进程,负责验证 Mach-O 二进制的代码签名和 entitlement。需要在宿主 macOS 上禁用 AMFI 才能运行携带私有 entitlement 的 vphone-cli。
SIP
System Integrity Protection
macOS 的系统完整性保护机制。需要禁用以允许加载私有 entitlement 和访问受保护的 Virtualization.framework 私有 API。
Entitlement
Apple 平台的权限声明,嵌入在二进制签名中的 plist 键值对。本项目需要 com.apple.private.virtualization 等私有 entitlement,正常情况下仅 Apple 自身二进制持有。
Trust Cache
iOS 的静态信任缓存,包含被系统信任的 Mach-O 文件的 CDHash 列表。通过 SSH Ramdisk 注入的二进制(如 vphoneddropbear)需要生成对应的 trust cache 才能在 AMFI 启用的 Guest 中执行。

0. 项目起源与技术演进

0.1 发现:PCC 固件中的 vphone600ap 组件

2024 年底,Apple 推出 Private Cloud Compute,宣称开辟云端 AI 隐私新纪元。2025 年底,安全研究社区注意到一个异常信号:Apple 在 cloudOS 26 的 PCC 固件中新增了 vphone600ap 相关组件——包括专用内核缓存 kernelcache.research.vphone600、设备树 DeviceTree.vphone600ap.im4p 等。

这些组件的名称强烈暗示 **"iPhone Research Environment Virtual Machine"**。这是 Apple 计划为安全研究者构建的虚拟 iPhone 环境,还是一次意外泄露?考虑到 2021 年 iOS 15.0 beta 至 15.1 beta3 OTA 中曾包含 DEVELOPMENT/KASAN 内核(持续约 4 个月),意外泄露的可能性不能排除。

2026 年 1 月,@_inside 在 Twitter 发布了利用这些 vphone600ap 组件启动虚拟 iPhone 的演示。相比此前的 QEMUAppleSilicon (Inferno) 项目,该方案运行流畅且支持 Metal 加速。这直接催生了本项目的开发(2026 年 1 月 31 日启动)。

0.2 技术传承谱系

本项目并非从零构建,而是站在三个关键前序项目的基础之上:

┌─────────────────────────────────────────────────────────────────────┐│                        技术传承链                                     ││                                                                      ││  security-pcc (Apple 官方)                                           ││  └── /System/Library/SecurityResearch/usr/bin/vrevm 源码             ││      发现: PV=3, BDID=0x90, ISA=2 硬件模型参数                       ││      发现: AVPBooter/AVPSEPBooter ROM 路径                           ││      发现: 1290x2796 分辨率 (iPhone 14 Pro Max/15 Plus/15 Pro Max)   ││                             │                                        ││                             ▼                                        ││  super-tart (JJTech0130)                                             ││  └── tart macOS VM 的扩展版: 自定义 ROM, 串口, DFU, GDB             ││      提供了 Virtualization.framework 私有 API 的 Swift 封装           ││                             │                                        ││                             ▼                                        ││  vma2pwn (nick-botticelli)                                           ││  └── macOS 12.0.1 虚拟机引导链完整修改                                ││      提供了固件补丁 + DFU 恢复 + idevicerestore 的完整工作流          ││      prepare.sh: IM4P 提取 → RAW 补丁 → IM4P 重建                   ││      vma2pwn.sh: DFU 模式 → idevicerestore 恢复                     ││                             │                                        ││                             ▼                                        ││  vphone-cli (本项目)                                                 ││  └── 三者融合 + 核心创新:                                             ││      ① 混合固件 (iPhone iOS 用户空间 + cloudOS 引导链)                ││      ② 动态补丁 (零硬编码偏移, 取代 vma2pwn 的静态地址)              ││      ③ Metal GPU 加速 (AppleParavirtGPU 驱动移植)                    ││      ④ vsock 控制协议 + Guest Daemon 架构                            │└─────────────────────────────────────────────────────────────────────┘

0.3 从硬编码到动态发现——关键架构演进

早期原型(super-tart-vphone writeup 阶段)使用硬编码文件偏移进行补丁,例如:

# 早期方式: 硬编码偏移 (仅适用于特定固件版本 26.1/23B85)patch(0x9D100xd503201f)   # iBSS: noppatch(0x9D140xd2800000)   # iBSS: mov x0, #0patch(0x24769640xd503201f)  # kernel: 根快照检查 NOPpatch(0x23cfde40xd503201f)  # kernel: 密封完整性 NOP

vphone-cli 将此演进为零硬编码偏移的动态分析系统:通过字符串锚定、ADRP 交叉引用索引、BL 频率分析等技术自动定位补丁点,确保跨固件版本兼容。这是整个项目最重要的工程化改进之一。

0.4 libirecovery 适配

标准 libimobiledevice 工具链不识别 vresearch101ap 硬件模型。项目需要修改 libirecovery 以添加 vresearch101ap 的设备描述符,使 idevicerestore 能够正确匹配恢复身份并完成 DFU 固件刷写。这是一个容易被忽视但不可或缺的前置步骤。


1. 系统全景

1.1 核心思想

将 iPhone iOS IPSW(完整用户空间)与 cloudOS IPSW(PCC 引导链 + 内核)合并为混合固件,对引导链施加动态二进制补丁绕过签名验证,使其在 macOS Virtualization.framework 的 vresearch1 虚拟硬件上启动完整的 iPhone iOS。

1.2 端到端数据流

┌─────────────────────────────────────────────────────────────────────┐│                        IPSW 来源                                    ││   iPhone IPSW (iOS 26.1)    cloudOS IPSW (PCC vresearch101ap)      ││   ├── iOS 用户空间           ├── 引导链 (LLB/iBSS/iBEC/SPTM/TXM)   ││   ├── Cryptex SystemOS/AppOS ├── 内核缓存 (vphone600)               ││   └── 静态信任缓存           └── 设备树/SEP/GPU/ANE 固件             │└──────────────┬──────────────────────────┬──────────────────────────┘               │ fw_prepare.sh           │               ▼                          ▼┌─────────────────────────────────────────────────────────────────────┐│                     合并工作目录                                      ││   iPhone*_Restore/                                                  ││   ├── kernelcache.*            ← 来自 cloudOS                       ││   ├── Firmware/{all_flash,dfu,agx,ane,pmp}/*  ← 来自 cloudOS       ││   ├── 058-*-*.dmg + 058-*-*.trustcache       ← 保留 iPhone 的      ││   └── BuildManifest-iPhone.plist             ← 备份原始清单          │└──────────────────────────┬──────────────────────────────────────────┘                           │ fw_manifest.py                           ▼┌─────────────────────────────────────────────────────────────────────┐│   混合 BuildManifest.plist + Restore.plist                          ││   单一 DFU Erase Install 身份 (20 个组件)                            ││   跨 vresearch101ap / vphone600ap / iPhone 三个来源嫁接              │└──────────────────────────┬──────────────────────────────────────────┘                           │ fw_patch.py                           ▼┌─────────────────────────────────────────────────────────────────────┐│   补丁后固件 (6 组件, 41+ 处修改)                                    ││   AVPBooter(1) + iBSS(2) + iBEC(3) + LLB(6) + TXM(1) + Kernel(25) │└──────────────────────────┬──────────────────────────────────────────┘                           │          ┌────────────────┼────────────────┐          ▼                ▼                ▼    restore (DFU)    ramdisk_build     vm_create          │           ramdisk_send         │          │                │               │          └───────┬────────┘               │                  ▼                        │           cfw_install.sh                  │           (7 阶段 SSH 安装)               │                  │                        │                  └────────┬───────────────┘                           ▼                     make boot                  ┌─────────────┐                  │  vphone-cli  │ ← Swift 6.0 + Virtualization.framework                  │  PV=3 虚拟机  │                  │  vsock 控制   │ ⟷ vphoned (Guest Daemon)                  └─────────────┘

1.3 技术栈总览

graph TB    subgraph "宿主 (macOS Sequoia 15+)"        CLI["vphone-cli<br/>Swift 6.0 + SwiftPM"]        VF["Virtualization.framework<br/>(Private APIs via Dynamic)"]        CLI --> VF    end    subgraph "固件工具链 (Python + Shell)"        FW["fw_prepare.sh<br/>IPSW 下载/合并"]        MF["fw_manifest.py<br/>混合清单生成"]        FP["fw_patch.py<br/>引导链补丁"]        RB["ramdisk_build.py<br/>SSH Ramdisk"]        CI["cfw_install.sh<br/>CFW 安装"]        PT["patchers/<br/>kernel.py | iboot.py<br/>txm.py | cfw.py"]        FW --> MF --> FP --> RB --> CI        FP --> PT        CI --> PT    end    subgraph "虚拟机 (iOS 26)"        GD["vphoned<br/>Objective-C Guest Daemon"]        IOS["iPhone iOS 用户空间"]        GD --> IOS    end    CLI -.->|"vsock:1337"| GD    FP -.->|"Capstone + Keystone"| PT

2. 固件组装流水线

2.1 六阶段流水线

graph LR    A["1. vm_create<br/>创建 VM 目录"] --> B["2. fw_prepare<br/>下载/合并 IPSW"]    B --> C["3. fw_patch<br/>补丁引导链"]    C --> D["4. restore<br/>DFU 刷写"]    D --> E["5. ramdisk<br/>SSH 启动"]    E --> F["6. cfw_install<br/>安装 CFW"]    F --> G["正常启动"]    style A fill:#2e2e2e,stroke:#60a5fa,color:#e0e0e0    style B fill:#2e2e2e,stroke:#60a5fa,color:#e0e0e0    style C fill:#2e2e2e,stroke:#fbbf24,color:#e0e0e0    style D fill:#2e2e2e,stroke:#fbbf24,color:#e0e0e0    style E fill:#2e2e2e,stroke:#fbbf24,color:#e0e0e0    style F fill:#2e2e2e,stroke:#fbbf24,color:#e0e0e0    style G fill:#2e2e2e,stroke:#4ade80,color:#e0e0e0

2.2 VM 目录结构 (vm_create.sh)

vm/├── AVPBooter.vresearch1.bin       ← 从 Virtualization.framework 资源复制├── AVPSEPBooter.vresearch1.bin    ← 同上├── Disk.img                       ← 64 GB 稀疏镜像 (dd seek, APFS COW)├── SEPStorage                     ← 512 KB 全零, 模拟 SEP 安全存储├── machineIdentifier              ← 首次启动时创建, 持久化 ECID├── nvram.bin                      ← 每次启动覆盖└── .vphoned.signed                ← Guest daemon 签名二进制

2.3 IPSW 合并策略 (fw_prepare.sh)

iPhone IPSW                          cloudOS IPSW┌────────────────┐                  ┌────────────────┐│ iOS 系统镜像    │                  │ 引导链          ││ Cryptex DMGs   │                  │  LLB/iBSS/iBEC ││ Trust Caches   │ ◄─── 保留 ─────  │  SPTM/TXM/SEP  ││ BuildManifest  │  (备份为 -iPhone) │ 内核缓存        ││                │                  │ 设备树/GPU/ANE  │└───────┬────────┘                  └───────┬────────┘        │                                   │        └──────────────┬────────────────────┘                       ▼              合并后的 Restore 目录              (cloudOS 引导链覆盖 iPhone 对应位置)              使用 cp -cR (APFS clone, 零拷贝)

2.4 Ramdisk 构建 (ramdisk_build.py)

8 步签名流水线,处理 iBSS → iBEC → SPTM → DeviceTree → SEP → TXM → Kernel → Ramdisk+Trustcache:

SHSH Blob ─→ 提取 IM4M (签名清单)                │                ├─→ iBSS: 已补丁 IM4P → 用 IM4M 签名为 IMG4                ├─→ iBEC: 替换 boot-args (rd=md0) → 签名                ├─→ SPTM: 仅签名                ├─→ DeviceTree: 重标记为 rdtr → 签名                ├─→ SEP: 重标记为 rsep → 签名                ├─→ TXM release: 重新补丁(restore用) → lzfse 压缩 → 保留 PAYP → 签名                ├─→ Kernel: 重标记为 rkrn → 保留 PAYP → 签名                └─→ Ramdisk:                     原始 cloudOS ramdisk DMG                           ↓ 扩展为 254 MB APFS                           ↓ 注入 SSH 工具 (ssh.tar.gz)                           ↓ ldid 重签所有 Mach-O (signcert.p12)                           ↓ trustcache 生成信任缓存                           ↓ 签名

PAYP 保留技术:某些 IM4P 文件尾部附带 PAYP (payload properties)。通过 rfind(b"PAYP") 定位,追加到新 IM4P 末尾并修正 ASN.1 长度字段。

2.5 Cryptex 恢复失败——SSH Ramdisk 方案的根本原因

固件恢复(idevicerestore)完成后,虚拟机会自动重启,但此时会在 launchd 进程中发生 panic:因为 /usr/lib/libSystem.B.dylib 缺失。该库位于 Cryptex 分区的 dyld_shared_cache 中,而 Cryptex 分区在恢复过程中未能正确写入

这是因为混合固件的 Cryptex DMG 来自 iPhone IPSW,但恢复流程本身由 cloudOS 的引导链驱动。cloudOS 的恢复逻辑与 iPhone Cryptex 的 AEA (Authenticated Encryption Archive) 格式之间存在不兼容,导致 Cryptex 数据无法在恢复阶段被正确安装。

解决方案是引入 SSH Ramdisk 作为中间步骤:在恢复完成后、首次正常启动前,通过 SSH Ramdisk 启动虚拟机,手动执行以下操作:

恢复后问题诊断:  idevicerestore 完成 → 重启 → launchd panic  原因: /usr/lib/libSystem.B.dylib 缺失       ← dyld_shared_cache 不存在       ← Cryptex 分区未正确恢复       ← cloudOS 恢复逻辑不兼容 iPhone AEA CryptexSSH Ramdisk 修复流程:  1. APFS 快照重命名 (com.apple.os.update-* → orig-fs)     → 允许后续修改根文件系统  2. AEA 解密 iPhone SystemOS Cryptex → 挂载 → SCP 传输到 /mnt1/System/Cryptexes/OS  3. 复制 iPhone AppOS Cryptex → /mnt1/System/Cryptexes/App  4. 创建 dyld 符号链接:     /System/Library/Caches/com.apple.dyld → ../../../System/Cryptexes/OS/...     /System/DriverKit/System/Library/dyld → ../../../../System/Cryptexes/OS/...

这个问题直接解释了为什么整个流水线必须包含 ramdisk_build → ramdisk_send → cfw_install 三个额外阶段,而不能像标准 iOS 恢复那样一步到位。

2.6 CFW 安装 (cfw_install.sh)

通过 SSH ramdisk 写入设备文件系统,7 个阶段(幂等设计,可安全重跑):

                        SSH Ramdisk 运行中 (端口 2222)                                   │    ┌──────────────────────────────┼──────────────────────────────┐    │                              ▼                              │    │  ┌─────────────────────────────────────────────────────┐   │    │  │ 1/7  Cryptex 安装                                    │   │    │  │   解析 iPhone BuildManifest → AEA 解密 SystemOS      │   │    │  │   → 复制 SystemOS + AppOS 到 /mnt1/System/Cryptexes │   │    │  │   → 创建 dyld 符号链接                               │   │    │  └─────────────────────────────────────────────────────┘   │    │  ┌─────────────────────────────────────────────────────┐   │    │  │ 2/7  seputil 补丁                                    │   │    │  │   "/%s.gl" → "/AA.gl" (Gigalocker UUID 固定化)       │   │    │  └─────────────────────────────────────────────────────┘   │    │  ┌─────────────────────────────────────────────────────┐   │    │  │ 3/7  GPU 驱动安装                                    │   │    │  │   AppleParavirtGPUMetalIOGPUFamily.bundle            │   │    │  └─────────────────────────────────────────────────────┘   │    │  ┌─────────────────────────────────────────────────────┐   │    │  │ 4/7  iosbinpack64 安装 (越狱工具包)                  │   │    │  └─────────────────────────────────────────────────────┘   │    │  ┌─────────────────────────────────────────────────────┐   │    │  │ 5/7  launchd_cache_loader 补丁                       │   │    │  │   NOP 条件分支 → 允许加载修改后的 launchd.plist       │   │    │  └─────────────────────────────────────────────────────┘   │    │  ┌─────────────────────────────────────────────────────┐   │    │  │ 6/7  mobileactivationd 补丁                          │   │    │  │   should_hactivate → 返回 YES (绕过激活锁)           │   │    │  └─────────────────────────────────────────────────────┘   │    │  ┌─────────────────────────────────────────────────────┐   │    │  │ 7/7  LaunchDaemons 安装                              │   │    │  │   编译 vphoned → 安装到 /usr/bin/                    │   │    │  │   注入 bash/dropbear/trollvnc/vphoned plist          │   │    │  │   补丁 launchd.plist                                 │   │    │  └─────────────────────────────────────────────────────┘   │    │                                                             │    │  APFS 快照管理: com.apple.os.update-* → orig-fs            │    │  所有补丁从 .bak 备份重新应用 (幂等)                         │    └─────────────────────────────────────────────────────────────┘

3. 混合身份签名架构

3.1 问题

DFU 硬件报告为 vresearch101ap (BDID=0x90, ChipID=0xFE01),但需要运行 iPhone iOS 用户空间。Apple 的签名验证要求 BuildManifest 中的身份与硬件完全匹配。

3.2 三源嫁接方案

fw_manifest.py 生成的 BuildManifest 从三个不同身份中精选组件:

┌─────────────────────────────────────────────────────────────────┐│              混合 Build Identity (单一 DFU Erase Install)        ││                                                                  ││  ┌──── vresearch101ap RELEASE ────┐  ┌── vresearch101ap RESEARCH ──┐│  │  LLB          (匹配 DFU 硬件)  │  │  iBoot/TXM (宽松限制)       ││  │  iBSS/iBEC    (DFU 签名)       │  │  KernelCache (research内核) ││  │  SPTM         (安全监视器)      │  └────────────────────────────┘│  │  RestoreRamDisk (cloudOS 恢复)  ││  └────────────────────────────────┘│                                                                  ││  ┌──── vphone600ap RELEASE ────────┐  ┌──── iPhone ERASE ──────────┐│  │  DeviceTree   (MKB dt=1,       │  │  OS (iOS 系统镜像)          ││  │               无 keybag 启动)   │  │  SystemVolume               ││  │  SEP Firmware (匹配设备树)      │  │  StaticTrustCache           ││  └────────────────────────────────┘  │  SystemVolumeCanonicalMetadata││                                       └────────────────────────────┘└─────────────────────────────────────────────────────────────────┘

3.3 Restore.plist 设备映射

DeviceMap 同时包含 iPhone 和 cloudOS 的设备条目,SupportedProductTypeIDs 合并两个来源的 DFU/Recovery ID,确保 idevicerestore 能匹配到正确的恢复身份。

选择逻辑:Info.Variant 部分匹配 "Erase Install (IPSW)" 同时排除 "Research"


4. 动态二进制补丁系统

4.1 核心设计哲学

零硬编码偏移 —— 所有补丁通过动态分析定位,确保跨固件版本兼容:

graph TD    A["字符串锚定<br/>在数据段找特征字符串"] --> B["ADRP 索引交叉引用<br/>O(1) 查找引用该字符串的代码"]    C["BL 频率分析<br/>按调用次数识别关键函数"] --> D["补丁点定位"]    E["唯一常量模式匹配<br/>Keystone 汇编 → 二进制搜索"] --> D    F["结构化数据遍历<br/>PRELINK_INFO plist / mac_policy_conf"] --> D    B --> D    D --> G["应用补丁<br/>NOP / mov x0,#0 / 无条件跳转"]    style A fill:#1a1a1a,stroke:#60a5fa,color:#e0e0e0    style B fill:#1a1a1a,stroke:#60a5fa,color:#e0e0e0    style C fill:#1a1a1a,stroke:#fbbf24,color:#e0e0e0    style D fill:#1a1a1a,stroke:#4ade80,color:#e0e0e0    style E fill:#1a1a1a,stroke:#fbbf24,color:#e0e0e0    style F fill:#1a1a1a,stroke:#f87171,color:#e0e0e0    style G fill:#1a1a1a,stroke:#4ade80,color:#e0e0e0

4.2 KernelPatcher 预处理架构

patchers/kernel.py 在应用任何补丁前构建三个全局索引,使后续查找达到 O(1) 或 O(n) 线性复杂度:

┌───────────────────────────────────────────────────────────────┐│                    预处理阶段 (一次性)                          ││                                                               ││  1. Mach-O 段解析                                             ││     解析 __TEXT, __TEXT_EXEC, __PRELINK_TEXT 等段              ││     确定 BASE_VA (0xFFFFFE0007004000) 和代码范围              ││                                                               ││  2. Kext 范围发现                                              ││     解析 __PRELINK_INFO (XML plist)                           ││     提取 APFS / Sandbox / AMFI 三个 kext 的                  ││     _PrelinkExecutableLoadAddr → 嵌入 Mach-O → __text 范围   ││                                                               ││  3. ADRP 页索引  [page_addr → [(file_offset, dest_reg)]]     ││     遍历所有可执行段的每条 ADRP 指令                           ││     解码目标页地址 → 建立倒排索引                              ││     效果: 给定字符串 VA → O(1) 找到所有 ADRP 引用             ││                                                               ││  4. BL 调用索引  [target_offset → [caller_offsets]]           ││     遍历所有 BL 指令 → 解码跳转目标                           ││     建立 callee → callers 的倒排索引                          ││     效果: O(1) 查询任意函数的调用者数量                        ││                                                               ││  5. _panic 发现                                               ││     条件: callers > 2000 且前方 ADRP+ADD 指向 "@%s:%d"        ││     用于后续定位 panic 相关分支                                │└───────────────────────────────────────────────────────────────┘

4.3 引导链补丁总览 (fw_patch.py, 6 组件 41+ 处)

┌──────────┬────────┬─────────────────────────────────────────────────────┐│ 组件      │ 补丁数 │ 关键技术                                             │├──────────┼────────┼─────────────────────────────────────────────────────┤│ AVPBooter │   1    │ 0x4447 ("DG") 常量锚定 → 返回值改 mov x0,#0        ││ iBSS     │   2    │ 串口 banner 替换 + Image4 回调 b.ne NOP             ││ iBEC     │   3    │ 串口 + Image4 绕过 + boot-args ADRP 重编码          ││ LLB      │   6    │ 串口 + Image4 + boot-args + rootfs(3处) + panic     ││ TXM      │   1    │ 0x2446 常量锚定 → 二叉搜索 BL → mov x0,#0          ││ Kernel   │  26    │ (见下方详细分类)                                      │└──────────┴────────┴─────────────────────────────────────────────────────┘

4.4 内核 26 处补丁分类

┌──────────────────────────────────────────────────────────────────────┐│                          内核补丁 (26 处)                            ││                                                                      ││  ┌─ APFS 文件系统 (6 处) ─────────────────────────────────────────┐ ││  │  #1  根快照检查 NOP       (tbnz w8,#5 → NOP)                  │ ││  │  #2  密封完整性 panic 跳过 (BL _panic 前条件分支 NOP)           │ ││  │  #3  rootvp 认证 panic 跳过                                    │ ││  │  #12 apfs_graft 根哈希验证 → mov w0,#0                        │ ││  │  #13-14 rw 挂载 + 升级检查 (cmp x0,x0 / mov w0,#0)           │ ││  │  #15 fsioc_graft Image4 验证 → mov w0,#0                     │ ││  │  #16 handle_get_dev_by_role 权限门控绕过 (NOP cbz → allow)    │ ││  │      ("com.apple.apfs.get-dev-by-role" entitlement gate)      │ ││  │      保障 /private/preboot / /private/xarts 挂载成功          │ ││  └────────────────────────────────────────────────────────────────┘ ││                                                                      ││  ┌─ 代码签名/启动约束 (4 处) ────────────────────────────────────┐  ││  │  #4-5  proc_check_launch_constraints → mov w0,#0; ret         │ ││  │  #8    TXM CodeSignature 后验证 tbnz NOP                      │ ││  │  #9    AMFI postValidation → cmp w0,w0 (始终通过)             │ ││  └────────────────────────────────────────────────────────────────┘ ││                                                                      ││  ┌─ 安全策略 (4 处) ─────────────────────────────────────────────┐  ││  │  #6-7  PE_i_can_has_debugger → mov x0,#1; ret (启用调试器)    │ ││  │  #10-11 dyld_policy_internal → mov w0,#1 (允许任意 dyld)     │ ││  └────────────────────────────────────────────────────────────────┘ ││                                                                      ││  ┌─ Sandbox MACF 钩子 (10 处, 5 个 hook × 2 条指令) ────────────┐  ││  │  #17-26 通过 mac_policy_conf 结构发现:                         │ ││  │    "Sandbox" + "Seatbelt sandbox policy" 字符串               │ ││  │    → __DATA_CONST chained fixup pointer                       │ ││  │    → ops 表 → 函数指针 → mov x0,#0; ret                      │ ││  │                                                                │ ││  │  禁用的 hook:                                                  │ ││  │    vnode_check_open / vnode_check_rename                      │ ││  │    mount_check_mount / mount_check_remount                    │ ││  │    vnode_check_access                                         │ ││  └────────────────────────────────────────────────────────────────┘ │└──────────────────────────────────────────────────────────────────────┘

4.5 IBootPatcher 通用模式 (iBSS/iBEC/LLB 共享)

                    iBSS        iBEC        LLB串口 banner 替换     ✓           ✓           ✓Image4 回调绕过      ✓           ✓           ✓自定义 boot-args               ✓           ✓rootfs 绕过 (6处)                           ✓Panic 绕过                                  ✓

Image4 回调绕过的通用模式:

搜索模式:  b.ne <target>; mov x0, x22   (且前方有 cmp 指令)补丁:      NOP b.ne + 置返回值为 0

4.6 CFW 用户空间补丁 (patchers/cfw.py)

┌─────────────────────────────────────────────────────────────────┐│  7 个 CLI 子命令                                                 ││                                                                  ││  cryptex-paths        解析 BuildManifest → Cryptex DMG 路径      ││  patch-seputil        "/%s.gl" → "/AA.gl" (Gigalocker 固定化)   ││  patch-launchd-cache  字符串锚 → ADRP xref → NOP 条件分支       ││  patch-mobileactivationd  符号表/ObjC 元数据 → mov x0,#1; ret   ││  patch-launchd-jetsam 字符串锚 → 条件分支 → 无条件跳转          ││  inject-daemons       plistlib 注入 LaunchDaemon 条目            ││  inject-dylib         Mach-O LC_LOAD_DYLIB 注入 (FAT 感知)      │└─────────────────────────────────────────────────────────────────┘mobileactivationd 补丁的双重回退策略:    策略 1: LC_SYMTAB 符号查找    ─────────────────────────    搜索 "should_hactivate" → 符号 VA → 文件偏移    策略 2: ObjC 元数据链 (符号表不可用时)    ─────────────────────────────────────"should_hactivate\0" 选择器字符串        → __objc_selrefs 指针            → __objc_const 相对方法列表                → 计算 IMP 偏移

5. Metal GPU 加速——核心技术突破

5.1 问题发现

固件恢复 + Cryptex 安装完成后的首次启动中,虚拟 iPhone 停留在黑色设置屏幕,无法继续(respring 循环)。通过 MetalTest 程序验证,MTLCreateSystemDefaultDevice() 返回 null——Metal 完全不可用。

然而 ioreg -l 显示内核已正确识别 AppleParavirtGPU 设备。问题出在用户空间缺少对应的 Metal 驱动库

5.2 根因分析:Metal 驱动加载链

iOS 的 Metal 实现依赖 /System/Library/Extensions 中的设备特定驱动 bundle。以实体设备为例:

实体 iPhone (A10 芯片):  MTLCreateSystemDefaultDevice()    → IOKit 匹配 IOGPU 驱动    → 加载 /System/Library/Extensions/AGXMetalA10.bundle    → 返回 MTLDevice 实例PCC 虚拟机 (macOS):  MTLCreateSystemDefaultDevice()    → IOKit 匹配 AppleParavirtGPU    → 加载 /System/Library/Extensions/AppleParavirtGPUMetalIOGPUFamily.bundle    → 返回 <AppleParavirtDevice> 实例虚拟 iPhone (问题状态):  MTLCreateSystemDefaultDevice()    → IOKit 匹配 AppleParavirtGPU  ✓ (内核已识别)    → /System/Library/Extensions/ 中无对应 bundle  ✗    → 返回 null

iPhone IPSW 的 /System/Library/Extensions 中只包含物理 GPU 对应的驱动(如 AGXMetal 系列),不含虚拟化 GPU 驱动。而 cloudOS (PCC) 的 /System/Library/Extensions 中恰好包含 AppleParavirtGPUMetalIOGPUFamily.bundle

5.3 解决方案:驱动移植 + dylib 逆向实现

┌──────────────────────────────────────────────────────────────────────┐│  Metal GPU 驱动移植方案                                               ││                                                                      ││  Step 1: 从 PCC 虚拟机提取驱动 bundle                                ││    /System/Library/Extensions/AppleParavirtGPUMetalIOGPUFamily.bundle││    (7 个文件)                                                        ││                                                                      ││  Step 2: 通过 SSH Ramdisk 注入到虚拟 iPhone                          ││    → /mnt1/System/Library/Extensions/ (cfw_install 阶段 3/7)         ││                                                                      ││  Step 3: 逆向实现缺失的 dylib                                        ││    问题: bundle 内的 libAppleParavirtCompilerPluginIOGPUFamily.dylib  ││          引用了 PCC 虚拟机 dsc (dyld_shared_cache) 中的符号            ││          但该 dylib 不存在于 iPhone 16 (iOS 26) 的 dsc 中            ││                                                                      ││    方案: 从 PCC 的 dsc 中逆向分析该 dylib 的接口与实现                ││          → 独立重新实现 → 编译为 arm64 dylib                          ││          → 注入虚拟 iPhone                                            ││                                                                      ││  验证: MTLCreateSystemDefaultDevice() 返回                            ││        <AppleParavirtDevice: 0x...>                                  ││        name = Apple Paravirtual device                               │└──────────────────────────────────────────────────────────────────────┘

这是整个项目最关键的技术突破之一:没有 Metal 加速,虚拟 iPhone 无法渲染 UI、无法通过 Setup 屏幕、SpringBoard 无法正常运行。Metal 支持是从"能启动"到"能使用"的分水岭。

5.4 SEP 配置的前置要求

在首次恢复阶段,如果 SEP (Secure Enclave Processor) 配置不当(SEPStorage 文件缺失或格式错误),会在恢复过程中触发 panic。正确配置需要:

  • SEPStorage:512 KB 全零文件,模拟 SEP 安全存储
  • AVPSEPBooter.vresearch1.bin:从 Virtualization.framework 资源复制
  • _VZSEPCoprocessorConfiguration:通过私有 API 正确初始化,绑定 storageURL + romBinaryURL

6. 越狱机制深度剖析

6.0 核心概念:虚拟化层越狱 vs 传统越狱

vphone 的越狱机制与传统物理设备越狱本质不同

┌─────────────────────────────────────────────────────────────────┐│              传统越狱 vs vphone 越狱对比                          ││                                                                  ││  传统越狱 (unc0ver / Taurine / checkra1n)                        ││  ──────────────────────────────────────────                      ││  • 依赖系统漏洞 (内核 exploit / bootrom bug)                     ││  • 版本绑定 (仅特定 iOS 版本可越狱)                               ││  • 运行时注入 (系统启动后执行漏洞利用)                            ││  • 签名冲突 (必须绕过已运行的 AMFI / Sandbox)                    ││  • 工具发布时滞 (等待研究者发现新漏洞)                            ││                                                                  ││  vphone 虚拟化层越狱                                              ││  ──────────────────────────────────────                          ││  • 无需系统漏洞 (固件级二进制补丁)                                ││  • 版本无关 (理论支持任意 iOS 版本)                               ││  • 刷写前修改 (DFU 恢复前完成所有补丁)                            ││  • 深度绕过 (修改 BootROM → TXM → Kernel 全链路)                ││  • 自带工具链 (补丁工具随项目分发)                                │└─────────────────────────────────────────────────────────────────┘

关键优势:由于在虚拟化环境中拥有对固件的完全控制权,可在 IPSW 刷写前直接修改引导链和内核二进制,绕过所有安全验证。这种"上帝视角"的修改方式是物理设备越狱永远无法企及的。

6.1 越狱补丁全景:分层架构

┌──────────────────────────────────────────────────────────────────┐│            越狱补丁金字塔 (fw_patch_jb + cfw_install_jb)          ││                                                                   ││  ┌─────────────────────────────────────────────────────────┐    ││  │  首次启动初始化 (vphone_jb_setup.sh)        9 步骤       │    ││  │  ────────────────────────────────────────────           │    ││  │  • /var/jb 符号链接 (launchdhook 运行时创建)             │    ││  │  • prep_bootstrap.sh → procursus 完整激活               │    ││  │  • Sileo / apt / libkrw0-tfp0 / TrollStore 安装         │    ││  └─────────────────────────────────────────────────────────┘    ││                          ▲                                       ││  ┌─────────────────────────────────────────────────────────┐    ││  │  用户空间 CFW JB (cfw_install_jb.sh)        5 阶段       │    ││  │  ────────────────────────────────────────────           │    ││  │  • JB-1: launchd jetsam 绕过 + /b 注入                  │    ││  │  • JB-2: iosbinpack64 安装                              │    ││  │  • JB-3: debugserver entitlements 补丁 (新增)           │    ││  │  • JB-4: procursus bootstrap + BaseBin hooks 部署       │    ││  │  • JB-5: 首次启动 LaunchDaemon 部署                     │    ││  └─────────────────────────────────────────────────────────┘    ││                          ▲                                       ││  ┌─────────────────────────────────────────────────────────┐    ││  │  内核层 (KernelCache JB)            24 活跃方法          │    ││  │  ────────────────────────────────────────────           │    ││  │  • task_for_pid / 任务转换 (调试器附加)                  │    ││  │  • AMFI 信任缓存 / execve 绕过 (代码签名)                │    ││  │  • Sandbox MACF hooks 禁用 (沙箱突破)                   │    ││  │  • IOUC MACF gate 绕过 (IOKit 访问)                     │    ││  │  • vm_fault / vm_protect (RWX 内存)                     │    ││  │  • syscall mask / cred_label hooks (特权提升)            │    ││  │  • NVRAM 权限 / 共享区域映射 (系统修改)                  │    ││  └─────────────────────────────────────────────────────────┘    ││                          ▲                                       ││  ┌─────────────────────────────────────────────────────────┐    ││  │  TXM 层 (Trusted Execution Monitor)     6 逻辑方法      │    ││  │  ────────────────────────────────────────────           │    ││  │  • trustcache 哈希绕过 (base)                            │    ││  │  • selector24 强制 PASS (mov w0,#0xa1 + b epilogue)     │    ││  │  • get-task-allow 强制启用 (selector 41)                 │    ││  │  • 调试器权限强制启用 (selector 42|29)                   │    ││  │  • 开发者模式强制启用 (init 阶段)                        │    ││  └─────────────────────────────────────────────────────────┘    ││                          ▲                                       ││  ┌─────────────────────────────────────────────────────────┐    ││  │  iBoot 层 (iBSS)                          1 补丁         │    ││  │  ────────────────────────────────────────────           │    ││  │  • APNonce 生成绕过 (允许任意 SHSH blob)                 │    ││  └─────────────────────────────────────────────────────────┘    │└──────────────────────────────────────────────────────────────────┘总计: 1 (iBSS) + 6 (TXM) + 24 (Kernel) + 3 (CFW) = 34 逻辑补丁组      对应 84+ 条指令级修改 (含 shellcode 多指令块)      注: CLAUDE.md 中 "126 patches" 为指令级总计 (含 dev 层叠加),          与此处"逻辑方法数"口径不同

6.2 TXM 越狱补丁:突破信任执行监视器

TXM (Trusted Execution Monitor) 是 iOS 26+ 引入的安全层,运行在 SPTM (Secure Page Table Monitor) 监管下的 GL1 (Guest Level 1) 特权级。所有代码签名验证、调试器权限检查都通过 TXM 选择器 (selector) 调度。

6.2.1 TXM 执行模型与返回路径约束

┌──────────────────────────────────────────────────────────────┐│                   TXM 执行上下文                              ││                                                               ││   SPTM (GL2) ◄─────── svc #0 ─────────┐                     ││      │                                 │                     ││      │ selector dispatch              │                     ││      ▼                                 │                     ││   TXM (GL1)                            │                     ││      │                                 │                     ││      │ 执行验证逻辑                    │                     ││      ▼                                 │                     ││   构造返回码 x16 ─────────────────────┘                     ││   (例: 0x000000FD00000000)                                   ││                                                               ││   CRITICAL: TXM 函数不能通过 ret/retab 返回!                ││   ─────────────────────────────────────                      ││   • RETAB → LR 指向 SPTM 地址空间                           ││   • TXM 无权执行 SPTM 代码 (权限故障)                        ││   • 必须通过 svc #0 陷入 SPTM 完成返回                       ││                                                               ││   返回链: func → bl <helper> → bl <stub> → b <trampoline>    ││            trampoline: pacibsp; svc #0; retab                │└──────────────────────────────────────────────────────────────┘

关键限制:这种架构要求补丁不能改变控制流返回路径。早期尝试用 mov x0,#0; retab 替换函数入口全部失败(权限故障),最终采用手术刀式原地修改,保留完整的 svc #0 返回链。

6.2.2 六大 TXM 补丁详解

TXM 补丁分为两层:base 层(patchers/txm.py)在所有模式下运行,dev/JB 层(patchers/txm_dev.py)通过 patch_txm_dev() 叠加。

Layer 1: txm.py — trustcache 哈希绕过 (base, 所有模式共享)─────────────────────────────────────────────────────────────────  定位: mov w19, #0x2446 唯一常量 → 扫描函数体       mov w2, #0x14; bl <hash_cmp>; cbz w0; tbnz w0, #0x1f  补丁: bl <hash_cmp> → mov x0, #0  效果: cbz w0 始终跳转 match 分支 → 信任缓存查找永远成功Layer 2: txm_dev.py — 5 个追加补丁 (selector24/41/42 + devmode)─────────────────────────────────────────────────────────────────  T-2 selector24 强制 PASS:    定位: 函数内唯一 "mov w0, #0xa1" (CS 失败错误码)          向前验证: LDR X1,[Xn,#0x38] / ADD X2 / BL / LDP 序列          向后定位: epilogue (ldp x29,x30 + retab)    补丁: body_start+0: mov w0, #0xa1          body_start+4: b   <epilogue>    效果: 短路全部哈希/版本验证, 直接以 PASS 清栈返回  T-3 get-task-allow 强制 true (selector 41):    定位: "get-task-allow" 字符串 ADRP xref → BL + TBNZ w0,#0    补丁: BL → mov x0, #1  T-4 selector42|29 shellcode hook (5 个补丁):    定位: "com.apple.private.cs.debugger" xref → debugger gate 函数          BTI J; mov x0,x20; BL; mov x1,x21; mov x2,x22; BL fn; B stub    补丁: B → cave (NOP + mov x0,#1 + strb w0,[x20,#0x30] + mov x0,x20 + B back)    效果: 预设 manifest[0x30]=1, 防 sel42 先于 sel41 运行时 assert  T-5 debugger entitlement 强制 true (selector 42):    定位: "com.apple.private.cs.debugger" xref          BL + TBNZ w0,#0 + 前置 mov x2,#0 / mov x0,#0    补丁: BL → mov w0, #1  T-6 developer mode 强制启用 (init 阶段):    定位: "developer mode enabled due to system policy configuration"          向后扫描 TBNZ/CBNZ w9,#0    补丁: → NOP

补丁依赖链

T-6 (devmode ON)  └─→ T-3 (sel41 需要 devmode 开启)       └─→ T-4 (sel42 需要 manifest[0x30]=1)            └─→ T-5 (sel42 debugger check)T-1 (base trustcache, 独立)   T-2 (sel24 独立, CS 代码签名绕过)

6.2.3 selector24 重新设计说明

当前方案(mov w0,#0xa1; b epilogue)相比早期 NOP 方案更为直接彻底:

Early (NOP-based, 已废弃):  ldr x1,[x20,#0x38] → NOP   ← 移除 hash_data_ptr 加载  bl  hash_flags_extract → NOP ← 移除 hash_flags 初始化  ... 继续执行后续逻辑 ...if (hash_data_ptr != 0) == ((hash_flags & 2) >> 1):return 0x130A1           ← hash_flags=0 时某些 CS blob 仍可能命中Current (force-PASS, 彻底短路):  [prologue: pacibsp; stp; ...; add x29,sp,#imm]  mov w0, #0xa1  ← 注入: PASS 返回码  b   <epilogue> ← 注入: 跳过全部验证逻辑  [原始函数体: 完全跳过]  [epilogue: ldp x29,x30; retab (→ svc#0)]

UUID Canary 验证:修改 TXM LC_UUID 末字节(如 655D → 655C),启动日志中出现匹配值则证明补丁后的 TXM 被正确加载。

6.3 内核越狱补丁:25 个 Mixin 的模块化设计

6.3.1 补丁架构总览

classKernelJBPatcher(# ── Group A: 核心门禁绕过 (4 活跃) ───────────────────────────    KernelJBPatchKcall10Mixin,               # JB-05: 内核函数调用接口 (kcall10)    KernelJBPatchIoucmacfMixin,              # JB-10: IOUC MACF gate 绕过 (新增)    KernelJBPatchHookCredLabelMixin,         # JB-04: cred_label hook 注入 (shellcode)    KernelJBPatchSyscallmaskMixin,           # JB-07: syscall mask 绕过 (shellcode)    KernelJBPatchCredLabelMixin,             # JB-03: cred_label 更新绕过# ── Group B: 字符串/模式锚定 (16 活跃) ───────────────────────    KernelJBPatchThidCrashMixin,             # JB-23: thid_should_crash=0    KernelJBPatchSecureRootMixin,            # JB-16: io_secure_bsd_root 绕过    KernelJBPatchNvramMixin,                 # JB-19: NVRAM 权限绕过    KernelJBPatchSharedRegionMixin,          # JB-20: 共享区域映射    KernelJBPatchLoadDylinkerMixin,          # JB-17: dyld 加载策略    KernelJBPatchTaskForPidMixin,            # JB-22: task_for_pid 允许    KernelJBPatchSpawnPersonaMixin,          # JB-21: persona 验证绕过    KernelJBPatchBsdInitAuthMixin,           # JB-14: _bsd_init rootauth gate 绕过    KernelJBPatchDounmountMixin,             # JB-15: unmount 检查绕过    KernelJBPatchMacMountMixin,              # JB-18: mount MACF 绕过    KernelJBPatchVmProtectMixin,             # JB-25: RWX 内存允许    KernelJBPatchVmFaultMixin,               # JB-24: cs_bypass gate NOP    KernelJBPatchPortToMapMixin,             # JB-13: 端口到 map 转换    KernelJBPatchProcPidinfoMixin,           # JB-12: 进程信息查询绕过    KernelJBPatchProcSecurityMixin,          # JB-11: 进程安全策略    KernelJBPatchPostValidationMixin,        # JB-06: 后验证绕过# ── Group A (cont): 复合绕过 ──────────────────────────────────    KernelJBPatchSandboxExtendedMixin,       # JB-09: Sandbox MACF hooks 批量禁用    KernelJBPatchTaskConversionMixin,        # JB-08: 任务转换检查绕过    KernelJBPatchAmfiExecveMixin,            # JB-02: amfi_execve (Mixin 保留, 方法从调度中排除)    KernelJBPatchAmfiTrustcacheMixin,        # JB-01: AMFI 信任缓存绕过    KernelJBPatcherBase):"""    25 个 Mixin, 24 个活跃方法.    JB-02 (patch_amfi_execve_kill_path) 被从 _GROUP_A_METHODS 调度计划中注释排除,    但 KernelJBPatchAmfiExecveMixin 仍保留在 MRO 中供单独调用.    JB-03 (patch_cred_label_update_execve) 代码注释标注 "disabled/pending revalidation",    但仍在 _GROUP_C_METHODS 调度列表中, 实际会被执行.    每个 Mixin 可包含:      • 1–40 条指令级补丁 (如 syscallmask 含 40 条 shellcode)      • 单条 NOP / MOV / 分支重定向      • 多个代码洞穴 (code cave) 中的 shellcode 块    """

执行调度(按组顺序):

Group A (核心门禁):  amfi_trustcache → task_conversion → sandbox_extended → iouc_macfGroup B (模式锚定):  post_validation → proc_security → proc_pidinfo → port_to_map                    bsd_init_auth → dounmount → secure_root → load_dylinker                    mac_mount → nvram → shared_region → spawn_persona                    task_for_pid → thid_crash → vm_fault → vm_protectGroup C (shellcode): cred_label_update → hook_cred_label → kcall10 → syscallmask

6.3.2 代表性补丁深度分析

A. task_for_pid 绕过 (调试器附加核心)

# KernelJBPatchTaskForPidMixin.patch_task_for_pid()# 定位策略: 0 BL callers + 2x ldadda + movk #0xc8a2 + ldr/str w,[x,#0x490]# 原始逻辑 (伪代码):deftask_for_pid(task, flavor, who, target):# ... 鉴权检查 ...if task.flags & HARDENED:  # ldr w,[task,#0x490]return EPERM           # 强化进程禁止访问# ... 返回目标任务 ...# 补丁: NOP ldr w,[task,#0x490] 指令#   → flags 寄存器保持 0 → HARDENED 检查恒为假 → 允许访问所有进程

效果:LLDB 可附加到任意进程(包括系统守护进程),无需 get-task-allow entitlement。

B. AMFI 信任缓存绕过 (任意代码执行)

# KernelJBPatchAmfiTrustcacheMixin.patch_amfi_cdhash_in_trustcache()# 定位策略: "loadable trust cache" 字符串锚定 → ADRP xref → 函数分析# 原始逻辑:defamfi_cdhash_in_trustcache(cdhash, cdhash_len, flags):for tc in loaded_trustcaches:if cdhash in tc.hash_list:returnTruereturnFalse# 未在信任缓存中 → 拒绝执行# 补丁: 函数入口替换为 mov x0, #1; ret#   → 所有二进制文件被视为"已信任" → 绕过代码签名验证

效果:可执行未签名的二进制文件(如自编译工具、逆向调试器)。

C. Sandbox MACF Hooks 批量禁用 (沙箱突破)

# KernelJBPatchSandboxExtendedMixin.patch_sandbox_hooks_extended()# 定位策略: "Sandbox" + "Seatbelt" 字符串 → mac_policy_conf 结构#          → ops 表 → 10 个 hook 函数指针 → 全部替换为 mov x0,#0; rethooks = ['vnode_check_open',      # 文件打开检查'vnode_check_rename',    # 文件重命名检查'mount_check_mount',     # 挂载点检查'mount_check_remount',   # 重新挂载检查'vnode_check_access',    # 文件访问检查# ... 共 10 个]# 补丁: 每个 hook 函数 → mov x0, #0; ret (2 条指令, 共 20 处修改)

效果:进程突破沙箱限制,可读写 /var/private 等受保护目录,访问相机/麦克风等硬件。

D. IOUC MACF gate 绕过 (IOKit 访问) — 新增

# KernelJBPatchIoucmacfMixin.patch_iouc_failed_macf()# 定位策略: "IOUC %s failed MACF in process %s" 字符串 → ADRP xref#          → 包含该字符串引用的函数内找 BL <macf_aggregator> + CBZ W0#          验证 macf_aggregator: ldr x10,[x10,#0x9e8] + blraa/blr x10 (slot load)# 原始逻辑:defIOUserClient_open(client, task):    result = mac_iokit_check_open(...)if result == 0:   # CBZ W0 → allow        proceed()else:        log("IOUC %s failed MACF in process %s")return deny# 补丁: CBZ W0 → B <allow>  (无条件跳转 allow 分支)#   → MACF 检查结果被忽略 → IOUserClient 始终允许打开

效果:绕过 IOKit 访问控制,进程可打开任意 IOUserClient(包括受 MACF 保护的 GPU/神经引擎驱动)。

E. vm_protect RWX 内存 (代码注入支持)

# KernelJBPatchVmProtectMixin.patch_vm_map_protect()# 定位策略: "VM_PROT_COPY" 字符串 → 函数上下文 → 权限检查分支# 原始逻辑:defvm_map_protect(map, start, end, new_prot):if (new_prot & VM_PROT_WRITE) and (new_prot & VM_PROT_EXECUTE):return KERN_PROTECTION_FAILURE  # W^X 策略: 禁止 RWX 内存# ... 应用保护 ...# 补丁: NOP 权限检查分支 → 允许创建可写+可执行内存

效果:支持运行时代码生成(如 JavaScript JIT、Python ctypes)。

F. _bsd_init rootauth 绕过 (根文件系统认证)

# KernelJBPatchBsdInitAuthMixin.patch_bsd_init_auth()# 定位策略: 符号 "_bsd_init" (或 "rootvp not authenticated after mounting" xref)#          → 函数内 "rootvp not authenticated after mounting" panic 路径#          → panic 调用前的 cbnz w0/x0 (FSIOC_KERNEL_ROOTAUTH 失败分支)#          → 验证: 前方有 bl (ioctl handler) + 后方有 bl imageboot_needed# 补丁: cbnz w0, panic_path → NOP#   → 即使 FSIOC_KERNEL_ROOTAUTH 返回错误也继续启动

6.3.3 Shellcode 注入型补丁

部分补丁需要注入全新代码逻辑(而非简单 NOP/修改),使用代码洞穴 (code cave) 技术:

# KernelJBPatchHookCredLabelMixin.patch_hook_cred_label_update_execve()步骤 1: 定位 Sandbox mac_policy_ops 表 (通过 "Sandbox" 字符串)步骤 2: 读取 ops[16] (hook_cred_label_update_execve 函数指针)步骤 3: 在 __TEXT_EXEC 中找到零填充区域 (UDF cave, ~180 字节)步骤 4: 注入 shellcode:    ┌─────────────────────────────────────────────────────┐    │ mrs x8, tpidr_el1         ; 读取当前线程指针       │    │ stp x8, x0, [sp, #0x70]   ; 构造 vfs_context 结构  │    │ add x1, sp, #0x70         ; x1 = &vfs_context       │    │ bl vnode_getattr_addr     ; 调用 vnode_getattr      │    │ ... 40+ 条指令 ...        ; 完整 hook 逻辑          │    │ b original_hook_addr      ; 跳回原始 hook 继续执行  │    └─────────────────────────────────────────────────────┘步骤 5: 修改 ops[16] 指向 shellcode 入口

关键技术

  • 内联 vfs_context 构造:避免符号依赖,通过 mrs tpidr_el1 直接读取线程局部存储
  • 动态函数地址解析vnode_getattr 通过 "vnode_getattr" 字符串锚定 + ADRP xref 定位
  • Code cave 分配:扫描 __TEXT_EXEC 中的全零区域(对齐至 0x40 字节边界)

6.4 用户空间越狱:Procursus + BaseBin 双层架构

6.4.1 五阶段 CFW JB 安装流程

cfw_install_jb.sh 执行流程:Phase 0: 运行基础 CFW 安装 (7 阶段, 同非 JB 版本)         CFW_SKIP_HALT=1 zsh cfw_install.sh         ├─ Cryptex 安装         ├─ seputil 补丁         ├─ GPU 驱动注入         ├─ iosbinpack64 (基础工具包)         ├─ launchd_cache_loader 补丁         ├─ mobileactivationd 补丁         └─ LaunchDaemons 安装═══════════════════════════════════════════════════════════Phase JB-1: launchd jetsam 绕过 + /b 注入┌────────────────────────────────────────────────────────┐│ 1. 备份 /sbin/launchd → /sbin/launchd.bak            ││ 2. 提取并保存原始 entitlements (ldid -e)              ││    (保留 spawn 权限, 避免 "operation not permitted")  ││ 3. 注入 LC_LOAD_DYLIB: /b (短路径别名)                ││    原因: launchd Mach-O 头空间有限, 无法容纳           ││    /cores/launchdhook.dylib 完整路径; 使用 /b 替代    ││ 4. 补丁 jetsam guard (cfw.py patch-launchd-jetsam):   ││    定位: "com.apple.xpc.launchd.domain" 字符串 → 函数 ││    查找: CBZ/CBNZ 分支判断 jetsam 状态                ││    修改: CBZ → B (无条件跳转, 跳过 panic)             ││ 5. 以原始 entitlements 重签名 + SCP 上传              │└────────────────────────────────────────────────────────┘Phase JB-2: iosbinpack64 安装 + dev overlay (本地 tar)┌────────────────────────────────────────────────────────┐│ 1. SCP iosbinpack64.tar → /mnt1                       ││ 2. tar --preserve-permissions -xf 解压到设备          ││ 3. apply_dev_overlay: 替换本地 iosbinpack64.tar 中的  ││    rpcserver_ios (cfw_dev/rpcserver_ios 存在时执行)    ││    注: 修改的是本地 tar 副本, 当次已解压的设备文件     ││    不受影响, 下次运行 JB-2 时才会应用到设备           │└────────────────────────────────────────────────────────┘Phase JB-3: debugserver entitlements 补丁┌────────────────────────────────────────────────────────┐│ 1. SCP 取回 /mnt1/usr/libexec/debugserver            ││ 2. 提取原始 entitlements (ldid -e)                    ││ 3. 移除 seatbelt-profiles (沙盒约束)                  ││ 4. 注入 task_for_pid-allow: YES                       ││ 5. 重签名 + 上传回 /mnt1/usr/libexec/debugserver     │└────────────────────────────────────────────────────────┘Phase JB-4: Procursus Bootstrap 安装 + BaseBin Hooks 部署┌────────────────────────────────────────────────────────┐│ Bootstrap 安装:                                        ││ 1. zstd -d bootstrap-iphoneos-arm64.tar.zst          ││ 2. 挂载 /dev/disk1s5 → /mnt5 (Preboot 卷)            ││ 3. 获取 boot_manifest_hash (96 字符 SHA-384)          ││ 4. 创建 /mnt5/<hash>/jb-vphone/ 目录                  ││ 5. tar --preserve-permissions -xf → jb-vphone/       ││ 6. 重组目录: mv var/ → procursus/                     ││              mv procursus/jb/* → procursus/           ││ 7. 上传 Sileo 2.5.1 deb (如存在)                      ││ 注: /var/jb 符号链接在首次正常启动时由                 ││     launchdhook.dylib 创建 (Data 卷加密, ramdisk      ││     下不可挂载, 无法在此阶段创建)                      ││                                                        ││ BaseBin Hooks 部署:                                    ││ 1. 清理并重建 /mnt1/cores/                            ││ 2. ldid 重签名所有 dylib (signcert.p12)               ││ 3. SCP 上传到 /mnt1/cores/ (0755)                     ││    dylib 清单:                                         ││      systemhook.dylib   (全局 hook, 所有进程加载)     ││      launchdhook.dylib  (launchd 专用 hook)           ││      libellekit.dylib   (hook 引擎)                   ││ 4. 安装 /b 短别名:                                    ││    cp launchdhook.dylib → /mnt1/b (launchd 加载用)   │└────────────────────────────────────────────────────────┘Phase JB-5: 首次启动 LaunchDaemon 部署┌────────────────────────────────────────────────────────┐│ 1. SCP vphone_jb_setup.sh → /mnt1/cores/             ││ 2. SCP com.vphone.jb-setup.plist →                   ││       /mnt1/System/Library/LaunchDaemons/             ││ 3. 注入 com.vphone.jb-setup 到 launchd.plist         ││    (确保 launchd 在首次正常启动时自动运行)              │└────────────────────────────────────────────────────────┘

Bootstrap 内容物:

/mnt5/<hash>/jb-vphone/procursus/  ├── bin/          # 核心工具 (dpkg, apt, bash, etc.)  ├── sbin/         # 系统工具 (ldid, substrate, etc.)  ├── lib/          # 运行时库 (libapt-pkg, libsubstrate)  ├── Library/      # Cydia Substrate 框架  └── var/          # dpkg 数据库

6.4.2 launchd 注入机制详解

// launchd 加载流程 (iOS 26)dyld 初始化  → 解析 Mach-O 头  → 读取 LC_LOAD_DYLIB 命令 (注入的 /b, 即 launchdhook.dylib 短别名)  → dlopen("/b")    → launchdhook 构造函数执行      → hook launchd 内部函数 (如 _xpc_domain_init, _job_start)      → 拦截所有守护进程启动 → 注入 systemhook.dylib 到子进程环境      → 创建 /var/jb → /private/preboot/<hash>/jb-vphone/procursus 符号链接        (Data 卷在 ramdisk 阶段加密不可访问, 必须在首次正常启动时创建)// jetsam guard 绕过 (必须, 否则 launchd 会 panic)// 原始逻辑: 检测到未授权 dylib 加载 → 触发 jetsam panic// 补丁后: CBZ → B, 跳过 panic 分支 → launchd 正常运行

为什么使用 /b 短别名:launchd 二进制在 LC_CODE_SIGNATURE 被剥离后,Mach-O 加载命令区域空间有限(通常只剩几十字节)。/cores/launchdhook.dylib(27 字节路径)无法容纳,而 /b(2 字节)能完美适配,同时在 /mnt1/b 处放置同名文件。

为什么必须保留原始 entitlements:launchd 持有 spawn、XPC 等特权 entitlement,重签时若使用空白 entitlement 会导致各守护进程的 spawn 操作返回 "operation not permitted"。通过 ldid -e 提取后原样回填,确保重签后权限不变。

6.4.3 Procursus vs Elucubratus 技术选型

┌──────────────┬─────────────────────┬────────────────────────┐│              │ Procursus           │ Elucubratus            │├──────────────┼─────────────────────┼────────────────────────┤│ 维护者       │ CoolStar / Sileo    │ Sam Bingner / BigBoss  ││ 包格式       │ Modern deb (zst压缩)│ Legacy deb (xz/gzip)   ││ 架构         │ arm64 only          │ arm64 + armv7          ││ 依赖管理     │ APT 2.x             │ APT 1.x                ││ Hook 引擎    │ ElleKit (推荐)      │ Cydia Substrate        ││ 兼容性       │ iOS 14+             │ iOS 6+                 ││ 更新频率     │ 高 (活跃开发)       │ 低 (维护模式)          ││ Sileo 支持   │ 原生                │ 需第三方移植           │└──────────────┴─────────────────────┴────────────────────────┘vphone 选择 Procursus 的原因:  • 原生支持 iOS 26 (最新 APT/dpkg)  • 更好的 arm64 优化 (无 armv7 历史包袱)  • 活跃的社区支持 (问题快速修复)  • Sileo GUI 无缝集成 (vs Cydia 需手动移植)

6.4.4 BaseBin Hooks 工作原理

┌─────────────────────────────────────────────────────────────┐│                   BaseBin Hook 调用链                        ││                                                              ││  进程启动                                                    ││      │                                                       ││      ▼                                                       ││  dyld 预加载 systemhook.dylib (通过环境变量)                ││      │                                                       ││      ▼                                                       ││  systemhook 构造函数                                         ││      ├─→ dlopen("libellekit.dylib")  (hook 引擎)           ││      ├─→ 读取 /cores/hooks.plist     (hook 配置)           ││      └─→ ellekit_hook(target_func, replacement_func, ...)  ││                                                              ││  目标函数调用                                                ││      │                                                       ││      ▼                                                       ││  [trampoline] → replacement_func (自定义逻辑)               ││      │            ├─ 前置处理 (日志/权限修改)                ││      │            ├─ call_original() (可选调用原函数)        ││      │            └─ 后置处理 (返回值篡改)                   ││      │                                                       ││      └─→ 原始函数 (或跳过)                                   │└─────────────────────────────────────────────────────────────┘ElleKit vs Cydia Substrate 对比:  ElleKit (现代化, vphone 使用):    • PAC/BTI 兼容 (iOS 14+ 必须)    • 支持 Swift/ObjC/C++ 函数    • 内联 hook (直接修改函数头)    • 轻量级 (单一 dylib)  Cydia Substrate (传统):    • 不完全支持 PAC (iOS 14+ 问题多)    • 主要支持 ObjC 消息    • MSHookFunction API (需额外 libhooker)    • 重量级 (多个依赖库)

6.4.5 首次启动 JB 初始化 (vphone_jb_setup.sh)

Procursus bootstrap 安装在 Preboot 卷(只读挂载,ramdisk 阶段写入),但 Data 卷(/var)在 ramdisk 阶段处于加密状态,无法访问。因此 procursus 的完整激活必须推迟到首次正常启动后由 LaunchDaemon 完成:

LaunchDaemon: com.vphone.jb-setup  程序: /cores/vphone_jb_setup.sh  运行时机: 首次正常启动 (launchd 加载后)  幂等保护: /var/mobile/.vphone_jb_setup_done 标记文件9 步初始化流程 ([0/8] ~ [8/8]):─────────────────────────────────────────────────────────────  0/8  替换 procursus launchctl       procursus 的 launchctl 缺少 _launch_active_user_switch 符号       → 将原始 launchctl 保存为 launchctl.procursus       → ln -sf iosbinpack64/bin/launchctl → JB/usr/bin/launchctl 和 JB/bin/launchctl       (dpkg postinst/prerm 脚本兼容性所需)  1/8  创建 /var/jb 符号链接       /private/var/jb → /private/preboot/<hash>/jb-vphone/procursus  2/8  修复 mobile Library 权限       chown -R 501:501 /var/jb/var/mobile/Library (0755)  3/8  运行 prep_bootstrap.sh       procursus 内置的首次激活脚本 (执行后自删除)  4/8  创建 JB 标记文件       /var/jb/.procursus_strapped       /var/jb/.installed_dopamine  5/8  安装 Sileo       dpkg -i org.coolstar.sileo_2.5.1_iphoneos-arm64.deb       uicache -a (刷新图标)  6/8  APT 初始化       添加 Havoc.app 源       apt-get update       apt-get install libkrw0-tfp0 (内核读写桥接库)       apt-get upgrade  7/8  安装 TrollStore Lite       apt-get install com.opa334.trollstorelite       uicache -a  8/8  SSH Shell 配置       生成 /var/root/.bashrc + .bash_profile       (source /var/jb/etc/profile, 加载完整 JB PATH)─────────────────────────────────────────────────────────────  完成后写入 done marker → 后续重启时跳过 (幂等)

监控方式:首次启动后通过 vphoned 文件浏览器(或 SSH)查看:

tail -f /var/log/vphone_jb_setup.log

6.5 越狱能力矩阵与应用场景

┌──────────────────────────┬──────────────┬────────────────────────────────┐│ 能力                     │ 补丁来源     │ 典型应用场景                    │├──────────────────────────┼──────────────┼────────────────────────────────┤│ 任意代码执行             │ K-AMFI       │ 运行自编译工具/逆向二进制       ││ 调试器附加               │ K-task       │ LLDB/Frida 附加系统进程         ││ 文件系统读写             │ K-Sandbox    │ 修改系统文件/访问隐私数据       ││ IOKit 全面访问           │ K-IOUC       │ GPU/ANE 驱动直接访问            ││ RWX 内存                 │ K-VM         │ JIT 编译器 (V8/JavaScriptCore)  ││ 内核函数调用             │ K-kcall      │ 直接调用内核 API                ││ Root 权限持久化          │ CFW-JB       │ SSH/VNC 守护进程                ││ 包管理系统               │ Procursus    │ apt/dpkg 安装越狱插件           ││ 全局 Hook 注入           │ BaseBin      │ Tweak 开发 (类 Cydia)           ││ 绕过代码签名 (TXM 层)    │ TXM-sel24    │ 加载未签名 dylib                ││ 强制开发者模式           │ TXM-sel41/42 │ 绕过 DeveloperDiskImage 需求    ││ LLDB debugserver 直连    │ JB-3         │ 附加到任意进程无需 task-allow   ││ TrollStore / APT         │ vphone_jb    │ 安装已签名 IPA / apt 包管理     │└──────────────────────────┴──────────────┴────────────────────────────────┘K-XXX:    内核补丁 (kernel_jb.py)TXM-XXX:  TXM 补丁 (txm_dev.py, 在 fw_patch_jb.py 中通过 patch_txm_dev 调用)CFW-JB:   SSH Ramdisk 阶段安装 (cfw_install_jb.sh)JB-N:     CFW JB 安装阶段vphone_jb: 首次启动初始化 (vphone_jb_setup.sh LaunchDaemon)

实战案例

  1. 逆向工程工作流

    make boot  (启动越狱 VM)→ ssh root@localhost -p 22222 (alpine)→ apt install frida-server cycript class-dump→ frida -U -n SpringBoard -l hook.js→ 实时 hook SpringBoard 函数调用
  2. Tweak 开发测试

    编写 Tweak.x (Logos 语法)→ 本地编译 .dylib→ scp 到 VM /Library/MobileSubstrate/DynamicLibraries/→ killall -9 SpringBoard (重启 UI)→ Tweak 自动加载 (通过 systemhook)
  3. 安全研究沙箱

    运行恶意样本 → 完整文件系统访问权限→ 内核级监控 (通过 kcall hook)→ 无风险 (VM 快照隔离)

6.6 越狱稳定性保障机制

1. 幂等设计 (Idempotent Patching)   所有补丁可重复应用, 检测已补丁标记后跳过:if remote_file_exists("/mnt1/sbin/launchd.bak"):       skip_patch()  # 已补丁, 跳过2. 原始文件备份   launchd → launchd.bak (保留原始 entitlements 用于重签)   seputil → seputil.bak   mobileactivationd → mobileactivationd.bak3. SSH Ramdisk 恢复能力   补丁失败 → 重启进 ramdisk → 从 .bak 恢复   rm /mnt1/sbin/launchd; cp launchd.bak launchd4. 动态补丁验证   每个补丁方法返回 True/False   失败补丁打印详细错误 → 不影响其他补丁继续执行   KernelJBPatcher 按计时分组执行, 慢于 10s 的方法打印警告5. 首次启动 done marker   /var/mobile/.vphone_jb_setup_done 存在则跳过 vphone_jb_setup.sh   重置方式: 删除标记文件 → 下次重启重新执行 9 步初始化6. 日志追踪   所有 SSH 命令通过 ssh_cmd() 包装 → 自动重试 3 次   网络断开 → 自动重连机制 (3s 延迟)   首次启动 JB 初始化全程记录到 /var/log/vphone_jb_setup.log

7. Swift 虚拟机运行时

7.1 应用启动流程

sequenceDiagram    participant M as main.swift    participant CLI as VPhoneCLI    participant AD as VPhoneAppDelegate    participant VM as VPhoneVirtualMachine    participant HW as VPhoneHardwareModel    participant CTL as VPhoneControl    participant WC as VPhoneWindowController    M->>CLI: parseOrExit() (同步, 在 runloop 前)    M->>AD: NSApplication.delegate = AppDelegate(cli)    M->>M: app.run() (进入事件循环)    AD->>AD: applicationDidFinishLaunching    AD->>AD: 设置 SIGINT handler (DispatchSource)    AD->>AD: Task { @MainActor startVirtualMachine() }    AD->>VM: VPhoneVirtualMachine(options:)    VM->>HW: createModel() [PV=3, BDID=0x90, ISA=2]    VM->>VM: 配置 15+ 个子系统    VM->>VM: validate() + start(forceDFU:)    alt GUI 模式 (非 DFU)        AD->>CTL: VPhoneControl() → connect(device:)        CTL-->>AD: onConnect(caps)        AD->>WC: 创建窗口 + 工具栏        AD->>AD: 根据 caps 启用位置/IPA 功能    end

7.2 VM 配置架构

VPhoneVirtualMachine.init(options:) 构造器中完成全部 15+ 个子系统的配置:

VZVirtualMachineConfiguration├── 平台配置 (VZMacPlatformConfiguration)│   ├── VPhoneHardwareModel     ← PV=3, BDID=0x90, ISA=2 (私有 API)│   ├── VZMacMachineIdentifier  ← 持久化到磁盘 (稳定 ECID)│   └── VZMacAuxiliaryStorage   ← NVRAM, boot-args 通过私有 API 设置│       └── boot-args: "serial=3 debug=0x104c04"├── 引导加载器 (VZMacOSBootLoader)│   └── _setROMURL()            ← 私有 API 设置自定义 ROM├── CPU: max(用户指定, minimumAllowed)├── 内存: max(用户指定, minimumAllowed)├── 图形: VZMacGraphicsDeviceConfiguration (单显示器)├── 音频: VZVirtioSoundDevice (输入流 + 输出流)├── 存储: VZVirtioBlockDevice + DiskImageAttachment (读写)├── 网络: VZVirtioNetworkDevice + NAT├── 串口: PL011 UART (私有 API)│   ├── stdin → Pipe → VM 串口输入 (后台线程转发)│   └── VM 串口输出 → Pipe → stdout├── 触摸屏: _VZUSBTouchScreenConfiguration (私有 API)├── 键盘: VZUSBKeyboardConfiguration├── Vsock: VZVirtioSocketDevice (端口 1337 → VPhoneControl)├── GDB 调试桩 (私有 API, 系统分配端口)└── SEP 协处理器 (私有 API)    ├── SEP Storage + SEP ROM    └── 独立 GDB 调试桩

7.3 私有 API 访问模式

所有私有 API 通过 Dynamic 库以运行时消息分发调用,无需 ObjC 桥接:

                 Dynamic 库 (mhdhejazi/Dynamic)                 运行时动态方法调用                        │    ┌───────────────────┼───────────────────────┐    │                   │                       │    ▼                   ▼                       ▼ 类实例化            属性设置               方法调用 Dynamic._VZ...()   Dynamic(obj)          Dynamic(obj)                      ._setProp(val)        .method(args) 使用场景: ┌────────────────────────────────────────────────────────┐ │ _VZMacHardwareModelDescriptor    → PV=3 硬件模型       │ │ _setROMURL                      → 自定义 ROM           │ │ _VZPL011SerialPortConfiguration → PL011 串口           │ │ _VZUSBTouchScreenConfiguration  → USB 触摸屏           │ │ _setDebugStub / _VZGDBDebugStubConfiguration → GDB    │ │ _VZSEPCoprocessorConfiguration  → SEP 协处理器         │ │ _setForceDFU / _setStopInIBoot → 启动模式控制          │ │ _setDataValue (NVRAM)           → boot-args 设置       │ └────────────────────────────────────────────────────────┘ 前置条件:   macOS 15+ (Sequoia) + SIP 禁用 + AMFI 禁用   Entitlements: (entitlements & 0x12) != 0     bit 1: com.apple.private.virtualization     bit 4: com.apple.private.virtualization.security-research

8. Host-Guest 控制协议

8.1 协议规范

传输层: VirtIO Socket (vsock), 端口 1337帧格式: [uint32 BE 长度][UTF-8 JSON 载荷]最大消息: 4 MB消息字段:"v"  : 协议版本 (当前 = 1)"t"  : 消息类型 (字符串)"id" : 请求 ID (十六进制, 响应中回显)

8.2 连接握手与自动更新

sequenceDiagram    participant H as Host (VPhoneControl)    participant G as Guest (vphoned)    H->>H: 加载 .vphoned.signed, 计算 SHA-256    H->>G: vsock connect(port: 1337)    H->>G: {"v":1, "t":"hello", "bin_hash":"<sha256>"}    G->>G: 计算自身 SHA-256, 比对    G->>H: {"v":1, "t":"hello", "name":"vphoned", "caps":[...], "need_update":true/false}    alt need_update = true        H->>G: {"t":"update", "size": N}        H->>G: [N 字节原始二进制数据] (非 JSON 帧, 内联传输)        G->>G: 写入 /var/root/Library/Caches/vphoned        G->>H: {"t":"ok"}        G->>G: exit(0) → launchd 重启 → execv 新二进制        Note over H,G: 3 秒后自动重连    end    H->>H: startReadLoop() + onConnect(caps)

8.3 消息类型一览

┌────────────────┬───────────┬──────────────────────────────────────────┐│ 消息类型        │ 方向       │ 说明                                      │├────────────────┼───────────┼──────────────────────────────────────────┤│ hello          │ 双向       │ 握手 (含 bin_hash, caps, need_update)     ││ update         │ Host→Guest│ 头帧 + 原始二进制流 (上限 10 MB)          ││ hid            │ Host→Guest│ HID 按键 (page/usage/down)               ││ ping / pong    │ 双向       │ 心跳探活                                  ││ version        │ 请求/响应   │ Guest 版本查询                            ││ devmode        │ 请求/响应   │ 开发者模式状态/启用 (XPC)                 ││ location       │ Host→Guest│ GPS 注入 (lat/lon/alt/accuracy/speed)     ││ location_stop  │ Host→Guest│ 停止位置模拟                              ││ file_list      │ 请求/响应   │ 列目录                                    ││ file_get       │ 请求/响应   │ 下载文件 (响应含内联二进制)               ││ file_put       │ Host→Guest│ 上传文件 (头帧 + 二进制流)                ││ file_mkdir     │ Host→Guest│ 创建目录                                  ││ file_delete    │ Host→Guest│ 删除文件/目录                             ││ file_rename    │ Host→Guest│ 重命名                                    ││ ipa_install    │ 请求/响应   │ IPA/TIPA 安装 (path/cert_path/registration → vphoned_install MCMAppContainer) ││ ok / err       │ Guest→Host│ 通用成功/错误响应                         │└────────────────┴───────────┴──────────────────────────────────────────┘

8.4 请求-响应模型

Host 端 (VPhoneControl.swift)sendRequest(_:)    │ 分配唯一 hex id    │ withCheckedThrowingContinuation    ▼pendingRequests[id] = continuation     ← NSLock 保护    │    │ 写入 [uint32 长度][JSON{v,t,id,...}]    ▼startReadLoop (后台线程)    │ 循环读取帧 → JSON 解析    │ 取出 id → 查找 pendingRequests[id]    │ resume(returning: response)    ▼调用者 await 获得响应断连处理:    读循环结束 → disconnect()    → fail 所有 pending requests (VPhoneError.disconnected)    → 通知 onDisconnect    → 如果之前已连接 → 3 秒后自动重连

9. Guest Daemon 架构

9.1 vphoned 总览

Objective-C 编写的 LaunchDaemon,运行在 iOS 虚拟机内部:

vphoned (Objective-C)├── vphoned.m              主循环: vsock 监听, 消息分发, 自动更新├── vphoned_protocol.{h,m} 帧协议: 长度前缀 JSON, 4MB 限制├── vphoned_hid.{h,m}      HID 按键注入 (IOHIDEvent)├── vphoned_devmode.{h,m}  开发者模式 (XPC)├── vphoned_location.{h,m} GPS 模拟 (CLLocationManager)├── vphoned_files.{h,m}    文件操作 (list/get/put/mkdir/delete/rename)├── vphoned_install.{h,m}  IPA/TIPA 安装 (ipa_install: MCMAppContainer + LSApplicationWorkspace)├── unarchive.{h,m}        libarchive 解压封装 (IPA/TIPA ZIP 解包)├── vendor/libarchive/      vendored libarchive 静态库├── vphoned.plist           LaunchDaemon 配置├── entitlements.plist      权限声明└── signcert.p12            签名证书

9.2 自动更新热替换

main() 启动    │    ▼检查 /var/root/Library/Caches/vphoned 是否存在    ├── 存在 → execv() 切换到缓存二进制 (热替换)    └── 不存在 → 继续正常启动    │    ▼AF_VSOCK 监听端口 1337    │    ▼ accept()握手: 比对 bin_hash    ├── 不匹配 → 接收新二进制 → 写入缓存 → exit(0)    │            launchd 自动重启 → execv 新版本    └── 匹配 → 进入消息循环

9.3 IPA 安装流水线

┌─────────────────────────────────────────────────────────────┐│  Host: VPhoneControl.installIPA(localURL:)                  ││    1. 读取本地 IPA / TIPA → 内存                             ││    2. 创建远端目录 /var/mobile/Documents/vphone-installs/   ││    3. uploadFile → <remoteDir>/<UUID>-<filename>.ipa        ││    4. 读取本地 signcert.p12 → 上传为 <UUID>-signcert.p12   ││    5. 发送 ipa_install 命令                                  ││       {"t":"ipa_install""path":..., "cert_path":...,      ││        "registration":"User"}                               ││                                                             ││  错误处理: Guest 返回 "unknown type: ipa_install"           ││    → 抛出错误 (提示用户更新 Guest daemon)                    ││    → 不降级到旧接口                                          │└──────────────────────────┬──────────────────────────────────┘                           │ vsock                           ▼┌─────────────────────────────────────────────────────────────┐│  Guest: vphoned_install.m — vp_handle_custom_install()      ││                                                             ││  前置检查:                                                   ││    vp_custom_installer_available()                          ││      → MCMAppContainer + LSApplicationWorkspace 均可用?     ││    vp_find_ldid_path() → Guest 侧 ldid 可执行文件位置       ││                                                             ││  Stage 1: Extract (vendored libarchive)                     ││    vp_extract_package_to_directory()                        ││    libarchive 解压 ZIP → /tmp/<UUID>/                       ││    (路径遍历防护 + NULL 路径名守卫)                           ││                                                             ││  Stage 2: Install (MCM + LS)                                ││    vp_install_app_from_package()                            ││    ├─ 签名: ldid -S (Guest 侧重签)                          ││    │   cert_path 存在时使用上传的 p12 证书                   ││    ├─ MCMAppContainer: 分配 App 沙箱容器                    ││    │   containerWithIdentifier:createIfNecessary:            ││    ├─ 注册: LSApplicationWorkspace                          ││    │   registerApplicationDictionary:                        ││    └─ 清理: 删除临时目录 + IPA + 证书文件                   ││                                                             ││  返回: {"t":"ok""msg":"Installed via built-in installer   ││         as User: <bundleId>"}                               │└─────────────────────────────────────────────────────────────┘

能力检测:握手响应 caps 数组中包含 "ipa_install" 时,Host 才展示安装入口。若 Guest daemon 过旧不支持此消息类型,返回错误并提示用户重连更新 daemon。


10. GUI 与交互系统

10.1 窗口与输入架构

┌────────────────────────────────────────────────────────────┐│  NSApplication                                              ││  ├── VPhoneAppDelegate (中央编排器)                          ││  │     持有: VM, Control, WindowCtrl, MenuCtrl,             ││  │           FileWindowCtrl, LocationProvider                ││  │                                                          ││  ├── VPhoneWindowController                                 ││  │     ├── NSWindow (VM 屏幕尺寸 / 缩放因子)               ││  │     │   └── 宽高比锁定, capturesSystemKeys               ││  │     ├── NSToolbar [Home 按钮]                            ││  │     └── 状态轮询 (2s 定时器 → subtitle 更新)             ││  │                                                          ││  ├── VPhoneVirtualMachineView (继承 VZVirtualMachineView)   ││  │     ├── 鼠标事件 → 触摸注入 (macOS 15: NSClassFromString ││  │     │    + KVC 手工构造触摸对象; macOS 16+: 原生支持)     ││  │     ├── 坐标归一化: 鼠标位置 → [0,1] 标准化              ││  │     ├── 边缘检测 (32px 阈值): iOS 手势模拟              ││  │     │   上滑=Home栏, 下拉=通知中心, 左/右=控制中心       ││  │     ├── 右键 → Home 键                                   ││  │     └── Cmd+H → Home 键                                  ││  │                                                          ││  └── VPhoneMenuController                                   ││        ├── Keys:     Home / Power / Vol Up / Vol Down       ││        ├── Type:     剪贴板 → 逐字符键入                    ││        ├── Connect:  File Browser / DevMode / Ping / Version ││        ├── Install:  IPA/TIPA 安装                          ││        ├── Location: 主机 GPS → Guest 同步 (toggle)         ││        └── Record:   屏幕录制 (toggle)                      │└────────────────────────────────────────────────────────────┘

10.2 macOS 版本兼容性与触屏交互差异

虚拟 iPhone 的触屏交互在不同 macOS 版本间存在显著差异,这是一个影响用户体验的关键兼容性问题:

┌────────────────────────────────────────────────────────────────────┐│  macOS 版本兼容性矩阵                                               ││                                                                     ││  macOS 15 (Sequoia):                                                ││    ├── 触屏: VZVirtualMachineView 不原生支持触摸事件                 ││    │   → 必须重写鼠标事件函数 (mouseDown/mouseDragged/mouseUp)       ││    │   → 通过 NSClassFromString + KVC 手工构造 _VZTouch 对象         ││    │   → 鼠标坐标归一化到 [0,1] 后注入为触摸事件                     ││    ├── 边缘手势: 32px 阈值检测                                       ││    │   上边缘下拉 = 通知中心, 下边缘上滑 = Home 栏                   ││    │   左/右边缘 = 控制中心                                          ││    └── 已验证: Apple M3 16GB, Sequoia 15.7.4                        ││                                                                     ││  macOS 16 (Tahoe):                                                  ││    ├── 触屏: VZVirtualMachineView 原生支持触摸事件                   ││    │   → _VZMultiTouchEvent 私有 API 可直接使用                      ││    │   → 代码中通过 #available(macOS 16, *) 条件编译                 ││    └── 已验证: Apple M1 Pro 32GB, Tahoe 26.3                        ││                                                                     ││  兼容性要求:                                                         ││    ├── 必须: Apple Silicon Mac (ARM64)                               ││    ├── 必须: SIP 禁用 + AMFI 禁用                                   ││    ├── 必须: 支持 pccvre 的目标设备                                  ││    └── entitlements: com.apple.private.virtualization                ││                    + com.apple.private.virtualization.security-research│└────────────────────────────────────────────────────────────────────┘

10.3 文件浏览器 (SwiftUI + AppKit 混合)

graph TB    subgraph "AppKit 层"        FWC["VPhoneFileWindowController<br/>NSWindow 700x500"]    end    subgraph "SwiftUI 层"        FBV["VPhoneFileBrowserView<br/>Table + Toolbar + ContextMenu<br/>搜索 / 拖放 / 进度遮罩"]    end    subgraph "ViewModel 层"        FBM["VPhoneFileBrowserModel<br/>@Observable @MainActor<br/>files / pathHistory / transfer"]    end    subgraph "数据模型"        RF["VPhoneRemoteFile<br/>struct, Identifiable<br/>name / type / size / perm / mtime"]    end    subgraph "通信层"        CTL["VPhoneControl<br/>vsock RPC"]    end    FWC -->|"NSHostingView"| FBV    FBV -->|"绑定"| FBM    FBM -->|"解析"| RF    FBM -->|"异步调用"| CTL    CTL -->|"vsock:1337"| GD["vphoned<br/>file_list / file_get / file_put"]

功能特性:

  • Table 视图:图标 / 名称 / 权限(等宽) / 大小 / 修改时间,支持排序和多选
  • 导航:路径历史栈 + 面包屑导航 + 前进后退
  • 文件操作:上传 / 下载(递归) / 新建文件夹 / 删除 / 重命名
  • 传输进度:全屏模糊遮罩 + 进度条 + 文件名 + 字节计数
  • 拖放支持:Finder → 窗口直接上传

10.4 位置转发

Mac 主机 CLLocationManager    │ requestAlwaysAuthorization()    │ startUpdatingLocation()    ▼LocationDelegateProxy (避免 @MainActor 隔离冲突)    │ didUpdateLocations    ▼VPhoneLocationProvider.forward(location:)    │ 缓存 lastLocation    │ 检查 control.isConnected    ▼VPhoneControl.sendLocation(    latitude, longitude, altitude,    horizontalAccuracy, verticalAccuracy,    speed, course)    │ vsock {"t":"location", ...}    ▼vphoned_location.m → CLLocationManager 注入

11. 构建系统

11.1 Makefile 目标依赖图

graph TB    subgraph "安装"        SM["setup_machine<br/>全自动安装"]        ST["setup_tools<br/>工具链安装"]    end    subgraph "构建"        B["build<br/>Swift compile + codesign"]        BU["bundle<br/>.app 打包"]        VD["vphoned<br/>iOS arm64 交叉编译"]    end    subgraph "固件流水线"        FP["fw_prepare"]        FPA["fw_patch"]        FPJ["fw_patch_jb"]    end    subgraph "恢复/Ramdisk"        RS["restore_get_shsh"]        RE["restore"]        RB["ramdisk_build"]        RD["ramdisk_send"]    end    subgraph "CFW"        CI["cfw_install"]        CJ["cfw_install_jb"]    end    subgraph "VM 管理"        VN["vm_new"]        BO["boot"]        BD["boot_dfu"]    end    SM --> ST    BU --> B    BO --> BU    BO --> VD    BD --> B    FP --> FPA    FPA --> FPJ    style SM fill:#1a1a1a,stroke:#4ade80,color:#e0e0e0    style BO fill:#1a1a1a,stroke:#60a5fa,color:#e0e0e0    style FPA fill:#1a1a1a,stroke:#fbbf24,color:#e0e0e0

11.2 关键变量

变量
默认值
说明
VM_DIRvm
VM 工作目录
CPU8
虚拟机 CPU 核数
MEMORY4096
内存 (MB)
DISK_SIZE64
磁盘大小 (GB)
CFW_INPUTcfw_input
CFW 输入资源
BOOT_ARGS
(空)
额外启动参数 (如 --install-ipa)

11.3 SwiftPM 依赖

版本
用途
swift-argument-parser
>= 1.3.1
CLI 参数解析
Dynamic
 (mhdhejazi)
>= 1.2.0
私有 API 运行时调用

系统框架:Virtualization / AppKit / SwiftUI / CoreLocation / AVFoundation

Python 工具链:capstone (反汇编) / keystone-engine (汇编) / pyimg4 (IM4P 处理)


12. 技术风险与未来挑战

12.1 Apple 组件移除风险

整个项目的基石是 cloudOS (PCC) 固件中包含的 vphone600ap 组件。这些组件可能是:

  • Apple 有意为之:计划向安全研究者提供虚拟 iPhone 环境(类似已有的 PCC 研究 VM)
  • 意外泄露:类似 2021 年 iOS 15 beta 中 DEVELOPMENT/KASAN 内核被包含约 4 个月的先例

如果 Apple 在未来 cloudOS 版本中移除这些组件,项目将冻结在最后一个可用固件版本上,无法跟随 iOS 新版本更新。

12.2 私有 API 稳定性

项目深度依赖 Virtualization.framework 的 10+ 个私有 API(通过 Dynamic 库运行时调用):

风险等级评估:  高风险 (API 签名或语义可能变化):    _VZMacHardwareModelDescriptor    → 硬件模型创建的核心    _setROMURL                       → 自定义 BootROM 的唯一途径    _VZSEPCoprocessorConfiguration   → SEP 模拟的唯一途径    _setForceDFU / _setStopInIBoot   → DFU 模式启动控制  中风险 (API 较稳定但仍为私有):    _VZPL011SerialPortConfiguration  → 串口调试    _VZUSBTouchScreenConfiguration   → 触摸输入 (macOS 16 已部分公开)    _VZGDBDebugStubConfiguration     → 内核调试  低风险 (趋向公开):    VZVirtualMachineView 触摸支持    → macOS 16 已原生支持

每次 macOS 大版本升级都可能导致私有 API 变更。项目的 Dynamic 库调用模式虽然避免了编译时绑定,但运行时仍可能因方法签名变化而崩溃。

12.3 Entitlement 与安全策略

运行 vphone-cli 需要 禁用 SIP + AMFI,这是因为:

  • 需要 com.apple.private.virtualization entitlement(正常情况下仅 Apple 自身二进制持有)
  • 需要 com.apple.private.virtualization.security-research entitlement
  • 自签名二进制在 AMFI 启用时无法加载这些受限 entitlement

Apple 可能在未来通过更严格的 entitlement 验证(如要求 PPL 保护的签名链)进一步限制此类用途,即使 SIP/AMFI 被禁用也无法运行。

12.4 固件版本耦合

尽管动态补丁系统实现了"零硬编码偏移",但仍存在隐式耦合:

已知耦合点:  ├── ADRP+ADD 指令模式假设  │   如果 Apple 编译器切换到不同的寻址模式 (如 ADRP+LDR)  │   → ADRP 索引将无法定位目标  │  ├── 字符串锚点依赖  │   如 "@%s:%d" (panic格式)、"Sandbox" (MACF策略名)  │   如果字符串被修改或移除 → 补丁定位失败  │  ├── 结构体布局假设  │   mac_policy_conf 结构的字段偏移  │   Mach-O 段名称和布局  │   如果内核结构体布局变化 → 解析出错  │  └── Cryptex AEA 加密格式      依赖 ipsw 工具解密 AEA → 如果 Apple 更换加密方案      → Cryptex 提取流程中断

12.5 GPU 驱动的逆向维护成本

Metal GPU 加速依赖从 PCC dsc 逆向实现的 libAppleParavirtCompilerPluginIOGPUFamily.dylib。每次 iOS/cloudOS 版本更新可能带来:

  • Metal shader 编译器接口变化
  • GPU 命令提交协议版本升级
  • 驱动 bundle 内部依赖变化

这意味着该 dylib 可能需要随每个主要版本重新逆向和适配,是长期维护成本最高的单一组件。

12.6 IPSW 版本匹配约束

混合固件要求 iPhone IPSW 和 cloudOS IPSW 的构建版本号 (Build Number) 必须匹配(如都为 23B85)。这是因为:

  • 内核与用户空间的 syscall 接口必须版本一致
  • Cryptex DMG 中的 dyld_shared_cache 与内核期望的 ABI 必须匹配
  • 设备树中的属性与对应固件组件必须兼容

如果 Apple 在某个版本中仅更新 iPhone IPSW 而不同步更新 cloudOS IPSW(反之亦然),将出现无法构建有效混合固件的空窗期。


附录 A: 启动链数据流

AVPBooter (ROM, 补丁: DGST 绕过)  │  ▼LLB (cloudOS, 补丁: 串口+Image4+boot-args+rootfs+panic)  │  ▼iBSS (cloudOS, 补丁: 串口+Image4)       ← DFU 入口  │  ▼iBEC (cloudOS, 补丁: 串口+Image4+boot-args)  │  ▼SPTM (cloudOS, 无补丁) + TXM (cloudOS, 补丁: 信任缓存绕过)  │  ▼KernelCache (cloudOS vphone600, 补丁: 26 处)  │  ├──── 正常启动 ────→ iOS 用户空间 (iPhone, CFW 补丁)  │                      ├── vphoned (vsock daemon)  │                      ├── dropbear (SSH :22222)  │                      ├── trollvnc (VNC :5901)  │                      └── bash (控制台)  │  └──── Ramdisk 启动 ──→ SSH Ramdisk (cloudOS)                           └── 用于 cfw_install 写入文件系统

附录 B: 安全绕过点汇总

┌──────────────────────────┬────────────────────────────────────────────────┐│ 安全机制                  │ 绕过方式                                        │├──────────────────────────┼────────────────────────────────────────────────┤│ Image4 签名验证           │ iBSS/iBEC/LLB: Image4 回调 NOP                 ││ DGST 验证                │ AVPBooter: mov x0, #0                          ││ APNonce 生成 (JB)        │ iBSS JB: tbz/tbnz w0,#0 → b (跳过 nonce 生成) ││ TXM 信任缓存             │ TXM base: 哈希比较 BL → mov x0, #0             ││ TXM CS 代码签名验证       │ TXM sel24: mov w0,#0xa1; b epilogue (PASS 短路)││ get-task-allow entitlement│ TXM sel41: BL → mov x0, #1                    ││ debugger entitlement      │ TXM sel42|29: shellcode + BL → mov w0, #1     ││ 开发者模式               │ TXM init: TBNZ w9,#0 → NOP                     ││ APFS 密封卷              │ Kernel: 根快照/密封/认证 3 处 NOP               ││ APFS 根哈希              │ Kernel: apfs_graft validate → mov w0, #0       ││ 启动约束                 │ Kernel: launch_constraints → mov w0,#0; ret     ││ 代码签名后验证            │ Kernel: TXM CS + AMFI → NOP / cmp w0,w0       ││ AMFI 信任缓存 (JB)       │ Kernel: amfi_cdhash_in_trustcache → mov x0,#1; ret ││ IOUC MACF gate (JB)      │ Kernel: CBZ W0 → B allow (IOKit open 绕过)     ││ dyld 策略                │ Kernel: check_dyld_policy → mov w0, #1         ││ 调试器检测               │ Kernel: PE_i_can_has_debugger → mov x0, #1     ││ Sandbox MACF 钩子        │ Kernel JB: 10 个 hook → mov x0, #0; ret        ││ 读写挂载                 │ Kernel: mount_upgrade_checks 绕过               ││ task_for_pid (JB)        │ Kernel JB: NOP ldr w,[task,#0x490]              ││ vm_protect W^X (JB)      │ Kernel JB: NOP 权限检查分支 → RWX 内存          ││ rootvp auth (JB)         │ Kernel JB: _bsd_init cbnz → NOP               ││ launchd 缓存验证         │ CFW: launchd_cache_loader NOP                  ││ 设备激活锁               │ CFW: mobileactivationd → 返回 YES               ││ Jetsam Panic 保护 (JB)   │ CFW JB-1: launchd 条件分支 → 无条件跳转         ││ debugserver 沙盒 (JB)    │ CFW JB-3: 移除 seatbelt-profiles + task-allow   ││ Gigalocker UUID          │ CFW: seputil "/%s.gl" → "/AA.gl"               │└──────────────────────────┴────────────────────────────────────────────────┘