利用 PCC 固件中的 VPHONE600AP 组件构建虚拟 iPhone 完整复现指南

利用 PCC 固件中的 VPHONE600AP 组件构建虚拟 iPhone 完整复现指南

原文: wh1te4ever/super-tart-vphone-writeup

本文档基于原始 writeup 整理为可落地复现的中文操作手册。


目录

  1. 背景与动机
  2. 前置要求
  3. 整体架构概览
  4. 第一阶段: 修改 super-tart 以启动虚拟 iPhone
  5. 第二阶段: 构建混合固件
  6. 第三阶段: 补丁 AVPBooter (BootROM)
  7. 第四阶段: 修改并编译 libirecovery
  8. 第五阶段: 补丁固件组件
  9. 第六阶段: 恢复固件
  10. 第七阶段: SSH Ramdisk 修复启动
  11. 第八阶段: 安装 Cryptex 与系统修补
  12. 第九阶段: 实现 Metal GPU 加速
  13. 第十阶段: Sequoia 上启用触摸交互
  14. 兼容性
  15. 常见问题排查
  16. 参考项目与工具链

1. 背景与动机

2024 年底,Apple 推出 Private Cloud Compute (PCC)。2025 年底,有人发现 Apple 在 cloudOS 26 的 PCC 固件中新增了 vphone600ap 相关组件——一个 “iPhone Research Environment Virtual Machine”

2026 年 1 月,@_inside 展示了利用这些组件成功启动虚拟 iPhone 的推文。与 QEMUAppleSilicon (Inferno) 相比,运行更加流畅,甚至支持 Metal 加速。

本文档完整复现 wh1te4ever 的构建流程。


2. 前置要求

2.1 硬件

项目 要求
处理器 Apple Silicon (M1/M2/M3/M4 系列)
内存 建议 16GB+(32GB 更佳)
磁盘 至少 100GB 可用空间

2.2 软件环境

项目 说明
macOS Sequoia 15.x 或 Tahoe 26.x
SIP 必须禁用 (System Integrity Protection)
AMFI 必须禁用
Xcode 最新版(用于编译 Swift 项目)
Python 3 用于运行固件处理脚本

2.3 禁用 SIP 和 AMFI

# 重启进入 Recovery 模式 (开机长按电源键)
# 在终端中执行:
csrutil disable
# 设置 boot-args 禁用 AMFI:
nvram boot-args="amfi_get_out_of_my_way=1"
reboot

2.4 必需工具

工具 来源 用途
super-tart GitHub 修改后的 tart VM,支持 DFU/自定义 BootROM
img4 GitHub IMG4/IM4P 处理
img4tool GitHub IM4P 创建
pyimg4 PyPI Python IMG4 处理库
idevicerestore GitHub 固件恢复
libirecovery wh1te4ever fork DFU 通信(已修改支持 vresearch101ap)
iproxy GitHub USB 端口转发
ldid GitHub 代码签名
trustcache GitHub TrustCache 创建
ipsw GitHub IPSW/AEA 处理
IDA Pro Hex-Rays 二进制逆向(补丁定位)

2.5 安装 Python 依赖

pip3 install pyimg4

2.6 固件下载

固件 版本 来源
cloudOS 26.1 23B85 PCC 固件(含 vphone 组件)
iOS 26.1 23B85 (iPhone17,3) ipsw.me

3. 整体架构概览

┌─────────────────────────────────────────────────────────────────┐
│                        整体流程                                  │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  1. 修改 super-tart ──→ 支持 vresearch101 硬件模型              │
│           │                                                     │
│  2. 混合固件 ──→ cloudOS 26.1 + iOS 26.1 组件                   │
│           │                                                     │
│  3. 补丁 AVPBooter ──→ 绕过 image4 签名验证                     │
│           │                                                     │
│  4. 修改 libirecovery ──→ 支持 vresearch101ap 模型              │
│           │                                                     │
│  5. 补丁固件组件 ──→ iBSS/iBEC/LLB/TXM/kernelcache             │
│           │                                                     │
│  6. 恢复固件 ──→ DFU 模式 + idevicerestore                      │
│           │                                                     │
│  7. SSH Ramdisk ──→ 修复 Cryptex 缺失问题                       │
│           │                                                     │
│  8. 安装 Cryptex + 系统修补 ──→ 注入 dyld_shared_cache 等       │
│           │                                                     │
│  9. Metal 支持 ──→ AppleParavirtGPUMetalIOGPUFamily.bundle      │
│           │                                                     │
│ 10. 触摸支持 ──→ VZVirtualMachineView 鼠标事件重写               │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

启动链 (Boot Chain)

AVPBooter (BootROM)
    └──→ iBSS (DFU 模式)
          └──→ iBEC
                └──→ LLB (正常启动)
                      └──→ SPTM + TXM + kernelcache
                            └──→ launchd → iOS 用户空间

4. 第一阶段: 修改 super-tart 以启动虚拟 iPhone

4.1 核心原理

Apple 的 security-pcc 项目对应 /System/Library/SecurityResearch/usr/bin/vrevm 二进制,使用 Virtualization.framework私有 API 来初始化硬件模型。关键参数:

  • PlatformVersion: 3 (.appleInternal4)
  • BoardID: 0x90
  • ISA: 2
  • BootROM: AVPBooter.vresearch1.bin
  • SEPROM: AVPSEPBooter.vresearch1.bin
  • 显示分辨率: 1179x2556 (iPhone 15 Pro 级别)

4.2 克隆并修改 super-tart

git clone https://github.com/JJTech0130/super-tart
cd super-tart

4.3 修改 /Sources/tart/VM.swift

VM 类中添加 vresearch101 硬件模型初始化函数:

class VM: NSObject, VZVirtualMachineDelegate, ObservableObject {

  // vresearch101 硬件模型配置
  static private func vzHardwareModel_VRESEARCH101() throws -> VZMacHardwareModel {
    var hw_model: VZMacHardwareModel

    guard let hw_descriptor = _VZMacHardwareModelDescriptor() else {
      fatalError("Failed to create hardware descriptor")
    }
    hw_descriptor.setPlatformVersion(3) // .appleInternal4 = 3
    hw_descriptor.setBoardID(0x90)
    hw_descriptor.setISA(2)
    hw_model = VZMacHardwareModel._hardwareModel(withDescriptor: hw_descriptor)

    guard hw_model.isSupported else {
        fatalError("VM hardware config not supported (model.isSupported = false)")
    }

    return hw_model
  }
  // ...
}

