How the vphone-cli Restore Pipeline Fetches SHSH Blobs and Performs DFU Restore
The vphone-cli restore pipeline coordinates Swift CLI orchestration with Python bridge scripts to first retrieve SHSH blobs from Apple's TSS service using the device's ECID, then boot the virtual machine into DFU mode and stream the signed firmware payload via vsock to the guest daemon to complete the restore process.
The Lakr233/vphone-cli project implements a fully automated restoration workflow for virtual iOS devices. By combining Swift-based VM management with Python-driven communication to Apple's signing infrastructure, the pipeline eliminates manual intervention during SHSH retrieval and DFU flashing. This architecture enables both online restores with live TSS negotiation and offline restores using cached signature blobs.
Resolving Device Identifiers and VM Bundles
Before contacting Apple's servers, the pipeline must identify the target device. In sources/vphone-cli/VPhoneRestoreCLI.swift, the run() method invokes VPhoneRestoreOps.resolveECID (defined in sources/VPhoneCore/VPhoneRestoreOps.swift) to determine the device's unique ECID. The resolver first checks for an explicit --ecid argument; if omitted, it reads from udid-prediction.txt generated during the DFU boot sequence. This identifier anchors all subsequent TSS communication and blob storage.
Fetching SHSH Blobs via the Python Bridge
The SHSH retrieval phase leverages a hybrid Swift-Python execution model. When the user invokes vphone-cli restore <vm-name> --get-shsh, the Swift layer constructs a command array targeting scripts/pymobiledevice3_bridge.py with the restore-get-shsh subcommand.
// VPhoneRestoreCLI.swift (lines 45-47)
if getShsh {
throw ExitCode(try pmd3("restore-get-shsh", extra: []))
}
The helper pmd3(_:) builds the full argument set including --vm-dir, --ecid, and verbosity flags, then executes via VPhoneProcessRunner.swift. The Python bridge contacts Apple's TSS service using libmobiledevice, submits the ECID/UDID pair, and writes the returned plist to <ecid>.shsh within the VM bundle directory. This file contains the signed hashes required to authorize the subsequent restore.
Booting into DFU Mode
The DFU restore requires the virtual machine to boot without the standard guest control channel. VPhoneCreateOrchestrator (lines 378-384) spawns the CLI binary with the --dfu flag, configuring VZVirtualMachine for a restricted boot environment. Alternatively, users can invoke make boot_dfu, which builds the binary and launches the VM in DFU-only mode, preparing the virtual hardware to receive the restore payload.
Executing the Restore Update
Once the VM runs in DFU mode, the orchestrator triggers the actual restoration. The Swift CLI invokes the restore-update subcommand through the same Python bridge:
// VPhoneRestoreCLI.swift (lines 61-66)
code = try pmd3("restore-update", extra: [])
The bridge streams the IPSW contents—including iBSS, iBEC, and ramdisk images—over the VM's vsock channel to the vphoned daemon running inside the guest. The daemon applies the SHSH signature previously fetched and executes the libimobiledevice restore sequence, effectively flashing the firmware to the virtual device.
Offline Restore with Cached SHSH
The pipeline supports air-gapped operations through the --offline flag. When specified, VPhoneRestoreCLI locates the cached *.shsh file within the VM bundle and passes it to the Python bridge via the --tss parameter. The bridge skips TSS server contact and uses the cached blob for signature verification, allowing restoration in isolated network environments.
# Offline restore workflow
vphone-cli vm launch MyPhone --dfu &
vphone-cli restore MyPhone --offline # Uses cached <ecid>.shsh
Post-Restore Version Bookkeeping
Upon successful completion (exit code 0), the CLI calls recordRestoreVersions to extract iOS and cloudOS version metadata from the restored bundle's plist files. Using VPhoneRestoreInfo.derive, the system writes this data to restore-info.json in the VM directory, creating a permanent record of the versions installed during the restore operation.
Complete Workflow Examples
The following commands demonstrate the full pipeline from SHSH retrieval to completed restore:
# 1. Fetch SHSH blob only (online)
vphone-cli restore MyPhone --get-shsh
# Generates: MyPhone/<ecid>.shsh
# 2. Full online restore (DFU boot + restore)
vphone-cli vm launch MyPhone --dfu &
vphone-cli restore MyPhone
# 3. Offline restore using cached blob
vphone-cli vm launch MyPhone --dfu &
vphone-cli restore MyPhone --offline --tss MyPhone/<ecid>.shsh
Summary
- The vphone-cli restore pipeline uses
VPhoneRestoreOps.resolveECIDto identify the virtual device before any network communication occurs. - SHSH blobs are fetched via
pymobiledevice3_bridge.pyusing therestore-get-shshcommand and cached as<ecid>.shshfiles within the VM bundle. - The DFU boot sequence is triggered by the
--dfuflag inVPhoneCreateOrchestrator, preparing the VM to receive firmware payloads. - Restore execution streams IPSW components over vsock to the
vphoneddaemon, which applies the SHSH signature and flashes the device using libimobiledevice logic. - Offline restores bypass Apple's TSS servers by passing cached SHSH files via the
--tssargument to the Python bridge. - Version metadata is automatically recorded to
restore-info.jsonupon successful completion viarecordRestoreVersions.
Frequently Asked Questions
How does the Python bridge interact with Apple's TSS servers?
The pymobiledevice3_bridge.py script uses libmobiledevice bindings to construct and send a TSS request containing the device's ECID and firmware identifiers. It receives the signed SHSH blob from Apple's signing service and writes it as a plist file to the VM bundle directory, enabling cryptographic authorization of the restore process.
What files does vphone-cli modify during the restore process?
The CLI writes the SHSH blob to <ecid>.shsh in the VM directory, updates restore-info.json with version metadata via VPhoneRestoreInfo.derive, and modifies temporary AEA image caches when handling encrypted IPSW components during offline restores.
Can I perform a restore without booting into DFU mode?
No, the restore pipeline specifically requires the VM to be running in DFU mode initiated via --dfu or make boot_dfu. This mode disables the standard guest control channel and prepares the virtual hardware to accept the low-level restore payload streamed by vphoned.
Where are SHSH blobs cached for offline restores?
SHSH blobs are stored in the VM bundle directory as files named <ecid>.shsh, where <ecid> matches the device's unique identifier resolved during the initial VPhoneRestoreOps.resolveECID call. These files persist between operations and are referenced via the --tss parameter during offline restore execution.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →