What Post-Restore Patches Are Applied by vphone-cli?
vphone-cli applies exactly one post-restore patch that rewrites the device-tree (DT) identity properties—model, target-type, and compatible strings—after the iOS restore completes to align the virtual device with experimental hardware identifiers.
The Lakr233/vphone-cli repository provides tooling for virtualized iPhone environments, including a sophisticated patching pipeline that handles firmware modifications at different stages. While most patches are injected into the IPSW before the restore process begins, vphone-cli post-restore patches serve a specific purpose: modifying the live filesystem's device-tree after iBoot validation has completed. Only one such patch exists in the codebase, targeting the device-tree binary stored in the restored root filesystem.
The Device-Tree Identity Rewrite (EXP-JB-6)
The sole post-restore modification performed by vphone-cli is the device-tree identity rewrite, designated as step EXP-JB-6 in the installation pipeline. This patch edits three critical properties of the root device-tree node to spoof hardware identifiers without breaking the restore process.
Why Post-Restore Timing Matters
During a normal restore, iBoot's "restore-mode" validator checks the DT's model and target-type against the signed BuildManifest. If these values differ from what the firmware expects, the restore aborts. The three DT edits performed by vphone-cli are not fatal to the boot process, allowing them to be applied safely after the restore finishes, just before the virtual machine boots the root filesystem.
The Three Critical Property Changes
The post-restore patch updates the following root node properties in /mnt5/<boot-hash>/usr/standalone/firmware/devicetree.img4 (or .im4p):
root/model— Changes from the generic value (e.g.,iPhone99,11) toiPhone17,3, making the device appear as a real iPhone model to services that readhw.model.root/target-type— Switches fromVPHONE600toD47, aligning the target-type with the experimental hardware identifier used by the EXP variant.root/compatible— Re-orders the compatible strings from["VPHONE600AP", "*", "AppleVirtualPlatformARM"]to["D47AP", "VPHONE600AP", "AppleVirtualPlatformARM"]. This ensuresD47APis reported as the board identifier while keeping the originalVPHONE600APentry for kernel-kext binding.
These edits are applied in-place, preserving the original compression (LZFSE) and image layout. The operation is idempotent—re-running it on an already-patched DT results in no changes.
Source Code Implementation
The post-restore patch is implemented across multiple files in the repository, with both Python and Swift variants handling the DT binary format.
Python Implementation
The primary implementation resides in scripts/patchers/cfw_patch_post_restore_dt.py. This script parses the DT binary, performs the three property updates, and handles IMG4 container logic. It is invoked automatically during the EXP installation process.
Swift Counterpart
The file sources/FirmwarePatcher/DeviceTree/DeviceTreePatcher.swift contains a Swift parser/serializer used by the VM tooling. While the Python script performs the actual post-restore modification, the Swift code provides the same parsing capabilities and references the EXP-JB-6 step in its documentation.
Installation Pipeline Integration
The installation script scripts/cfw_install_exp.sh lists this operation explicitly as step EXP-JB-6: "post-restore DT identity rewrite (root model …)". Research documentation in research/txm_jb_patches.md and research/0_binary_patch_comparison.md further describes the patch's role in the experimental variant.
Manual Execution and Technical Details
You can run the post-restore DT patch manually using the Python script to verify changes before applying them.
Dry-Run Execution
# Run the post-restore DT patch manually (dry-run)
$ ./scripts/patchers/cfw_patch_post_restore_dt.py /mnt5/<hash>/usr/standalone/firmware/devicetree.img4 --dry-run
[.] /mnt5/.../devicetree.img4: IMG4 desc='...' payload_compression='LZFSE'
[.] DT blob: 12345 bytes
[+] model: 'iPhone99,11' -> 'iPhone17,3'
[+] target-type: 'VPHONE600' -> 'D47'
[+] compatible: ['VPHONE600AP', '*', 'AppleVirtual PlatformARM'] -> ['D47AP', 'VPHONE600AP', 'AppleVirtualPlatformARM']
[+] wrote /mnt5/.../devicetree.img4
Swift API Usage
// Swift side – DeviceTreePatcher parses the DT similarly
let dt = DeviceTreePatcher(data: dtData)
dt.patchRootModel(to: "iPhone17,3")
dt.patchRootTargetType(to: "D47")
dt.reorderRootCompatible(to: ["D47AP", "VPHONE600AP", "AppleVirtualPlatformARM"])
Pre-Restore vs. Post-Restore Patches
Understanding the distinction between patching stages clarifies why the device-tree modification occurs after restoration:
- Pre-restore patches (applied during firmware-patching): kernel DSC patches, camera patches, watchdogd changes, build-version spoofing, and other modifications that must be embedded in the IPSW before iBoot validation.
- Post-restore patches: Only the device-tree identity rewrite, which must occur after iBoot validates the BuildManifest but before the kernel boots.
No other post-restore patches are defined in the repository; all remaining modifications are applied during the firmware-patch stage to ensure they are cryptographically signed and validated correctly.
Summary
- vphone-cli contains only one post-restore patch: the device-tree identity rewrite (EXP-JB-6).
- The patch modifies three properties in
devicetree.img4:model(toiPhone17,3),target-type(toD47), andcompatible(to prioritizeD47AP). - Implementation lives in
scripts/patchers/cfw_patch_post_restore_dt.pywith a Swift counterpart insources/FirmwarePatcher/DeviceTree/DeviceTreePatcher.swift. - The patch is applied to
/mnt5/<boot-hash>/usr/standalone/firmware/devicetree.img4after restore completion to avoid iBoot validation failures. - All other patches (kernel, camera, watchdogd) are applied pre-restore during IPSW creation.
Frequently Asked Questions
Can the post-restore patch be applied multiple times safely?
Yes. The device-tree patch is idempotent. Running cfw_patch_post_restore_dt.py on an already-patched DT binary detects the current values and produces no net changes, making it safe to execute repeatedly without corrupting the filesystem.
What file path does the post-restore patch modify?
The patch targets devicetree.img4 (or .im4p) located under /mnt5/<boot-hash>/usr/standalone/firmware/ on the restored root filesystem. The script preserves the original LZFSE compression and IMG4 container structure while editing the binary in-place.
Why must the device-tree patch occur after the restore instead of before?
iBoot validates the device-tree's model and target-type against the signed BuildManifest during the restore process. If these values were modified pre-restore, the validation would fail and abort the installation. Since the post-restore changes are non-fatal to boot, they can be safely injected after iBoot validation completes but before the kernel launches.
Are there any other post-restore patches besides the device-tree rewrite?
No. According to the source analysis of Lakr233/vphone-cli, all other modifications—including kernel DSC patches, camera system adjustments, watchdogd changes, and build-version spoofing—are applied during the pre-restore firmware-patching stage. The device-tree identity rewrite is the sole modification performed after the restore completes.
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 →