4.4 修改 craftConfiguration 方法

craftConfiguration 方法中配置以下关键部分:

4.4.1 Boot Loader + ROM

let bootloader = try vmConfig.platform.bootLoader(nvramURL: nvramURL)
Dynamic(bootloader)._setROMURL(romURL)
configuration.bootLoader = bootloader

4.4.2 SEP 协处理器配置

let homeURL = FileManager.default.homeDirectoryForCurrentUser
var sepstoragePath = homeURL.appendingPathComponent(".tart/vms/vphone/SEPStorage").path
let sepstorageURL = URL(fileURLWithPath: sepstoragePath)
let sep_config = Dynamic._VZSEPCoprocessorConfiguration(storageURL: sepstorageURL)
if let sepromURL {
    sep_config.romBinaryURL = sepromURL
}
sep_config.debugStub = Dynamic._VZGDBDebugStubConfiguration(port: 8001)
configuration._setCoprocessors([sep_config.asObject])

重要: SEP 配置不正确会导致 kernel panic。SEPStorage 文件路径必须正确。

4.4.3 平台配置

let pconf = VZMacPlatformConfiguration()
pconf.hardwareModel = try vzHardwareModel_VRESEARCH101()

let serial = Dynamic._VZMacSerialNumber.initWithString("AAAAAA1337")
let identifier = Dynamic.VZMacMachineIdentifier._machineIdentifierWithECID(
    0x1111111111111111, serialNumber: serial.asObject
)
pconf.machineIdentifier = identifier.asObject as! VZMacMachineIdentifier
pconf._setProductionModeEnabled(true)

var auxiliaryStoragePath = homeURL.appendingPathComponent(".tart/vms/vphone/nvram.bin").path
let auxiliaryStorageURL = URL(fileURLWithPath: auxiliaryStoragePath)
pconf.auxiliaryStorage = VZMacAuxiliaryStorage(url: auxiliaryStorageURL)

configuration.platform = pconf

4.4.4 键盘与触摸屏

if #available(macOS 14, *) {
  let keyboard = VZUSBKeyboardConfiguration()
  configuration.keyboards = [keyboard]
}

if #available(macOS 14, *) {
  let touch = _VZUSBTouchScreenConfiguration()
  configuration._setMultiTouchDevices([touch])
}

4.4.5 显示配置

let graphics_config = VZMacGraphicsDeviceConfiguration()
let displays_config = VZMacGraphicsDisplayConfiguration(
    widthInPixels: 1179,
    heightInPixels: 2556,
    pixelsPerInch: 460
)
graphics_config.displays.append(displays_config)
configuration.graphicsDevices = [graphics_config]

4.5 创建 VM 目录结构

mkdir -p ~/.tart/vms/vphone
# 需要在此目录下创建以下文件:
# - SEPStorage     (SEP 存储)
# - nvram.bin      (NVRAM / AuxiliaryStorage)
# - disk.img       (虚拟磁盘)

4.6 编译 super-tart

cd super-tart
swift build -c release

5. 第二阶段: 构建混合固件

5.1 原理

需要将 cloudOS 26.1 (23B85)iOS 26.1 (iPhone17,3; 23B85) 的组件混合。

来源分配:

来源 组件
iOS 26.1 (iPhone 16) SystemVolume, SystemVolumeCanonicalMetadata, OS, StaticTrustCache, RestoreTrustCache, RestoreRamDisk
cloudOS 26.1 (PCC) kernelcache, agx, all_flash, ane, dfu, pmp, sptm, txm 等其余所有

5.2 提取与混合脚本 (get_fw.py)

import os

# 1. 下载并解压 iOS 26.1 IPSW (iPhone17,3)
os.system("mkdir -p iPhone17,3_26.1_23B85_Restore")
# 从 ipsw.me 下载并解压到 iPhone17,3_26.1_23B85_Restore/

# 2. 下载并解压 cloudOS 26.1 PCC 固件
# 解压后的 hash 目录名示例:
# 399b664dd623358c3de118ffc114e42dcd51c9309e751d43bc949b98f4e31349_extracted/

# 3. 从 cloudOS 导入 vphone 相关组件
CLOUDOS_DIR = "399b664dd623358c3de118ffc114e42dcd51c9309e751d43bc949b98f4e31349_extracted"
RESTORE_DIR = "iPhone17,3_26.1_23B85_Restore"

# kernelcache
os.system(f"cp {CLOUDOS_DIR}/kernelcache.* {RESTORE_DIR}")

# 固件子目录
for subdir in ["agx", "all_flash", "ane", "dfu", "pmp"]:
    os.system(f"cp {CLOUDOS_DIR}/Firmware/{subdir}/* {RESTORE_DIR}/Firmware/{subdir}")

# sptm, txm 等 im4p 文件
os.system(f"cp {CLOUDOS_DIR}/Firmware/*.im4p {RESTORE_DIR}/Firmware")

# 4. 使用已修改好的 BuildManifest.plist 和 Restore.plist
os.system(f"sudo cp custom_26.1/BuildManifest.plist {RESTORE_DIR}")
os.system(f"sudo cp custom_26.1/Restore.plist {RESTORE_DIR}")

print("Done, grabbed all needed components for restoring")

5.3 修改 BuildManifest.plist

Manifest 键下的字典元素中:

  • 使用 iOS 26.1 (iPhone 16) 的组件: SystemVolume, SystemVolumeCanonicalMetadata, OS, StaticTrustCache, RestoreTrustCache, RestoreRamDisk
  • 使用 PCC 固件 vphone 相关文件: 其余所有项

仓库中提供了最终修改好的文件: BuildManifest.plist

5.4 修改 Restore.plist

  • 添加 DeviceMap 相关属性或 SupportedProductTypes
  • 修改 SystemRestoreImageFileSystems 元素

仓库中提供了最终修改好的文件: Restore.plist


6. 第三阶段: 补丁 AVPBooter (BootROM)

6.1 定位 image4_validate_property_callback

在 IDA Pro 中打开 AVPBooter.vresearch1.bin:

