* fix: prefer project venv Python for patchers
* add: VM backup, restore, and switch support
Named backups via rsync --sparse for efficient sparse disk handling.
- vm_backup.sh: save current VM as a named backup to vm.backups/
- vm_restore.sh: restore a named backup into vm/
- vm_switch.sh: save current + restore target in one step
- Makefile targets: vm_backup, vm_restore, vm_switch, vm_list
- Documentation added to all READMEs (EN, ZH, KO, JA)
Closes#204
Made-with: Cursor
* fix: preserve caller PATH through Nix zshenv reset in cfw scripts
Nix darwin's /etc/zshenv resets PATH on every zsh subprocess,
discarding the Makefile's carefully constructed PATH (which includes
.venv/bin and /opt/homebrew/bin). This caused 'Missing Python deps'
and ldid PKCS12_parse errors during cfw_install.
Pass the Makefile PATH through _VPHONE_PATH env var (which zshenv
won't touch), and restore it at the top of each cfw_install script.
* fix(cfw_install_dev): add python resolver, use glob for vphoned sources
- Add _resolve_python3() matching cfw_install.sh so the venv python
is used instead of Nix system python (which lacks capstone/keystone).
- Replace hardcoded VPHONED_SRCS list with glob pattern to auto-pick
up new .m files (was missing 5 files: accessibility, apps, clipboard,
settings, url — causing linker errors).
* fix: amfidont uses bundle binary CDHash and .build path
make boot launches the bundle binary (.build/vphone-cli.app/Contents/
MacOS/vphone-cli), not the release binary. amfidont's --path must
cover the .app bundle location.
- amfidont_allow_vphone depends on bundle (not build)
- start_amfidont_for_vphone.sh extracts CDHash from bundle binary
- --path points to .build/ so amfidont covers .app bundle contents
* fix(preflight): prevent run_capture errexit on non-zero return
zsh set -e is global scope — set -e inside run_capture then
return 137 triggers errexit and kills the script before reaching
the assert-bootable check. Use '|| rc=$?' instead to capture
the exit code without modifying errexit state.
Run SwiftFormat on firmware patcher
Remove legacy Python firmware patchers
Fix compare pipeline pyimg4 PATH handling
Restore Python patchers and prefer fresh restore
Update BinaryBuffer.swift
Avoid double scanning in patcher apply
Prefer Python TXM site before fallback
Retarget TXM trustcache finder for 26.1
Remove legacy Python firmware patchers
Fail fast on nested virtualization hosts
Return nonzero on fatal boot startup
Add amfidont helper for signed boot binary
Stage AMFI boot args for next host reboot
Add host preflight for boot entitlements
Fail fast when boot entitlements are unavailable
Switch firmware patch targets to Swift CLI
Record real Swift firmware parity results
Verify Swift firmware pipeline end-to-end parity
Fix Swift firmware pipeline JB dry-run
Implement VM configuration manifest system compatible with security-pcc's
VMBundle.Config format, storing VM settings in config.plist.
**Manifest System:**
- Add VPhoneVirtualMachineManifest.swift with security-pcc compatible structure
- Add scripts/vm_manifest.py for manifest generation during vm_new
- Update VPhoneCLI to support --config option with CLI overrides
- Update vm_create.sh to generate config.plist with CPU/memory/screen settings
**Environment Variables:**
- CPU/MEMORY/DISK_SIZE now only used during vm_new (written to manifest)
- boot/boot_dfu automatically read from config.plist
- Remove unused CFW_INPUT variable (overridden by scripts internally)
- Document remaining variables with their usage scope
**Documentation:**
- Update README.md with VM configuration section
- Update docs/README_{zh,ja,ko}.md with translated VM configuration docs
- Update Makefile help output with vm_new options and config.plist usage
- Fix fw_patch_jb description: "dev + JB extensions"
- Fix restore_get_shsh description: "Dump SHSH response from Apple"
**Code Quality:**
- Add VPhoneVirtualMachineRefactored.swift demonstrating code-clarity principles
- Extract 200+ line init into focused configuration methods
- Improve naming: hardwareModel, graphicsConfiguration, soundDevice
- Add BatteryConnectivity enum for magic numbers
- Create research/manifest_and_refactoring_summary.md with full analysis
**Compatibility with security-pcc:**
- Platform type: Fixed vresearch101 (iPhone-only)
- Network: NAT only (no bridging/host-only needed)
- Added: ScreenConfig and SEP storage (iPhone-specific)
- Removed: VirtMesh plugin support (PCC-specific)
docs: add machineIdentifier storage analysis
Research and validate the integration of machineIdentifier into config.plist.
**Findings:**
- security-pcc stores machineIdentifier in config.plist (same approach)
- VZMacAuxiliaryStorage creation is independent of machineIdentifier
- VZMacMachineIdentifier only requires Data representation, not file source
- No binding or validation between components
**Conclusion:**
- ✅ No compatibility issues
- ✅ Matches security-pcc official implementation
- ✅ Proper handling of first-boot creation and data recovery
- ✅ Safe to use
Delete VPhoneVirtualMachineRefactored.swift
refactor: integrate machineIdentifier into config.plist
Move machineIdentifier storage from standalone machineIdentifier.bin file
into the central config.plist manifest for simpler VM configuration.
**Changes:**
- VPhoneVirtualMachineManifest: Remove machineIDFile field
- VPhoneVirtualMachine: Load/create machineIdentifier from manifest
- VPhoneCLI: Remove --machine-id parameter, require --config
- Makefile: Remove --machine-id from boot/boot_dfu targets
- vm_manifest.py: Remove machineIDFile from manifest structure
**Behavior:**
- First boot: Creates machineIdentifier and saves to config.plist
- Subsequent boots: Loads machineIdentifier from config.plist
- Invalid/empty machineIdentifier: Auto-regenerates and updates manifest
- All VM configuration now centralized in single config.plist file
**File cleanup:**
- Move VPhoneVirtualMachineRefactored.swift to research/ as reference
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: build
* fix: remove [trusted=yes] from Havoc apt source
The inline [trusted=yes] option can cause issues with Sileo's
source parser. The apt-get calls already use AllowUnauthenticated
flags, making it redundant.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: main actor crash in VPhoneControl + IPA extraction failures
VPhoneControl: pending request handlers are @MainActor-isolated closures
but were called from DispatchQueue.global() in the read loop and timeout
handler, causing dispatch_assert_queue_fail crashes. Wrap all
pending.handler() calls in DispatchQueue.main.async.
unarchive: the recent ARCHIVE_EXTRACT_SECURE_* hardening (ef02d50) broke
IPA extraction on iOS because:
- SECURE_NOABSOLUTEPATHS: we set absolute output paths on entries
- SECURE_SYMLINKS: iOS system paths (/var, /tmp) are symlinks
- archive_write_header failures were silently swallowed due to if/else if
structure, making extraction report success with no files extracted
Fix by keeping only SECURE_NODOTDOT, resolving symlinks in extraction
path, fixing header error handling, removing unnecessary ACL/FFLAGS
flags, and surfacing libarchive errors in the install response.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* remove dropbear SSH daemon from guest
Drop all dropbear setup: LaunchDaemon plist injection, host key
generation, daemon deployment, and SSH availability messages.
Guest communication is handled by vphoned over vsock.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: liblaunch compat stub + automatic JB first-boot setup
liblaunch_compat.dylib: stub exporting _launch_active_user_switch
(missing from PCC VM's libSystem.B.dylib) so procursus binaries
like launchctl can load. Deployed to /cores/, loaded via
DYLD_INSERT_LIBRARIES in LaunchDaemon environment and JB profile.
vphone_jb_setup.sh: first-boot script replacing the SSH-based
cfw_install_jb_post.sh. Runs as a LaunchDaemon on first normal
boot and performs all JB finalization: /var/jb symlink,
prep_bootstrap, markers, Sileo, apt setup, TrollStore Lite.
Idempotent with done marker. Logs to /var/log/vphone_jb_setup.log.
Removes the cfw_install_jb_finalize make target and the entire
SSH/iproxy/sshpass-based post-boot flow from setup_machine.sh.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: update AGENTS.md firmware table, gitignore build artifacts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: launchctl wrapper uses absolute path + timeout to prevent hangs
- Use absolute path to launchctl.real instead of relative dirname,
fixing "not found" when called via /var/jb/bin/launchctl symlink
- Add 5s timeout so launchctl doesn't hang when launchd is
unresponsive on PCC VMs — always exits 0 for dpkg postinst compat
- Symlink /var/jb/bin/launchctl -> /var/jb/usr/bin/launchctl so both
paths work (openssh postinst uses the /bin/ path)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: replace liblaunch_compat dylib stub with iosbinpack64 launchctl symlink
Procursus launchctl crashes on PCC VMs due to missing
_launch_active_user_switch symbol. Rather than a custom dylib stub,
simply symlink iosbinpack64's launchctl into /var/jb — it talks to
launchd fine and always exits 0, which is all dpkg scripts need.
- Remove liblaunch_compat.c, its build target, signing, and deployment
- Remove DYLD_INSERT_LIBRARIES from setup script and plist
- Replace launchctl wrapper with symlinks to /iosbinpack64/bin/launchctl
- Both /var/jb/usr/bin/launchctl and /var/jb/bin/launchctl are covered
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Add scripts/cfw_install_jb_post.sh — an idempotent SSH-based finalizer to complete JB bootstrap on a normally-booted vphone (creates /var/jb symlink, fixes ownership, runs prep_bootstrap, creates markers, installs Sileo, and runs apt; requires sshpass). Add Makefile help, .PHONY and target cfw_install_jb_finalize to invoke the script. Remove host-side IPA signing/installing and related UI: delete VPhoneSigner, VPhoneIPAInstaller, VPhoneMenuInstall and remove signer/ipaInstaller fields and menu items/callbacks from the vphone-cli UI (also removed the DevMode enable WIP flow). Misc: minor table/formatting tweaks in AGENTS.md and research docs.
- Replace Python cfw_inject_dylib.py with tyilo/insert_dylib (built by setup_tools)
- Use --weak flag for LC_LOAD_WEAK_DYLIB injection (avoids crash on missing dylib)
- Preserve original launchd entitlements on re-sign (fixes "operation not permitted")
- Deploy dylibs from pre-built basebin payload instead of building from source
- Remove launchdhook, systemhook, treblehook sources (no longer needed)
- Print GDB debug stub port after VM starts
- Cleanup: remove test scripts, rename patch comparison doc
These were used for per-patch kernel JB debugging (C23 bisect,
single-patch boot test, batch testing). No longer needed now that
A2, C23, and C24 are all boot-tested and fixed.
Root cause: find_string("vnode_getattr") matched "%s: vnode_getattr: %d"
format string inside an AppleImage4 function. The old code then took that
function as vnode_getattr itself, causing BL to call into AppleImage4 with
wrong arguments → PAC failure on indirect branch at a2+48.
Fix: _find_vnode_getattr_via_string() now scans backward from the string
ref for a BL instruction and extracts its target — the real vnode_getattr
(sub_FFFFFE0007CCD1B4 at foff 0xCC91B4).
Bisection confirmed: variants A (stack frame) and B (+ tpidr_el1) boot OK,
variant C (+ BL vnode_getattr) panics with old resolution, boots OK with fix.
Boot-tested: full C23 patch with corrected vnode_getattr — BOOTS OK.
Introduce a set of tools for fast and batch testing of kernel JB patches: add testing_batch.sh, testing_do_patch.sh, testing_do_save.sh and testing_kernel_patch.py (plus a results _summary). Update the Makefile with new targets (testing_do_save, testing_kernel_patch, testing_do_patch, testing_batch) and PHONY entries to wire them into the build/test workflow. Modify kernel_jb.py to enable the amfi cdhash-in-trustcache patch (A1) and mark the amfi execve kill-path patch as causing PANIC (A2). These changes allow restoring a base kernel backup, applying single patches quickly, running per-patch DFU boots (with timeout/panic detection), and collecting logs for batch runs.
Introduce a new zsh helper script (scripts/testing_do.sh) and a Makefile target (testing_do) to automate the testing DFU workflow. The script sets strict error handling, kills any existing vphone-cli, runs fw_prepare, fw_patch_jb and testing_ramdisk_build, sends the ramdisk in the background, boots DFU, and tracks/cleans up child processes on exit. This simplifies and sequences the steps required to prepare, patch, send and boot the test ramdisk.
Sign patched firmware components (iBSS/iBEC/SPTM/DeviceTree/SEP/TXM/
kernelcache) into IMG4 without ramdisk or trustcache. Useful for
verifying boot chain patches in isolation.
- Add git-lfs to brew deps and document git lfs install/pull steps
in both English and Chinese READMEs
- Fix continuation line alignment in make help (off by one)
- Add missing blank line before VM management section
- Add `unlock` tool: C program dispatching IOHIDEvent to wake/unlock screen
- Rework serial port to pipes for programmatic command injection
- Auto-unlock on non-DFU boot via serial console after 8s delay
- Add "Unlock" menu item, `make unlock`/`make unlock_deploy` targets
- Defer to native VZVirtualMachineView touch on macOS 16+
- Add sshpass resolver with bundled/host fallback and arch checks
- Add gtar resolver with bundled/host/tar fallback and arch checks
- Prevent host-arch mismatches from breaking cfw_install and ramdisk_build
Closes#45, closes#46Fixes#38, fixes#41
Co-authored-by: webcpu <liang@unchartedworks.com>
Co-authored-by: tastyheadphones <tastyheadphones@icloud.com>
Add jailbreak extension patchers and targets:
- kernel_jb.py: 22 dynamic kernel patches (trustcache, execve cs_flags,
sandbox ops, task/VM, kcall10 syscall hook, ~160 total modifications)
- txm_jb.py: 13 TXM patches (CS validation, get-task-allow, debugger
entitlement, dev mode bypass)
- iboot_jb.py: iBSS nonce generation skip
- cfw.py: launchd jetsam patch, dylib injection commands
- fw_patch_jb.py: orchestrator running base + JB extension patches
- cfw_install_jb.sh: JB install phases (launchd jetsam fix, procursus
bootstrap + Sileo deployment)
3 kernel patches still WIP (nvram_verify_permission, thid_should_crash,
hook_cred_label_update_execve) — strategies documented in
researchs/kernel_jb_remaining_patches.md.
All base (non-JB) code paths verified unaffected — kernel.py produces
identical 25 patches, cfw.py base commands unchanged.
Add Linux venv setup script; tweak Makefile help
Add scripts/setup_venv_linux.sh to create a Python virtualenv on Debian/Ubuntu (or dnf-based) systems, install system packages and Python requirements, and verify core imports (capstone, keystone, pyimg4). Also update Makefile help text to mark the fw_patch_jb target as WIP. This simplifies local development setup on Linux and clarifies that the JB extension patches are a work in progress.
Update AGENTS.md: mark cfw_install_jb.sh as complete
Update README.md
Add Simplified Chinese README and link
Add README_zh-Hans.md containing a full Simplified Chinese translation of the project README and update README.md to include a link/badge to the new Chinese README. This makes the documentation accessible to zh-Hans readers.