25 Commits
Author SHA1 Message Date
zqxwceandClaude Opus 4.8 6aef60bd9a vphone-cli: Add --root-popup to elevate CFW host-mount via macOS auth dialog
* feat: add --root-popup to elevate CFW host-mount via macOS auth dialog

Adds --root-popup to `cfw install` and `vm create`, elevating the CFW host-mount through macOS's native authentication dialog (osascript -> do shell script with administrator privileges) instead of the script's sudo re-exec. do shell script runs under a bare env, so the vars the bundled scripts read are forwarded inline, plus SUDO_USER so the script's chown-back still returns artifacts to the invoking user. On `vm create`, --sudo-password takes precedence.

Co-Authored-By: Claude Opus 4.8 <[email protected]>

* cfw: remove entire .cfw_temp on install cleanup

Replaces the selective `rm -f` of individual temp binaries with `rm -rf "$TEMP_DIR"`, dropping the cached Cryptex DMGs along with the temp files.

Co-Authored-By: Claude Opus 4.8 <[email protected]>

---------

Co-authored-by: Claude Opus 4.8 <[email protected]>
2026-08-02 11:20:22 +03:00
zqxwceandClaude Opus 4.8 37ee2943c6 feat: guest restore/CFW pipeline updates for the consolidated CLI
- pymobiledevice3_bridge.py: colorized restore logs (coloredlogs.install,
  mirroring pmd3's own CLI) gated by a -v count
- cfw_install*.sh / fw_prepare.sh honor VPHONE_PYTHON/IPSW_DIR/VPHONE_SEAL_DIR
  and forward SPOOF_BUILD / FORCE_DSC_MAXSLIDE from the environment
- patch_camera_userland.sh / patch_hv_vmm_userland.sh adjustments

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Y4VDqWf5pVakcFLqB23CKe
2026-07-27 19:46:27 +03:00
zqxwceandClaude Opus 4.8 c22da90929 kernel: jb: Fix iOS 27 guest display via IOUC sandbox gate bypass
iOS 27 userland on the 26.4 vphone600 kernel had SpringBoard crash-looping
with no display. Root cause: the IOKit user-client open path runs TWO
independent MAC gates -- a MACF-aggregator check (already patched by
patchIoucFailedMacf) and a separate Sandbox check -- and the Sandbox gate
spuriously DENIES the render server (backboardd) its opens of
IOMobileFramebufferUserClient / IOSurfaceRootUserClient / IOHIDEventService.
27-specific: absent on a native 26.4 userland. Denied the framebuffer,
backboardd can't present (no Apple logo) and vends no main display, so
FBSDisplayMonitor asserts on a nil mainDisplay -> crash-loop.

Add patchIoucFailedSandbox (KernelJBPatchIoucSandbox.swift), mirroring
patchIoucFailedMacf: anchor on the "IOUC %s failed sandbox in process %s"
string, find the deny block (the CBNZ target enclosing the fail-log ADRP),
and rewrite its first instruction with an unconditional B to the
NotPermitted allow-proceed target. Structural anchors only, no hardcoded
offsets. No-op where the gate already allows (native 26.x userlands).

Verified: backboardd opens the framebuffer, SpringBoard runs (0 crashes),
display enumerates (LCD/primary), [CADisplay mainDisplay] resolves, and the
guest GUI renders (confirmed visible over VNC).

Disable three earlier wrong-theory display patches (kept in-tree, off in
findAll, for the record):
 - patchParavirtDisplayPrimary: setting primary=1 is actively HARMFUL on 27
   -- it becomes the display NAME suffix ("primary-1") and breaks the render
   server's exact-name match.
 - patchIomfbSwapEnd{VariableSize,HandlerSize}: iOS 27 never uses IOMFB
   method 5 (SwapEnd) for present -- confirmed by kernel trace of the real
   handler (cmp w2,#0x588) with SpringBoard actively presenting -- so these
   are irrelevant on 27 and would break 26.x's native 0x588 SwapEnd.

SwapEnd userland DSC size patch made per-base (cfw_install*, cfw.py,
cfw_patch_iomfb_swapend.py): 26.x validated, harmless on 27.

research/0_binary_patch_comparison.md updated (JB-10b added for the sandbox
gate; JB-02c corrected to disabled/wrong-theory).

Still open: the normal (VZ) render path stays black even though the guest
presents (VNC works) -- 27 uses a present mechanism the 26.4 paravirt-GPU
path doesn't receive. Tracked separately for follow-up.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-07-20 16:20:34 +03:00
zqxwceandClaude Fable 5 a67e0f3939 cfw: extend IOMobileFramebuffer SwapEnd display fix to iOS 18.x
iOS 18.6.2 userland on the 26.1 vphone600 kernel hits the same
IOMobileFramebuffer SwapEnd ABI mismatch as 26.0/26.0.1: userland sends
a smaller external-method-5 SwapEnd state than the 0x560 the userclient
expects, so SwapEnd returns kIOReturnBadArgument and the host VZ display
stays black (the guest still renders — the Apple logo is visible over
VNC, just not in the vphone-cli view). 18.6.2 sends 0x514 (26.0 sent
0x548).

cfw_patch_iomfb_swapend is already semantic + idempotent (it discovers
the source immediate and rewrites it to 0x560), so no patcher change is
needed — only the install-time gate. Extend the gate in cfw_install.sh
and cfw_install_dev.sh to fire when ProductVersion starts with 18. as
well as 26.0.

Scoped to those versions only: 26.1/26.3/26.4/26.5 match neither branch
of the gate and are unaffected. Document the widened scope in
research/0_binary_patch_comparison.md (patch row 9).

Part of ongoing iPhone17,3 18.6.2 + cloudOS 26.1 bring-up. Validated on
17,3_18.6.2_22G100: the Apple logo now renders in the vphone-cli view.
Full boot to the UI additionally needs two kernelcache fixes (keystore
sel-135 force-success and the mach-port EXC_GUARD disable) that are
validated at runtime but not yet folded into KernelPatcher — those will
be gated to iOS 18 bases so the working 26.x variants stay untouched.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-07-13 15:40:44 +03:00
Xin Huang 16663a2f5f Fix iOS 26.0 and 26.0.1 GUI boot
Patch the 26.0/26.0.1 IOMobileFramebuffer SwapEnd payload size during CFW install and document the validated 26.0, 26.0.1, and 26.1 host-install matrix.
2026-07-08 11:28:36 +03:00
zqxwceandClaude Opus 4.8 fcc30e1657 general: Remove SSH-ramdisk CFW install path; host-mount is the sole flow
The ramdisk-based install (build/send an SSH ramdisk, iproxy-forward, then
push CFW files over SSH and flip the boot snapshot with snaputil in-VM) has
been fully replaced by the host-mount path: cfw_install_host.sh mounts the
VM's Disk.img on the host, places every file locally, and flips the boot
snapshot offline via tools/apfs_snap_rename.py. This removes all remaining
ramdisk generation, delivery, and usage — no legacy fallback.

Deleted:
  - scripts/ramdisk_build.py, scripts/ramdisk_send.sh
Renamed:
  - scripts/cfw_host_mode.sh -> scripts/cfw_transport.sh (was a conditional
    "host-mode override"; now the sole, unconditionally-sourced transport)

setup_machine.sh: drop the USE_RAMDISK_CFW=1 branch and every iproxy/ramdisk
helper (usbmux UDID resolution, port picking, start/stop iproxy, wait-for-
ramdisk-ssh), all RAMDISK_*/IPROXY_* vars, the cleanup() iproxy handling, and
the orphaned cfw_install_target var. Only the host-mount cfw_install_host call
remains.

cfw_install{,_dev,_jb,_exp}.sh: delete the SSH transport (SSH_* vars, SSH_OPTS,
sshpass prereq/_sshpass/_ssh_retry, ssh_cmd/scp_to/scp_from/remote_file_exists/
remote_mount, wait_for_device_ssh_ready) and the dead ramdisk-mechanism body
blocks (snaputil snapshot flip, dropbearkey host-key pre-generation, halt-over-
SSH, CFW_SKIP_HALT). The transport is now sourced unconditionally from
cfw_transport.sh. dropbear -R generates host keys at first boot; the offline
apfs_snap_rename.py does the boot-source flip. Dropped the vestigial
CFW_HOST_MODE gate.

Also: pymobiledevice3_bridge.py (ramdisk-send command already gone), Makefile
(ramdisk targets/help/IRECOVERY_ECID removed), README + ja/ko/zh (install flow
rewritten to host-mount), AGENTS.md/CLAUDE.md architecture tree, and stale
comments in vphone_jb_setup.sh, VPhoneCLI.swift, apfs_snap_rename.py,
cfw_patch_post_restore_dt.py.

Verified booting via make setup_machine.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01XZVS9oqVNmHJzpb8mFtKJx
2026-07-06 15:15:01 +03:00
zqxwceandClaude Opus 4.8 d28754e89e cfw: Implement ramdisk-free host-mount CFW install
Add a host-mount install path that replaces the DFU + ramdisk_send +
iproxy + SSH transport: mount the VM's Disk.img volumes on the host, place
every CFW file locally, then flip the boot snapshot offline
(tools/apfs_snap_rename.py). The resulting VM is identical to the
ramdisk-installed one, minus the round-trips.

- cfw_host_mode.sh: sourced by cfw_install*.sh when CFW_HOST_MODE=1;
  overrides ssh_cmd/scp_to/scp_from/remote_mount/remote_file_exists to run
  locally against volumes mounted at $CFW_HOST_MNT/mnt{1,3,5} (host / is
  read-only, so device /mntN tokens are remapped), routes /usr/bin/tar to
  gtar (bsdtar lacks the GNU flags), and skips snaputil/dropbearkey/halt.
- cfw_install{,_dev,_jb,_exp}.sh: source the shim after their helper defs
  (host-mode is opt-in; the SSH path is unchanged). Also reword progress
  messages that assumed the ramdisk/SSH flow ("~3 minutes" scp, "to
  device", "Reboot the device") to read correctly in both modes.
- cfw_install_host.sh + `make cfw_install_host VARIANT=regular|dev|jb|exp`:
  attach the image, run the chosen installer under CFW_HOST_MODE as root,
  detach, and run the offline snapshot flip. Restores ownership of the
  host-side artifacts it creates (vm/.vphoned.signed, .cfw_temp, ...) to
  the invoking user afterward, so a later user-run `make boot` isn't
  blocked by root-owned files.

Runs as root (owners-honored mounts / chown / cp) via a sudo re-exec. No
authenticated-root/ARV change needed; mount_apfs -o rw honors owners.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01XZVS9oqVNmHJzpb8mFtKJx
2026-07-06 15:15:01 +03:00
zqxwceandClaude Fable 5 8d63bbc840 cfw/ramdisk: route hdiutil straight to sudo -A when SUDO_ASKPASS is set
When SUDO_PASSWORD is supplied, setup_machine.sh exports SUDO_ASKPASS.
Previously hdiutil ran unprivileged first (cfw_install.sh, ramdisk_build.py)
or via plain interactive sudo (cfw_install_dev/exp.sh), both of which
triggered a password prompt.

Now, when SUDO_ASKPASS is present, hdiutil goes straight to `sudo -A` so it
never runs unprivileged first and never prompts. When it is absent, every
call site keeps its original behavior verbatim.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-07-05 18:26:58 +03:00
zqxwceandClaude Fable 5 421ff3ed23 Generate dropbear host keys with ramdisk's trustcached dropbearkey
The ramdisk-time host-key pre-seed added in c6ed3a1 invoked
/mnt1/iosbinpack64/usr/local/bin/dropbearkey, an iPhone-Distribution-signed
third-party binary. Inside the SSH ramdisk its cdhash is in no active trust
cache, so AMFI SIGKILLs it (exit 137), aborting cfw_install_jb/dev.

Use the ramdisk's own /usr/local/bin/dropbearkey (from ssh.tar.gz, re-signed
and trustcached at build time), which runs and writes fresh keys to the same
Data-volume target. The first-boot generator in vphone_jb_setup.sh is
unaffected — it runs in the JB'd kernel where the iosbinpack64 binary is valid.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-07-05 14:27:33 +03:00
xiahouzhen 29d0f803d8 Harden dropbear key setup checks 2026-07-05 13:36:24 +03:00
xiahouzhen c6ed3a1732 Fix dropbear host keys on writable Data 2026-07-05 13:36:24 +03:00
zqxwce 20d3f1a217 pymobiledevice3: Replace most external tools with pymobiledevice3 2026-04-03 13:47:09 +03:00
Xin Huang 08c9cb78ee Nix PATH preservation, amfidont boot, and preflight stability (#196)
* 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.
2026-03-12 13:51:45 +08:00
cb409416af keychain: add remote keychain browser via vphoned (#169)
Co-authored-by: rezk <rezk>
Co-authored-by: Claude Opus 4.6 <[email protected]>
2026-03-10 00:48:04 +08:00
zqxwce d48ad72fa4 launch_daemons: Readd dropbear back as default in all variants (#155) 2026-03-09 01:17:02 +08:00
Felipe CavalcantiandClaude Opus 4.6 32b73cd50b Rework JB finalization: drop dropbear, auto-bootstrap on first boot (#141)
* 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 <[email protected]>

* 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 <[email protected]>

* 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 <[email protected]>

* 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 <[email protected]>

* chore: update AGENTS.md firmware table, gitignore build artifacts

Co-Authored-By: Claude Opus 4.6 <[email protected]>

* 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 <[email protected]>

* 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 <[email protected]>

---------

Co-authored-by: Claude Opus 4.6 <[email protected]>
2026-03-08 12:54:00 +08:00
LiBr b2a17f3cd1 use libarchive (#134) 2026-03-08 00:41:53 +08:00
LiBr 56451c4d53 Merge pull request #127 from lbr77/main
ipa install
2026-03-07 23:51:33 +08:00
Lakr d9c93ec703 Harden ramdisk mounts and enforce strict iproxy UDID isolation 2026-03-06 13:38:42 +08:00
Lakr e08850a45e Isolate multi-VM setup with deterministic device targeting (#119) 2026-03-06 12:47:30 +08:00
zqxwce 4cdff73e8c Merge pull request #112 from zqxwce/bugfix/debugserver-already-resigned
dev_mode: Fix exit if debugserver already patched
2026-03-06 00:01:58 +08:00
zqxwce 95a457ce30 dev_mode: Patch entitlements for debugserver 2026-03-05 11:59:46 +02:00
Lakr 62b1564e20 refactor: split patchers into base/mixin modules and format scripts 2026-03-04 15:19:17 +08:00
Lakr 641d5b5a79 Create txm_return_mechanism.md 2026-03-04 13:34:02 +08:00
Lakr 55a53e7179 Merge pull request #73 from p1atdev/ssh-retry
Add SSH retry logic to cfw_install and cfw_install_jb scripts
2026-03-04 11:07:30 +08:00