文件路径: /System/Library/Frameworks/Virtualization.framework/Resources/AVPBooter.vresearch1.bin
  1. 使用 “Text-search (slow!)” 搜索字符串 0x4447
  2. 找到包含该引用的函数(即 image4_validate_property_callback
  3. 在该函数的尾声 (epilogue) 处补丁,使其始终返回 0

6.2 补丁方法

参考 steven-michaud 的 gist,在函数返回前插入:

nop              ; 0xd503201f
mov x0, #0       ; 0xd2800000

此补丁使得后续可以加载自定义(未签名的)bootloader。


7. 第四阶段: 修改并编译 libirecovery

7.1 为何需要修改

默认的 libirecovery 不支持 vresearch101ap 设备模型,需要添加对应的设备标识。

7.2 操作步骤

# 使用 wh1te4ever 的 fork 版本
git clone https://github.com/wh1te4ever/libirecovery
cd libirecovery

# 编译安装
./autogen.sh
make
sudo make install

7.3 编译 idevicerestore

git clone https://github.com/libimobiledevice/idevicerestore
cd idevicerestore
./autogen.sh
make
sudo make install

8. 第五阶段: 补丁固件组件

8.1 补丁总览

组件 补丁目的 关键偏移
iBSS 绕过签名验证 0x9D10, 0x9D14
iBEC 绕过签名验证 + 启用串口日志 0x9D10, 0x9D14, 0x122D4, 0x122D8, 0x24070
LLB 绕过签名验证 + 串口日志 + SSV 绕过 0xA0D8, 0xA0DC, 0x12888, 0x1288C, 0x24990, 0x2BFE8
TXM 绕过 TrustCache 验证 0x2C1F8, 0x2BEF4, 0x2C060
kernelcache SSV 绕过 (多处) 0x2476964, 0x23CFDE4, 0xF6D960

8.2 通用补丁函数

import struct

def patch(offset, value):
    """在指定偏移处写入补丁值"""
    fp.seek(offset)
    if isinstance(value, int):
        fp.write(struct.pack('<I', value))  # 小端 32 位
    elif isinstance(value, str):
        fp.write(value.encode('utf-8') + b'\x00')

8.3 补丁 iBSS

# 绕过 image4_validate_property_callback
patch(0x9D10, 0xd503201f)   # nop
patch(0x9D14, 0xd2800000)   # mov x0, #0

8.4 补丁 iBEC

# 绕过签名验证
patch(0x9D10, 0xd503201f)   # nop
patch(0x9D14, 0xd2800000)   # mov x0, #0

# 修改 boot-args 为 "serial=3 -v debug=0x2014e %s"
patch(0x122d4, 0xd0000082)  # adrp x2, #0x12000
patch(0x122d8, 0x9101c042)  # add x2, x2, #0x70
patch(0x24070, "serial=3 -v debug=0x2014e %s")

8.5 补丁 LLB

# 绕过签名验证
patch(0xA0D8, 0xd503201f)   # nop
patch(0xA0DC, 0xd2800000)   # mov x0, #0

# boot-args
patch(0x12888, 0xD0000082)  # adrp x2, #0x12000
patch(0x1288C, 0x91264042)  # add x2, x2, #0x990
patch(0x24990, "serial=3 -v debug=0x2014e %s")

# SSV 绕过 — 允许修改后的 rootfs 加载 (snaputil -n 所需)
patch(0x2BFE8, 0x1400000b)
patch(0x2bca0, 0xd503201f)
patch(0x2C03C, 0x17ffff6a)
patch(0x2fcec, 0xd503201f)
patch(0x2FEE8, 0x14000009)

# 绕过 panic
patch(0x1AEE4, 0xd503201f)  # nop

8.6 补丁 TXM

# 绕过 TrustCache 验证 — 使未注册的二进制也能执行
# 调用链: FFFFFFF01702B018 → sub_FFFFFFF0170306E4 → ... → sub_FFFFFFF01702EC70
# (基址: 0xFFFFFFF017004000)
patch(0x2c1f8, 0xd2800000)  # mov x0, #0  (FFFFFFF0170301F8)
patch(0x2bef4, 0xd2800000)  # mov x0, #0  (FFFFFFF01702FEF4)
patch(0x2c060, 0xd2800000)  # mov x0, #0  (FFFFFFF017030060)

8.7 补丁 kernelcache

# ========= 绕过 SSV (Signed System Volume) =========

# _apfs_vfsop_mount: 防止 panic "Failed to find the root snapshot..."
patch(0x2476964, 0xd503201f)  # nop (FFFFFE000947A964)

# _authapfs_seal_is_broken: 防止 panic "root volume seal is broken..."
patch(0x23cfde4, 0xd503201f)  # nop (FFFFFE00093D3DE4)

# _bsd_init: 防止 panic "rootvp not authenticated after mounting..."
patch(0xf6d960, 0xd503201f)   # nop (FFFFFE0007F71960)

8.8 IM4P 格式转换 (RAW ↔ IM4P)

补丁流程: IM4P → RAW → 补丁 → IM4P

对于 kernelcache 和 TXM,需要保留 PAYP 结构:

from pathlib import Path
import sys

# === 以 TXM 为例 ===

# 1. 备份原文件
if not os.path.exists("iPhone17,3_26.1_23B85_Restore/Firmware/txm.iphoneos.research.im4p.bak"):
    os.system("cp iPhone17,3_26.1_23B85_Restore/Firmware/txm.iphoneos.research.im4p "
              "iPhone17,3_26.1_23B85_Restore/Firmware/txm.iphoneos.research.im4p.bak")

# 2. IM4P → RAW
os.system("pyimg4 im4p extract -i "
          "iPhone17,3_26.1_23B85_Restore/Firmware/txm.iphoneos.research.im4p.bak "
          "-o txm.raw")

# 3. 对 txm.raw 执行上述补丁操作 ...

# 4. RAW → IM4P (使用 LZFSE 压缩)
os.system("pyimg4 im4p create -i txm.raw -o txm.im4p -f trxm --lzfse")

# 5. 保留 PAYP 结构
txm_im4p_data = Path(
    'iPhone17,3_26.1_23B85_Restore/Firmware/txm.iphoneos.research.im4p.bak'
).read_bytes()
payp_offset = txm_im4p_data.rfind(b'PAYP')
if payp_offset == -1:
    print("Couldn't find payp structure !!!")
    sys.exit()

with open('txm.im4p', 'ab') as f:
    f.write(txm_im4p_data[(payp_offset-10):])

payp_sz = len(txm_im4p_data[(payp_offset-10):])
print(f"payp sz: {payp_sz}")

# 6. 修正 IM4P 头部大小字段
txm_im4p_data = bytearray(open('txm.im4p', 'rb').read())
txm_im4p_data[2:5] = (
    int.from_bytes(txm_im4p_data[2:5], 'big') + payp_sz
).to_bytes(3, 'big')
open('txm.im4p', 'wb').write(txm_im4p_data)

# 7. 替换原文件
os.system("mv txm.im4p "
          "iPhone17,3_26.1_23B85_Restore/Firmware/txm.iphoneos.research.im4p")

iBSS / iBEC 使用 img4tool 转换(无 PAYP):

# iBSS
os.system("tools/img4 -i ...iBSS.vresearch101.RELEASE.im4p.bak -o iBSS.vresearch101.RELEASE")
# ... 补丁 RAW ...
os.system("tools/img4tool -c ...iBSS.vresearch101.RELEASE.im4p -t ibss iBSS.vresearch101.RELEASE")

# iBEC
os.system("tools/img4 -i ...iBEC.vresearch101.RELEASE.im4p.bak -o iBEC.vresearch101.RELEASE")
# ... 补丁 RAW ...
os.system("tools/img4tool -c ...iBEC.vresearch101.RELEASE.im4p -t ibec iBEC.vresearch101.RELEASE")

# LLB
os.system("tools/img4 -i ...LLB.vresearch101.RESEARCH_RELEASE.im4p.bak -o LLB.vresearch101.RESEARCH_RELEASE")
# ... 补丁 RAW ...
os.system("tools/img4tool -c ...LLB.vresearch101.RESEARCH_RELEASE.im4p -t illb LLB.vresearch101.RESEARCH_RELEASE")

9. 第六阶段: 恢复固件

9.1 进入 DFU 模式

在 super-tart 中将虚拟机启动到 DFU 模式。

9.2 执行恢复

idevicerestore -y ./iPhone17,3_26.1_23B85_Restore

9.3 注意事项

  • 如果 SEP 配置不正确,会出现 kernel panic
  • 恢复完成后虚拟机会自动重启
  • 首次重启会因 缺少 /usr/lib/libSystem.B.dylib 而在 launchd 处 panic
    • 该库位于 Cryptex 分区的 dyld_shared_cache
    • Cryptex 分区无法通过正常恢复流程安装
    • 需要通过 SSH Ramdisk 手动注入

10. 第七阶段: SSH Ramdisk 修复启动

10.1 获取 SHSH / IM4M

# 获取 SHSH blob
idevicerestore -e -y ./iPhone17,3_26.1_23B85_Restore -t

# 解压
mv shsh/[ECID]-iPhone99,11-26.1.shsh shsh/[ECID]-iPhone99,11-26.1.shsh.gz
gunzip shsh/[ECID]-iPhone99,11-26.1.shsh.gz

# 提取 IM4M
pyimg4 im4m extract -i shsh/[ECID]-iPhone99,11-26.1.shsh -o vphone.im4m

[ECID] 替换为你的虚拟机 ECID (如 0x1111111111111111)。

10.2 生成 IMG4 签名文件

为每个固件组件生成 IMG4:

# iBSS
os.system("tools/img4 -i ...iBSS.vresearch101.RELEASE.im4p.bak -o iBSS.vresearch101.RELEASE")
# ... 补丁 ...
os.system("tools/img4tool -c iBSS.vresearch101.RELEASE.im4p -t ibss iBSS.vresearch101.RELEASE")
os.system("tools/img4 -i iBSS.vresearch101.RELEASE.im4p "
          "-o ./Ramdisk/iBSS.vresearch101.RELEASE.img4 -M ./vphone.im4m")

# iBEC
os.system("tools/img4tool -c iBEC.vresearch101.RELEASE.im4p -t ibec iBEC.vresearch101.RELEASE")
os.system("tools/img4 -i iBEC.vresearch101.RELEASE.im4p "
          "-o Ramdisk/iBEC.vresearch101.RELEASE.img4 -M vphone.im4m")

# SPTM (无需补丁)
os.system("tools/img4 -i .../sptm.vresearch1.release.im4p "
          "-o Ramdisk/sptm.vresearch1.release.img4 -M vphone.im4m -T sptm")

# DeviceTree (无需补丁)
os.system("tools/img4 -i .../DeviceTree.vphone600ap.im4p "
          "-o Ramdisk/DeviceTree.vphone600ap.img4 -M vphone.im4m -T rdtr")

# SEP firmware (无需补丁)
os.system("tools/img4 -i .../sep-firmware.vresearch101.RELEASE.im4p "
          "-o Ramdisk/sep-firmware.vresearch101.RELEASE.img4 -M vphone.im4m -T rsep")

# TXM (补丁 + PAYP + 签名)
# ... 补丁同第 8.6 节 ...
os.system("pyimg4 img4 create -p txm.im4p -o Ramdisk/txm.img4 -m vphone.im4m")

# kernelcache (补丁 + PAYP + 签名, 注意 Ramdisk 用 rkrn 而非 krnl)
# ... 补丁同第 8.7 节,但 IM4P tag 使用 rkrn ...
os.system("pyimg4 im4p create -i kcache.raw -o krnl.im4p -f rkrn --lzfse")
# ... 保留 PAYP ...
os.system("pyimg4 img4 create -p krnl.im4p -o Ramdisk/krnl.img4 -m vphone.im4m")

10.3 构建自定义 SSH Ramdisk

import glob, subprocess

# 提取原始 ramdisk
os.system("pyimg4 im4p extract -i iPhone17,3_26.1_23B85_Restore/043-53775-129.dmg -o ramdisk.dmg")

# 创建扩容的 ramdisk 副本
os.system("mkdir SSHRD")
os.system("sudo hdiutil attach -mountpoint SSHRD ramdisk.dmg -owners off")
os.system("sudo hdiutil create -size 254m -imagekey diskimage-class=CRawDiskImage "
          "-format UDZO -fs APFS -layout NONE -srcfolder SSHRD -copyuid root ramdisk1.dmg")
os.system("sudo hdiutil detach -force SSHRD")
os.system("sudo hdiutil attach -mountpoint SSHRD ramdisk1.dmg -owners off")

# 删除不必要的文件以腾出空间 ...

# 对所有 Mach-O 文件重新签名
target_path = [
    "SSHRD/usr/local/bin/*", "SSHRD/usr/local/lib/*",
    "SSHRD/usr/bin/*", "SSHRD/bin/*",
    "SSHRD/usr/lib/*", "SSHRD/sbin/*", "SSHRD/usr/sbin/*", "SSHRD/usr/libexec/*"
]
for pattern in target_path:
    for path in glob.glob(pattern):
        if os.path.isfile(path) and not os.path.islink(path):
            if "Mach-O" in subprocess.getoutput(f'file "{path}"'):
                os.system(f'tools/ldid_macosx_arm64 -S -M -Cadhoc "{path}"')

# 构建 TrustCache
os.system("pyimg4 im4p extract -i "
          "iPhone17,3_26.1_23B85_Restore/Firmware/043-53775-129.dmg.trustcache "
          "-o trustcache.raw")
os.system("tools/trustcache_macos_arm64 create sshrd.tc SSHRD")
os.system("pyimg4 im4p create -i sshrd.tc -o trustcache.im4p -f rtsc")
os.system("pyimg4 img4 create -p trustcache.im4p -o Ramdisk/trustcache.img4 -m vphone.im4m")

# 封装并签名 ramdisk
os.system("sudo hdiutil detach -force SSHRD")
os.system("sudo hdiutil resize -sectors min ramdisk1.dmg")
os.system("pyimg4 im4p create -i ramdisk1.dmg -o ramdisk1.dmg.im4p -f rdsk")
os.system("pyimg4 img4 create -p ramdisk1.dmg.im4p -o Ramdisk/ramdisk.img4 -m vphone.im4m")

10.4 使用 Ramdisk 启动

创建 boot_rd.sh:

#!/bin/zsh

# 加载 iBSS → iBEC → 进入 Recovery
irecovery -f Ramdisk/iBSS.vresearch101.RELEASE.img4
irecovery -f Ramdisk/iBEC.vresearch101.RELEASE.img4
irecovery -c go

sleep 1

# 加载 SPTM
irecovery -f Ramdisk/sptm.vresearch1.release.img4
irecovery -c firmware

# 加载 TXM
irecovery -f Ramdisk/txm.img4
irecovery -c firmware

# 加载 TrustCache
irecovery -f Ramdisk/trustcache.img4
irecovery -c firmware

# 加载 Ramdisk
irecovery -f Ramdisk/ramdisk.img4
irecovery -c ramdisk

# 加载 DeviceTree
irecovery -f Ramdisk/DeviceTree.vphone600ap.img4
irecovery -c devicetree

# 加载 SEP 固件
irecovery -f Ramdisk/sep-firmware.vresearch101.RELEASE.img4
irecovery -c firmware

# 加载内核并启动
irecovery -f Ramdisk/krnl.img4
irecovery -c bootx

执行:

chmod +x boot_rd.sh
./boot_rd.sh

10.5 验证启动成功

启动后检查:

  1. super-tart 的第三个窗口应显示 Minecraft Creeper 脸 图案
  2. 打开 系统信息 (System Information) → USB,应显示 “iPhone Research…”
  3. 通过 iproxy 连接:
iproxy 2222 22 &
ssh root@127.0.0.1 -p 2222
# 密码: alpine

10.6 重命名 APFS Snapshot

# 在 SSH 连接中执行:
mount_apfs -o rw /dev/disk1s1 /mnt1

# 列出 snapshot
snaputil -l /mnt1
# 输出类似: com.apple.os.update-8AAB8DBA5C8F1F...

# 重命名 snapshot(允许修改根文件系统)
snaputil -n com.apple.os.update-8AAB8DBA5C8F1F... orig-fs /mnt1

umount /mnt1
exit

注意: 这一步是 SSV 绕过的关键——LLB 中的补丁使得 snaputil -n 重命名操作成为可能。


11. 第八阶段: 安装 Cryptex 与系统修补

11.1 解密并挂载 Cryptex

import subprocess

# 解密 SystemOS Cryptex (AEA 格式)
key = subprocess.check_output(
    "ipsw fw aea --key iPhone17,3_26.1_23B85_Restore/043-54303-126.dmg.aea",
    shell=True, text=True
).strip()
os.system(f"aea decrypt -i iPhone17,3_26.1_23B85_Restore/043-54303-126.dmg.aea "
          f"-o CryptexSystemOS.dmg -key-value '{key}'")

# 复制 AppOS Cryptex (无需解密)
os.system("cp iPhone17,3_26.1_23B85_Restore/043-54062-129.dmg CryptexAppOS.dmg")

# 挂载
os.system("mkdir CryptexSystemOS CryptexAppOS")
os.system("sudo hdiutil attach -mountpoint CryptexSystemOS CryptexSystemOS.dmg -owners off")
os.system("sudo hdiutil attach -mountpoint CryptexAppOS CryptexAppOS.dmg -owners off")

11.2 传输 Cryptex 到虚拟机

def remote_cmd(cmd):
    """通过 SSH 在虚拟机上执行命令"""
    os.system(f"tools/sshpass -p 'alpine' ssh -o StrictHostKeyChecking=no "
              f"-o UserKnownHostsFile=/dev/null -p 2222 root@127.0.0.1 '{cmd}'")

# 挂载根文件系统 (读写)
remote_cmd("/sbin/mount_apfs -o rw /dev/disk1s1 /mnt1")

# 清理旧的 Cryptex 目录
remote_cmd("/bin/rm -rf /mnt1/System/Cryptexes/App")
remote_cmd("/bin/rm -rf /mnt1/System/Cryptexes/OS")
remote_cmd("/bin/mkdir -p /mnt1/System/Cryptexes/App")
remote_cmd("/bin/chmod 0755 /mnt1/System/Cryptexes/App")
remote_cmd("/bin/mkdir -p /mnt1/System/Cryptexes/OS")
remote_cmd("/bin/chmod 0755 /mnt1/System/Cryptexes/OS")

# 通过 SCP 传输 (约需 3 分钟)
SCP_OPTS = ("-q -r -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null "
            "-P 2222")
os.system(f"tools/sshpass -p 'alpine' scp {SCP_OPTS} "
          f"CryptexSystemOS/. 'root@127.0.0.1:/mnt1/System/Cryptexes/OS'")
os.system(f"tools/sshpass -p 'alpine' scp {SCP_OPTS} "
          f"CryptexAppOS/. 'root@127.0.0.1:/mnt1/System/Cryptexes/App'")

# 创建必要的符号链接
remote_cmd("/bin/ln -sf ../../../System/Cryptexes/OS/System/Library/Caches/com.apple.dyld "
           "/mnt1/System/Library/Caches/com.apple.dyld")
remote_cmd("/bin/ln -sf ../../../../System/Cryptexes/OS/System/DriverKit/System/Library/dyld "
           "/mnt1/System/DriverKit/System/Library/dyld")

11.3 补丁 seputil

seputil 无法正确找到 gigalocker 文件,需要补丁为始终查找 AA.gl:

# 从虚拟机拉取 seputil
os.system(f"tools/sshpass -p 'alpine' scp -q -o StrictHostKeyChecking=no "
          f"-o UserKnownHostsFile=/dev/null -P 2222 "
          f"root@127.0.0.1:/mnt1/usr/libexec/seputil ./custom_26.1/seputil")

# 补丁: 将 gigalocker 文件名硬编码为 "AA"
fp = open("custom_26.1/seputil", "r+b")
fp.seek(0x1B3F1)
fp.write(b"AA")
fp.close()

# 重新签名
os.system("tools/ldid_macosx_arm64 -S -M -Ksigncert.p12 "
          "-Icom.apple.seputil custom_26.1/seputil")

# 推送到虚拟机
os.system(f"tools/sshpass -p 'alpine' scp -q -o StrictHostKeyChecking=no "
          f"-o UserKnownHostsFile=/dev/null -P 2222 "
          f"custom_26.1/seputil 'root@127.0.0.1:/mnt1/usr/libexec/seputil'")
remote_cmd("/bin/chmod 0755 /mnt1/usr/libexec/seputil")

# 重命名 gigalocker 文件
remote_cmd("/sbin/mount_apfs -o rw /dev/disk1s3 /mnt3")
remote_cmd("/bin/mv /mnt3/*.gl /mnt3/AA.gl")

11.4 补丁 launchd_cache_loader

修改 /System/Library/xpc/launchd.plist 后需要补丁 launchd_cache_loader

# 拉取
os.system(f"tools/sshpass -p 'alpine' scp -q -o StrictHostKeyChecking=no "
          f"-o UserKnownHostsFile=/dev/null -P 2222 "
          f"root@127.0.0.1:/mnt1/usr/libexec/launchd_cache_loader ./custom_26.1/")

# 补丁: 应用 launchd_unsecure_cache=1 效果
fp = open("custom_26.1/launchd_cache_loader", "r+b")
fp.seek(0xB58)
fp.write(struct.pack('<I', 0xd503201f))  # nop
fp.close()

# 重新签名并推送
os.system("tools/ldid_macosx_arm64 -S -M -Ksigncert.p12 "
          "-Icom.apple.launchd_cache_loader custom_26.1/launchd_cache_loader")
os.system(f"tools/sshpass -p 'alpine' scp -q -o StrictHostKeyChecking=no "
          f"-o UserKnownHostsFile=/dev/null -P 2222 "
          f"custom_26.1/launchd_cache_loader "
          f"'root@127.0.0.1:/mnt1/usr/libexec/launchd_cache_loader'")
remote_cmd("/bin/chmod 0755 /mnt1/usr/libexec/launchd_cache_loader")

11.5 安装 iosbinpack64 (bash/dropbear)

# 传输 iosbinpack64 到虚拟机
os.system(f"tools/sshpass -p 'alpine' scp -q -r -o StrictHostKeyChecking=no "
          f"-o UserKnownHostsFile=/dev/null -P 2222 "
          f"jb/iosbinpack64.tar 'root@127.0.0.1:/mnt1'")

# 解压
remote_cmd("/usr/bin/tar --preserve-permissions --no-overwrite-dir "
           "-xvf /mnt1/iosbinpack64.tar -C /mnt1")
remote_cmd("/bin/rm /mnt1/iosbinpack64.tar")

启动后初始化 dropbear:

/iosbinpack64/bin/mkdir -p /var/dropbear
/iosbinpack64/bin/cp /iosbinpack64/etc/profile /var/profile
/iosbinpack64/bin/cp /iosbinpack64/etc/motd /var/motd

11.6 配置开机自启服务

创建并注入 3 个 LaunchDaemon plist (bash, dropbear, trollvnc) 到 /System/Library/LaunchDaemons/,并修改 /System/Library/xpc/launchd.plist:

import plistlib

# 传输 plist 文件
for service in ["bash", "dropbear", "trollvnc"]:
    os.system(f"tools/sshpass -p 'alpine' scp -q -o StrictHostKeyChecking=no "
              f"-o UserKnownHostsFile=/dev/null -P 2222 "
              f"jb/LaunchDaemons/{service}.plist "
              f"'root@127.0.0.1:/mnt1/System/Library/LaunchDaemons'")
    remote_cmd(f"/bin/chmod 0644 /mnt1/System/Library/LaunchDaemons/{service}.plist")

# 修改 launchd.plist
os.system(f"tools/sshpass -p 'alpine' scp -q -o StrictHostKeyChecking=no "
          f"-o UserKnownHostsFile=/dev/null -P 2222 "
          f"root@127.0.0.1:/mnt1/System/Library/xpc/launchd.plist ./custom_26.1/")
os.system("plutil -convert xml1 custom_26.1/launchd.plist")

# 注入 3 个 LaunchDaemon
for service in ["bash", "dropbear", "trollvnc"]:
    target_file = 'custom_26.1/launchd.plist'
    source_file = f'jb/LaunchDaemons/{service}.plist'
    insert_key = f'/System/Library/LaunchDaemons/{service}.plist'

    with open(target_file, 'rb') as ft, open(source_file, 'rb') as fs:
        target_data = plistlib.load(ft)
        source_data = plistlib.load(fs)

    target_data.setdefault('LaunchDaemons', {})[insert_key] = source_data

    with open(target_file, 'wb') as f:
        plistlib.dump(target_data, f, sort_keys=False)

# 推送修改后的 launchd.plist
os.system(f"tools/sshpass -p 'alpine' scp -q -o StrictHostKeyChecking=no "
          f"-o UserKnownHostsFile=/dev/null -P 2222 "
          f"custom_26.1/launchd.plist "
          f"'root@127.0.0.1:/mnt1/System/Library/xpc'")
remote_cmd("/bin/chmod 0644 /mnt1/System/Library/xpc/launchd.plist")

11.7 关机

remote_cmd("/sbin/halt")

12. 第九阶段: 实现 Metal GPU 加速

12.1 问题

首次正常启动后,Metal 不可用:

-bash-4.4# ./MetalTest
2026-02-08 22:49:02.293 MetalTest[633:9434] device: (null)
2026-02-08 22:49:02.294 MetalTest[633:9434] Metal Not Supported!

虽然 ioreg -l 显示内核已识别 AppleParavirtGPU,但缺少用户空间的 Metal 驱动。

12.2 MetalTest 验证程序

#import <stdio.h>
#import <Metal/Metal.h>
#import <Foundation/Foundation.h>

int main(int argc, char *argv[], char *envp[]) {
    id<MTLDevice> device = MTLCreateSystemDefaultDevice();
    NSLog(@"device: %@", device);

    if (device) {
        NSLog(@"Metal Device Create Success: %@", [device name]);
    } else {
        NSLog(@"Metal Not Supported!");
    }
    return 0;
}

12.3 解决方案

  1. PCC 虚拟机中提取 /System/Library/Extensions/AppleParavirtGPUMetalIOGPUFamily.bundle
  2. 通过 SSH Ramdisk 放入虚拟 iPhone 的相同路径
  3. 从 PCC 的 dyld_shared_cache 中逆向并重新实现 libAppleParavirtCompilerPluginIOGPUFamily.dylib(因为 iPhone 16 的 dsc 中不包含此 dylib)

12.4 验证

-bash-4.4# ./MetalTest
device: <AppleParavirtDevice: 0x102c48fe0>
    name = Apple Paravirtual device
Metal Device Create Success: Apple Paravirtual device

13. 第十阶段: Sequoia 上启用触摸交互

13.1 问题

macOS Tahoe 26 上 VZVirtualMachineView 原生支持触摸映射,但 Sequoia 15.x 上不行,需要手动重写鼠标事件。

13.2 解决方案

创建 VirtualMachineView 子类,重写鼠标事件并映射到 _VZMultiTouchEvent:

class VirtualMachineView: VZVirtualMachineView {
    var currentTouchSwipeAim: Int64 = 0

    override func mouseDown(with event: NSEvent) {
        let multiTouchDevices: NSArray = Dynamic(self.virtualMachine)
            ._multiTouchDevices.asArray!
        let locationInWindow = event.locationInWindow
        let normalizedPoint = normalizeCoordinate(locationInWindow)
        let localPoint = self.convert(locationInWindow, from: nil)
        let edgeResult = hitTestEdge(at: localPoint)
        self.currentTouchSwipeAim = Int64(edgeResult)

        if multiTouchDevices.count as Int > 0 {
            guard let touch = VZTouchHelper.createTouch(
                withView: self.virtualMachine,
                index: 0,
                phase: 0,  // UITouchPhase.began
                location: normalizedPoint.point,
                swipeAim: edgeResult,
                timestamp: event.timestamp
            ) else { return }

            let touchEvent = Dynamic._VZMultiTouchEvent(
                touches: [touch] as NSArray
            ).asObject
            let device = multiTouchDevices.object(at: 0)
            Dynamic(device).sendMultiTouchEvents([touchEvent] as NSArray)
        }
        super.mouseDown(with: event)
    }

    override func mouseDragged(with event: NSEvent) {
        // phase: 1 (UITouchPhase.moved)
        // ... 类似 mouseDown 的逻辑 ...
        super.mouseDragged(with: event)
    }

    override func mouseUp(with event: NSEvent) {
        // phase: 3 (UITouchPhase.ended)
        // ... 类似 mouseDown 的逻辑 ...
        super.mouseUp(with: event)
    }

    // 右键点击 → 双指触摸
    override func rightMouseDown(with event: NSEvent) {
        // 创建两个 touch (index: 0 和 index: 1)
        // ... 实现多点触控 ...
        super.rightMouseDown(with: event)
    }

    override func rightMouseUp(with event: NSEvent) {
        // 结束双指触摸
        super.rightMouseUp(with: event)
    }
}

13.3 坐标标准化

func normalizeCoordinate(_ point: CGPoint) -> NormalizedResult {
    let bounds = self.bounds
    if bounds.size.width <= 0 || bounds.size.height <= 0 {
        return NormalizedResult(point: .zero, isInvalid: true)
    }
    let localPoint = self.convert(point, from: nil)
    var nx = max(0.0, min(1.0, Double(localPoint.x / bounds.size.width)))
    var ny = max(0.0, min(1.0, Double(localPoint.y / bounds.size.height)))
    if !self.isFlipped { ny = 1.0 - ny }
    return NormalizedResult(point: CGPoint(x: nx, y: ny), isInvalid: false)
}

13.4 边缘检测 (用于滑动手势)

func hitTestEdge(at point: CGPoint) -> Int {
    let bounds = self.bounds
    let distLeft = point.x
    let distRight = bounds.size.width - point.x
    var minDist: Double
    var edgeCode: Int

    if distRight < distLeft {
        minDist = distRight; edgeCode = 4  // Right
    } else {
        minDist = distLeft;  edgeCode = 8  // Left
    }

    let topCode = self.isFlipped ? 2 : 1
    let bottomCode = self.isFlipped ? 1 : 2

    if point.y < minDist {
        minDist = point.y; edgeCode = topCode
    }
    if (bounds.size.height - point.y) < minDist {
        minDist = bounds.size.height - point.y; edgeCode = bottomCode
    }

    return minDist < 32.0 ? edgeCode : 0  // VMViewEdge.none
}

13.5 窗口管理 (ScreenSharingVNC)

class ScreenSharingVNC: VNC {
    var virtualMachine: VZVirtualMachine?
    private var windowController: NSWindowController?

    private func openVMWindow(for vm: VZVirtualMachine) {
        let vmView: NSView
        if #available(macOS 16.0, *) {
            let view = VZVirtualMachineView()
            view.virtualMachine = vm
            view.capturesSystemKeys = true
            vmView = view
        } else {
            // Sequoia: 使用自定义的 VirtualMachineView
            let view = VirtualMachineView()
            view.virtualMachine = vm
            view.capturesSystemKeys = true
            vmView = view
        }

        let windowSize = NSSize(width: 1179, height: 2556)
        let window = NSWindow(
            contentRect: NSRect(origin: .zero, size: windowSize),
            styleMask: [.titled, .closable, .resizable, .miniaturizable],
            backing: .buffered,
            defer: false
        )
        window.contentAspectRatio = windowSize
        window.title = "vphone"
        window.contentView = vmView
        window.center()

        let controller = NSWindowController(window: window)
        controller.showWindow(nil)
        self.windowController = controller

        if NSApp == nil { _ = NSApplication.shared }
        NSApp.setActivationPolicy(.regular)
        window.makeKeyAndOrderFront(nil)
        NSApp.activate(ignoringOtherApps: true)
    }
}

