10 KiB
vphone-cli
Virtual iPhone boot tool using Apple's Virtualization.framework with PCC research VMs.
Quick Reference
- Build:
make build - Boot (GUI):
make boot - Boot (DFU):
make boot_dfu - All targets:
make help - Python venv:
make setup_venv(installs to.venv/, activate withsource .venv/bin/activate) - Platform: macOS 15+ (Sequoia), SIP/AMFI disabled
- Language: Swift 6.0 (SwiftPM), private APIs via Dynamic
- Python deps:
capstone,keystone-engine,pyimg4(seerequirements.txt)
Workflow Rules
- Do not create, read, or update
/TODO.md. - Ignore
/TODO.mdif it exists locally; it is intentionally not part of the repo workflow anymore. - Track plan, progress, assumptions, blockers, and next actions in commit history, code comments when warranted, and current research docs instead of a repo TODO file.
For any changes applying new patches, also update research/0_binary_patch_comparison.md. Dont forget this.
Local Skills
- If working on kernel analysis, symbolication lookups, or kernel patch reasoning, read
skills/kernel-analysis-vphone600/SKILL.mdfirst. - Use this skill as the default procedure for
vphone600kernel work.
Firmware Variants
| Variant | Boot Chain | CFW | Make Targets |
|---|---|---|---|
| Regular | 51 patches | 10 phases | fw_patch + cfw_install |
| Development | 64 patches | 12 phases | fw_patch_dev + cfw_install_dev |
| Jailbreak | 126 patches | 14 phases | fw_patch_jb + cfw_install_jb |
JB finalization (symlinks, Sileo, apt, TrollStore) runs automatically on first boot via
/cores/vphone_jb_setup.shLaunchDaemon. Monitor progress:/var/log/vphone_jb_setup.log.
See research/ for detailed firmware pipeline, component origins, patch breakdowns, and boot flow documentation.
Architecture
Makefile # Single entry point — run `make help`
sources/
├── vphone.entitlements # Private API entitlements (5 keys)
└── vphone-cli/ # Swift 6.0 executable (pure Swift, no ObjC)
├── main.swift # Entry point — NSApplication + AppDelegate
├── VPhoneAppDelegate.swift # App lifecycle, SIGINT, VM start/stop
├── VPhoneCLI.swift # ArgumentParser options (no execution logic)
├── VPhoneBuildInfo.swift # Auto-generated build-time commit hash
│
│ # VM core
├── VPhoneVirtualMachine.swift # @MainActor VM configuration and lifecycle
├── VPhoneHardwareModel.swift # PV=3 hardware model via Dynamic
├── VPhoneVirtualMachineView.swift # Touch-enabled VZVirtualMachineView + helpers
├── VPhoneError.swift # Error types
│
│ # Guest daemon client (vsock)
├── VPhoneControl.swift # Host-side vsock client for vphoned (length-prefixed JSON)
│
│ # Window & UI
├── VPhoneWindowController.swift # @MainActor VM window management + toolbar
├── VPhoneKeyHelper.swift # Keyboard/hardware key event dispatch to VM
├── VPhoneLocationProvider.swift # CoreLocation → guest forwarding over vsock
├── VPhoneScreenRecorder.swift # VM screen recording to file
│
│ # Menu bar (extensions on VPhoneMenuController)
├── VPhoneMenuController.swift # Menu bar controller
├── VPhoneMenuKeys.swift # Keys menu — home, power, volume, spotlight
├── VPhoneMenuType.swift # Type menu — paste ASCII text to guest
├── VPhoneMenuLocation.swift # Location menu — host location sync toggle
├── VPhoneMenuConnect.swift # Connect menu — devmode, ping, version, file browser
├── VPhoneMenuInstall.swift # Install menu — IPA installation to guest
├── VPhoneMenuRecord.swift # Record menu — screen recording controls
├── VPhoneMenuBattery.swift # Battery menu — battery status display
│
│ # IPA installation
├── VPhoneIPAInstaller.swift # IPA extraction, signing, and installation
├── VPhoneSigner.swift # Mach-O binary signing utilities
│
│ # File browser (SwiftUI)
├── VPhoneFileWindowController.swift # File browser window (NSHostingController)
├── VPhoneFileBrowserView.swift # SwiftUI file browser with search + drag-drop
├── VPhoneFileBrowserModel.swift # @Observable file browser state + transfers
└── VPhoneRemoteFile.swift # Remote file data model
scripts/
├── vphoned/ # Guest daemon (ObjC, runs inside iOS VM over vsock)
├── patchers/ # Python CFW patcher modules
│ └── cfw.py # CFW binary patcher entrypoint
├── resources/ # Resource archives (git submodule)
├── repos/ # Toolchain source repos (git submodules: trustcache, insert_dylib, libimobiledevice stack)
├── patches/ # Build-time patches (libirecovery)
├── fw_prepare.sh # Download IPSWs, merge cloudOS into iPhone
├── fw_manifest.py # Generate hybrid BuildManifest/Restore plists
├── ramdisk_build.py # Build SSH ramdisk with trustcache (reuses Swift patch-component for TXM/base kernel)
├── ramdisk_send.sh # Send ramdisk to device via irecovery
├── cfw_install.sh # Install CFW (regular)
├── cfw_install_dev.sh # Regular + rpcserver daemon
├── cfw_install_jb.sh # Regular + jetsam fix + procursus
├── vm_create.sh # Create VM directory
├── setup_machine.sh # Full automation (setup → first boot)
├── setup_tools.sh # Install deps, build toolchain from submodules, create venv
├── setup_venv.sh # Create Python venv
├── setup_venv_linux.sh # Create Python venv (Linux)
├── setup_libimobiledevice.sh # Build libimobiledevice stack from scripts/repos submodules
└── tail_jb_patch_logs.sh # Tail JB patch log output
research/ # Detailed firmware/patch documentation
Key Patterns
- Private API access: Via Dynamic library (runtime method dispatch from pure Swift). No ObjC bridge.
- App lifecycle:
main.swift→NSApplication+VPhoneAppDelegate. CLI args parsed before run loop. AppDelegate drives VM start/window/shutdown. - Configuration:
ArgumentParser→VPhoneVirtualMachine.Options→VZVirtualMachineConfiguration. - Guest daemon (vphoned): ObjC daemon inside iOS VM, vsock port 1337, length-prefixed JSON protocol. Host side is
VPhoneControlwith auto-reconnect. - Menu system:
VPhoneMenuController+ per-menu extensions (Keys, Type, Location, Connect, Install, Record). - File browser: SwiftUI (
VPhoneFileBrowserView+VPhoneFileBrowserModel) inNSHostingController. Search, sort, upload/download, drag-drop viaVPhoneControl. - IPA installation:
VPhoneIPAInstallerextracts + re-signs viaVPhoneSigner+ installs over vsock. - Screen recording:
VPhoneScreenRecordercaptures VM display. Controls via Record menu.
Coding Conventions
Swift
- Language: Swift 6.0 (strict concurrency).
- Style: Pragmatic, minimal. No unnecessary abstractions.
- Sections: Use
// MARK: -to organize code within files. - Access control: Default (internal). Only mark
privatewhen needed for clarity. - Concurrency:
@MainActorfor VM and UI classes.nonisolateddelegate methods useMainActor.isolated {}to hop back safely. - Naming: Types are
VPhone-prefixed. Match Apple framework conventions. - Private APIs: Use
Dynamic()for runtime method dispatch. Touch objects useNSClassFromString+ KVC to avoid designated initializer crashes. - NSWindow
isReleasedWhenClosed: Always setwindow.isReleasedWhenClosed = falsefor programmatically created windows managed by anNSWindowController. The defaulttruecausesobjc_releasecrashes on dangling pointers during CA transaction commit.
Shell Scripts
- Use
zshwithset -euo pipefail. - Scripts resolve their own directory via
${0:a:h}or$(cd "$(dirname "$0")" && pwd).
Python Scripts
Kernel patcher guardrails
-
For kernel patchers, never hardcode file offsets, virtual addresses, or preassembled instruction bytes inside patch logic.
-
All instruction matching must be derived from Capstone decode results (mnemonic / operands / control-flow), not exact operand-string text when a semantic operand check is possible.
-
All replacement instruction bytes must come from Keystone-backed helpers already used by the project (for example
asm(...),NOP,MOV_W0_0, etc.). -
Prefer source-backed semantic anchors: in-image symbol lookup, string xrefs, local call-flow, and XNU correlation. Do not depend on repo-exported per-kernel symbol dumps at runtime.
-
When retargeting a patch, write the reveal procedure and validation steps into the relevant research doc or commit notes before handing off for testing. Do not create
TODO.md. -
For
patch_bsd_init_authspecifically, the allowed reveal flow is: recoverbsd_init-> locate rootvp panic block -> find the unique in-functioncall->cbnz w0/x0, panic->bl imageboot_neededsite -> patch the branch gate only. -
Patchers use
capstone(disassembly),keystone-engine(assembly),pyimg4(IM4P handling). -
Dynamic pattern finding (string anchors, ADRP+ADD xrefs, BL frequency) — no hardcoded offsets.
-
Each patch logged with offset and before/after state.
-
Use project venv (
source .venv/bin/activate). Create withmake setup_venv.
Build & Sign
The binary requires private entitlements for PV=3 virtualization. Always use make build — never swift build alone, as the unsigned binary will fail at runtime.
Design System
- Audience: Security researchers. Terminal-adjacent workflow.
- Feel: Research instrument — precise, informative, no decoration.
- Palette: Dark neutral (
#1a1a1abg), status green/amber/red/blue accents. - Typography: System monospace (SF Mono / Menlo) for UI and log output.
- Depth: Flat with 1px borders (
#333333). No shadows. - Spacing: 8px base unit, 12px component padding, 16px section gaps.