The JB first-boot setup adds the Frida repo (deb https://build.frida.re/ ./)
next to the existing Havoc source, so Sileo/apt can install and update Frida
packages. Idempotent — skipped if a build.frida.re source is already present —
and picked up by the same insecure-repo `apt-get update` that follows.
Co-Authored-By: Claude Fable 5 <[email protected]>
On iOS 27, -[LSApplicationWorkspace registerApplicationDictionary:] (what the
first-boot `uicache -a` uses) is a deprecated no-op stub — lsd logs "You cannot
use -[LSApplicationWorkspace registerApplicationDictionary:] to register
applications anymore. These interfaces have been deprecated for years." and it
returns NO. So vphone_jb_setup.sh installs Sileo's .deb but never registers it:
the files land in /var/jb/Applications but Sileo never appears on the home
screen. There is no gate to patch here — Apple removed the implementation.
Fix: register JB apps via the modern containerized API instead.
- scripts/vpregister/vpregister.m: standalone helper that registers
/var/jb/Applications/*.app (or given paths) via
registerContainerizedApplicationWithInfoDictionaries:...:registrationError:,
treating a nil error as success (it returns NO even when it registers). Works
once lsd's embedded-reg gate is patched (cfw_patch_lsd_embedded_reg, applied
by cfw_install.sh, which cfw_install_jb.sh and cfw_install_exp.sh both chain).
It lives in its OWN dir (scripts/vpregister/), NOT scripts/vphoned/, so it is
not swept up by the `scripts/vphoned/*.m` globs that build vphoned
(cfw_install.sh, cfw_install_dev.sh, and the vphoned Makefile all glob that
dir) — otherwise its main() collides with vphoned's ("duplicate symbol
'_main'"). Built separately by the JB/EXP installers.
- cfw_install_jb.sh / cfw_install_exp.sh: build + sign (vphoned entitlements +
CFW signcert) + deploy vpregister to /cores.
- vphone_jb_setup.sh: after dpkg + uicache -a, invoke /cores/vpregister to
register JB apps via the containerized path. Guarded by [ -x ].
vpregister verified on 17,3_27.0_24A5380h + cloudOS 26.4 (JB): registers Sileo
via the containerized API (uicache -l 0->1) on the gate-patched VM. The exact
cfw_install.sh vphoned build (VPHONED_SRCS glob + clang) now links cleanly with
vpregister.m relocated. Doc: item 12 in research/0_binary_patch_comparison.md.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_013pk5tsoBeuu3jhkmnRFtic
Fetch debs listed in debs.list into a cached debs/ dir (skipping already
-cached files, honoring manually-added ones), stage the whole cache into
the per-boot preboot dir alongside Sileo, and install on first boot.
- fetch_debs.sh: manifest fetch, atomic download, non-fatal on failure,
chowns cache back to invoking user under sudo
- cfw_install_jb.sh / cfw_install_exp.sh: fetch + stage into $BOOT_HASH/debs
- vphone_jb_setup.sh (5b): idempotent install — skip packages already at
>= the staged version, install the rest in one dpkg -i so inter-package
deps resolve in a single pass
- debs.list tracked manifest; debs/ cache gitignored
Co-Authored-By: Claude Opus 4.8 <[email protected]>
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
Create .bashrc and .bash_profile for /var/root so SSH sessions
(both login and non-login) source /var/jb/etc/profile for the
full JB PATH. Adapted from #144 to the new vphone_jb_setup.sh
architecture introduced in #141.
Co-authored-by: McNight <[email protected]>
* 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]>