完整源码: ScreenSharingVNC.swift


14. 兼容性

Mac 型号 内存 macOS 版本 状态
Apple M3 16GB Sequoia 15.7.4 已验证
Apple M1 Pro 32GB Tahoe 26.3 已验证

预计任何支持 pccvre 的设备均可运行。

Sequoia vs Tahoe 差异:

  • Tahoe 26.x: VZVirtualMachineView 原生支持触摸映射
  • Sequoia 15.x: 需要自定义 VirtualMachineView 子类重写鼠标事件(见第 13 阶段)

15. 常见问题排查

Q1: SEP 相关 Kernel Panic

原因: SEPStorage 文件路径或内容不正确。

解决: 确认 ~/.tart/vms/vphone/SEPStorage 存在且路径一致。

Q2: 恢复后 launchd panic (缺少 libSystem.B.dylib)

原因: Cryptex 分区未成功恢复,dyld_shared_cache 缺失。

解决: 按第 10-11 阶段通过 SSH Ramdisk 手动注入 Cryptex 文件。

Q3: Metal 不可用 (MTLCreateSystemDefaultDevice 返回 null)

原因: 缺少 AppleParavirtGPUMetalIOGPUFamily.bundle

解决: 从 PCC VM 中提取该 bundle 并放入 /System/Library/Extensions/

Q4: 触摸交互无响应 (Sequoia)

原因: Sequoia 的 VZVirtualMachineView 不自动处理触摸事件映射。

解决: 使用自定义 VirtualMachineView 子类(见第 13 阶段)。

Q5: 启动后卡在黑色设置界面

原因: 第一次启动时 Metal 未配置,UI 渲染异常。

解决: 先完成 Metal 支持配置(第 12 阶段),然后重新启动。

Q6: snaputil -n 失败

原因: LLB 中的 SSV 绕过补丁未正确应用。

解决: 重新检查 LLB 补丁偏移 (0x2BFE8, 0x2bca0, 0x2C03C, 0x2fcec, 0x2FEE8)。


16. 参考项目与工具链

项目 用途
security-pcc Apple PCC 源码,vrevm 参考实现
super-tart 修改版 tart VM,支持 DFU/自定义 BootROM
vma2pwn macOS VM 自定义启动链参考
SSHRD_Script SSH Ramdisk 参考
libirecovery (fork) 支持 vresearch101ap 的 libirecovery
idevicerestore 固件恢复工具
pyimg4 IMG4 处理 Python 库
img4tool IM4P 创建/转换
img4lib IMG4 处理 C 库
ipsw IPSW/AEA 固件处理
ldid 代码签名
trustcache TrustCache 创建
TrollVNC VNC 远程控制

致谢


免责声明: 本文档仅供安全研究和学习目的。请遵守 Apple 的服务条款和当地法律法规。

说实话,这个项目的复现难度非常高,属于 iOS 安全研究领域的顶级操作。我从几个维度来分析:


难度评级:9/10


一、技术门槛极高

需要同时精通以下多个领域:

领域 具体要求 难度
Apple 虚拟化框架 熟悉 Virtualization.framework 的私有 API,没有公开文档 极高
ARM64 逆向 能在 IDA Pro 中定位并理解 iBoot/LLB/TXM/kernelcache 的关键函数
iOS 启动链 理解 AVPBooter → iBSS → iBEC → LLB → SPTM → TXM → kernel 整条链
IMG4/IM4P 签名体系 理解 Apple 的 Image4 验证机制、PAYP 结构、SHSH blob
APFS 文件系统 SSV、snapshot 机制、Cryptex 分区架构 中高
macOS 内核扩展 Metal 驱动移植、IOKit 驱动架构
Swift 开发 修改 super-tart、实现触摸映射

二、最大的几个卡点

  1. 固件混合 — 作者自己都记不清细节

原文直说了:

“uh, but… I can’t remember the exact details”(我记不清具体细节了)

BuildManifest.plist 和 Restore.plist 的修改是整个流程中最关键也最不透明的部分。虽然仓库提供了最终文件,但如果固件版本变了(比如 cloudOS 27 或 iOS 27),你需要自己重新搞清楚哪些组件从哪里来,这基本等于重新做一遍研究。

  1. 补丁偏移地址是硬编码的

所有补丁(iBSS 0x9D10、kernelcache 0x2476964 等)都是针对 cloudOS 26.1 (23B85) 的特定版本。固件一更新,所有地址全部失效,你需要:

  • 重新逆向每个组件

  • 重新定位每个函数

  • 重新计算每个补丁偏移

  1. Cryptex 缺失问题没有根本解决方案

作者用了一个"临时方案"——通过 SSH Ramdisk 手动注入 Cryptex 文件。为什么正常恢复流程无法安装 Cryptex,原文并没有给出明确解释。如果你遇到不同的失败情况,只能自己调试。

  1. Metal 驱动需要逆向实现

从 PCC 的 dyld_shared_cache 中逆向 libAppleParavirtCompilerPluginIOGPUFamily.dylib 并重新实现——这一步原文只用了一句话带过,但实际工作量可能是整个项目中最大的之一。

  1. SIP/AMFI 必须禁用

这意味着你的宿主机 macOS 安全性大幅降低,不适合在日常使用的机器上操作。

三、可复现性分析

条件 评估
仓库提供了 BuildManifest.plist / Restore.plist 降低难度,但版本锁定
仓库提供了 ScreenSharingVNC.swift 完整代码 触摸交互可直接复用
仓库提供了 libirecovery fork 可直接编译
补丁脚本只给了部分代码 (patch_fw.py) 需要自己补全完整脚本
Metal dylib 逆向实现没有提供 这是最大的缺失,需要自己做
patch() 函数的具体实现没有完整给出 需要自己编写文件 I/O 逻辑
工具链(img4/img4tool/ldid/trustcache)需要自己编译 各有各的依赖问题

四、现实可行性判断

能顺利复现的人大概需要:

  • 3 年以上 iOS/macOS 安全研究经验

  • 熟练使用 IDA Pro 进行 ARM64 逆向

  • 了解 Apple 启动链和签名验证机制

  • 有耐心调试大量 kernel panic(串口日志是你的好朋友)

  • 愿意花 1-2 周全职投入

对大多数人来说最现实的障碍是:

  • 没有 Apple Silicon Mac(硬性要求)

  • 不愿意禁用 SIP/AMFI

  • Metal dylib 的逆向实现完全没有公开

五、总结

这个 writeup 的价值更多在于思路和方法论,而不是一个开箱即用的工具。它展示了:

  • Apple 虚拟化框架私有 API 的能力边界

  • 一套完整的"从 DFU 到用户空间"的固件定制方法

  • Cryptex、SSV、TrustCache 等 iOS 现代安全机制的绕过思路

如果你的目标是学习 iOS 底层安全机制,这个 writeup 是极好的教材。如果你的目标是跑起来一个虚拟 iPhone 用,那难度和投入产出比都非常不友好。

2 个赞