Commit Graph
39 Commits
Author SHA1 Message Date
zqxwceandClaude Fable 5 ceccc126c8 tests: Add Frida encoder/version-gate tests
- ARM64Encoder round-trips (TBZ/TBNZ bit retarget, movz flag clear) and the
  cloudOS 26.4 version-gate compare.
- Reveal procedures and static/runtime validation for both kernel patches;
  patch-comparison table rows JB-23b / JB-25c and the opt-in note.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-08-12 11:40:24 +03:00
ZomkaDEV 334a558e32 fix: treat LSD embedded-reg gate as idempotent when already NOP'd 2026-08-11 15:05:35 +03:00
zqxwceandClaude Opus 4.8 f48fc29a27 cfw: Patch os_lockdown_mode_enabled to not crash on iOS 27b5
iOS 27's os_lockdown_mode_enabled() resolves Lockdown Mode via
sysctlbyname("security.mac.lockdown_mode_state_public", ...) and os_crashes
on a -1 return. The vphone base kernel (cloudOS 26.x) does not implement that
MAC sysctl, so the call returns -1/ENOENT and the first daemon to query
Lockdown Mode after "Continuing system boot" -- launchd (pid 1) -- aborts,
panicking the system (initproc exited, namespace 2 subcode 6).

Add cfw_patch_lockdown_mode.py: NOP the `cmn w0,#1; b.eq <os_crash>` gate so
the pre-zeroed output buffer path is taken (Lockdown Mode = disabled);
behavior-neutral on a kernel that implements the sysctl. Wire it into cfw.py
(patch-lockdown-mode) and the cfw_install.sh 27.* DSC-patch block. Also fixes
the 0_binary_patch_comparison.md LWCR note and adds row 16.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01N2bwKrGJWY7o2ArdxibVPe
2026-08-11 14:50:22 +03:00
31772b3818 cfw: Add opt-in --force-exc-guard for the EXC_GUARD Mach-port-guard patch
On 26.x bases the EXC_GUARD (Mach port guard) disable patch is not required
to boot, so it is no longer applied unconditionally on regular/jb/exp.
Production apps shipping crash-reporting/RASP SDKs (Bugly, Crashlytics,
KSCrash) call task_swap_exception_ports(), which the research kernel enforces
as a fatal GUARD_TYPE_MACH_PORT violation on launch; a --force-exc-guard flag
(FORCE_EXC_GUARD=1 in the Makefile) re-enables the patch for those cases.

iOS 18 bases and the dev variant keep the patch always-on, since both need it
to boot. The documented violation is corrected from SET_EXCEPTION_BEHAVIOR to
KOBJECT_REPLY_PORT_SEMANTICS, matching the actual reproduction crash logs.

Also add /vm-*/ to .gitignore for multi-VM directories.

Co-authored-by: Paulo Sarrin <[email protected]>
Co-authored-by: zqxwce <[email protected]>
Co-Authored-By: Claude Fable 5 <[email protected]>
2026-07-26 08:57:27 +03:00
zqxwceandClaude Fable 5 c9ad3c7519 cfw: dsc: Add FORCE_DSC_MAXSLIDE opt-in to zero maxSlide on non-27 bases
patch-dsc-maxslide self-gates to a no-op when the shared cache fits the
vphone600 26.x kernel's 6 GiB region, which 26.x/18.x bases always do, so
it only fires on 27. Add a --force flag that bypasses the fits-check and
zeroes maxSlide unconditionally (still idempotent), and a
FORCE_DSC_MAXSLIDE=1 env opt-in in cfw_install.sh that runs it on non-27
bases. Default off; 27 behavior unchanged.

Also fix the installer env-threading in cfw_install_host.sh: a
${VAR:+NAME=val} word produced by expansion is not parsed as a shell
assignment (zsh runs it as a command), so route the assignments through
env. This makes FORCE_DSC_MAXSLIDE reach the installer and repairs the
same latent bug for SPOOF_BUILD.

Verified on a 26.4 JB VM: FORCE_DSC_MAXSLIDE=1 yields on-disk maxSlide=0
and a live shared-cache slide of 0x0 (dyld maps the cache at its
preferred base 0x180000000 in rpcserver_ios), versus the nonzero slide a
stock 26.4 boot picks.

Docs + research/0_binary_patch_comparison.md updated (README and the ja/ko/zh
translations).

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-07-23 17:46:40 +03:00
zqxwceandClaude Opus 4.8 fac586a95d cfw: jb: Fix iOS 27 random resprings (FileProvider-scoped vnode_check_open)
The JB blanket-neuters Sandbox mpo_vnode_check_open (ops[267] -> allow) so
processes can read /var/jb. FileProvider's fpfs parent-walk relies on the stock
check's EACCES at the domain-container boundary as its terminus; with it
neutered the walk climbs unbounded and ResolverService balloons (~12 GB) ->
vm-compressor-space-shortage jetsam -> backboardd killed -> respring
(27b4/24A5390f).

Keep the global bypass, enforce the real check for the FileProvider daemons
only. On iOS 27, ops[267] is left un-neutered (removed from the JB-09 blanket
list) and retargeted to a code-cave trampoline: inline current_proc
(tpidr_el1 -> uthread+0x3F0 -> proc+0x18), read p_comm (+0x56C), and for
ResolverService/fileproviderd branch to the real vnode_check_open, else return
allow. Register-only, no frame/call. Gated to a 27.x base via applyIOS27; other
bases keep the blanket neuter.

Verified: cave disasm + branch targets correct (final b -> real
vnode_check_open); 26.5 kernelcache byte-identical pre-vs-post (ops[267] stays
neutered there). Documented as JB-29 in research/0_binary_patch_comparison.md.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01YNySXhjsxhFG9yZMBHJUqY
2026-07-23 16:50:41 +03:00
zqxwceandClaude Fable 5 0827e0ad53 cfw: jb: Fix iOS 27 daemon crash-loop (libxpc LWCR self-check abort)
iOS 27 XPC servers pin a Lightweight Code Requirement on their listener
(xpc_connection_set_peer_lightweight_code_requirement / the Swift
XPCPeerRequirement.hasEntitlement wrapper). Creating one self-checks via
libxpc _xpc_token_satisfies_lwcr, whose matcher returns a "matched" bool
plus a match_result.error_code and then hard-asserts they agree
(matched == (error_code == AICMR_MATCH), where AICMR_MATCH == 0) via
_os_crash_msg -> brk #1.

Under our JB code-signing environment the matcher writes error_code =
MATCH(0) but returns a failure status, producing the forbidden
(matched=0, error_code=0) pair, so libxpc aborts. Every daemon that pins
an entitlement peer-requirement at startup crash-loops continuously from
boot: intelligencetasksd, searchpartyd, transparencyd, bluetoothd, ...

Fix (cfw_patch_xpc_lwcr.py, 27.*-gated in cfw_install.sh, self-gating on
the symbol): derive "matched" from error_code and drop the abort. The
three instructions "cset w8,ne; eor w8,w0,w8; tbz w8,#0,<abort>" become
"cset w0,eq; nop; nop". The function then returns (error_code == 0),
reproducing stock behavior when the two agree and resolving the
contradiction toward "satisfied" when error_code says MATCH; genuine
allow/deny (error_code != 0) is unchanged. Symbol resolved from the DSC
.symbols table, site located by control-flow shape (Capstone),
replacements from Keystone, modified 16 KiB page re-attested
(cfw_dsc_codesign; CDHash change accepted by the JB AMFI cdhash-trust
patch).

Validated on 17,3_27.0_24A5390f + cloudOS 26.4 (JB, host-mount deploy):
the four crash-loopers disappear from the crash census after boot;
launchd (which links libxpc) boots clean past first unlock.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-07-23 16:50:41 +03:00
zqxwceandClaude Opus 4.8 decda02ab4 cfw: jb/exp: Fix iOS 27 Campo crash-loop (sandbox mach-lookup exceptions)
iOS 27's Campo (wallpaper renderer) runs under the temporary-sandbox profile
(its own com.apple.private.sandbox.profile:embedded + no-container). On the 26.4
vphone600 kernel that builtin profile predates 27 and denies the backboard/
frontboard launch mach-services, so BKSDisplayServicesStart and then
+[BKSHIDEventDeliveryManager sharedInstance] fail their mach-lookups, log
"backboardd isn't running -- or we couldn't talk to it", and brk ~34ms after
launch -> continuous crash-loop, no wallpaper. JB-02d's container-upcall
force-success stops the exec-time autobox kill but does not grant these services.

Grant them through Campo's own com.apple.security.exception.mach-lookup.global-name
array (the sanctioned escape hatch, honored by temporary-sandbox -- Campo already
ships ~20 such exceptions; these launch services just aren't among them because
27's profile allows them directly). Applied at host-mount build time as step
JB-3b in cfw_install_jb.sh / cfw_install_exp.sh, re-signed with signcert.p12 via
ldid_sign_ent. The service list is merged by the external helper
scripts/patchers/campo_mach_lookup_exceptions.py (plistlib, not plutil -- the
entitlement key's dots would break plutil keypaths).

Hard-gated to 27.* on the mounted rootfs SystemVersion.plist (same gate as the
vpregister/DSC patches): skipped on 26.x/18.x, which don't need it and where
Campo.app also exists.

Verified on-device (17,3_27.0_24A5390f + cloudOS 26.4, JB): Campo launches and
stays up, no BKSDisplayServicesStart/BKSHIDEventDeliveryManager trap. Documented
as entry #14 in research/0_binary_patch_comparison.md.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_014McnrLRb5cZsTrpcBkvkj3
2026-07-23 16:50:41 +03:00
zqxwceandClaude Opus 4.8 9becab4031 cfw: Fix iOS 27 DDI (/System/Developer) auto-mount
Productionize the 3-part fix that makes `pymobiledevice3 mounter auto-mount`
land the personalized DDI at /System/Developer on the iOS-27-userland /
26.4-vphone600-kernel (c0ecdb4b) JB hybrid.

- KernelJBPatchDiskImages2.swift (new; wired into KernelJBPatcher.findAll):
  DiskImages2 ABI acceptance. GATE1/GATE2b NOP the CreateDevice/Connect
  cmp#9/b.ne ABI-version rejects (kernel driver v9 vs iOS-27 controller/daemon
  v11). GATE2 widens the RegisterNotificationPort backing array + both
  bound-check field loads (all-or-nothing) to clear the `type < getMaxPorts`
  off-by-one that otherwise fails the attach ("Can't register notification
  port").
- KernelJBPatchSandboxExtended: retarget mac_policy_ops[124]
  (mpo_proc_check_syscall_unix) to the allow stub so MobileStorageMounter's
  mount_apfs can make the mount(2) syscall (unix 167) — else the kernel
  Sandbox denies it ("Protobox: mount_apfs deny(1) syscall-unix 167").
- cfw_patch_diskimagesiod.py + cfw.py + cfw_install.sh (gated to 27.*):
  force -[DIDiskArb isMountCompleteWithExpectedCount:diskTracker:] -> YES so
  MobileStorageMounter's waitForDAMount returns and it performs the real
  nobrowse mount.

GATE2a anchor fix (the critical one): Capstone on this toolchain decodes the
AllocPortsArray size-shift lsl-immediate (a UBFM alias) as 2 operands, not the
xd,xn,#imm 3-operand shape. The original 3-operand + imm==3 match found 0, so
the all-or-nothing silently skipped GATE2 on every build (only manual dd pokes
ever worked). Now matched on mnemonic + destination x1 — the unique
size-writing lsl in AllocPortsArray; the replacement is a fixed mov x1,#0x4000
so the shift amount is irrelevant. Verified from a clean build on c0ecdb4b via
`patch-component --component kernel-jb --records-out`: all five di2 records
emit (createdevice, connect, allocports_size, notif_boundcheck_d8/e8), and
`pmd3 mounter auto-mount` -> rc=0 with the DDI mounted, no poke.

Documented in research/0_binary_patch_comparison.md (JB-09, JB-28, CFW
binary-patch #13).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_013pk5tsoBeuu3jhkmnRFtic
2026-07-20 16:20:34 +03:00
zqxwceandClaude Opus 4.8 de725d26aa cfw: Fix iOS 27 Sileo-at-setup — register JB apps via containerized LS API (vpregister)
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
2026-07-20 16:20:34 +03:00
zqxwceandClaude Opus 4.8 82485d988d cfw: Fix iOS 27 app registration — patch lsd embedded-reg gate + vphoned containerized fallback
iOS 27 lsd gates app (re)registration behind
-[_LSDModifyClient clientIsEntitledForEmbeddedRegistrationOperations], an
XPC-peer entitlement check for one of three privileged entitlements
(coreservices.lsaw / installcoordinationd.daemon /
coreservices.can-register-install-results). Missing -> NSOSStatusErrorDomain
-54 (permErr, LSDModifyService.mm:1639), so registerApplicationDictionary: and
registerContainerizedApplicationWithInfoDictionaries: fail and no app can
register — blocking vphoned's installer, TrollStore, and uicache/Sileo. The
entitlement route is unsatisfiable: LS registration is proxied, so the peer lsd
inspects is not the caller (even vphoned with all three in its validated csblob
is rejected).

Fix (two parts):
- cfw_patch_lsd_embedded_reg.py: NOP the gate's final cbz so the check always
  returns YES + re-attest the 16 KiB page (TXM per-page). Wired into cfw.py
  (patch-lsd-embedded-reg) and cfw_install.sh (after patch-dsc-maxslide);
  self-gates on pre-27 userlands (method absent). Method resolved via the DSC's
  own .symbols in-image table (ipsw symaddr/a2s time out on this cache), gate
  located by control-flow shape (cbz/cbnz w0 whose fall-through sets the
  mov w<reg>,#1 result), NOP bytes from Keystone. New CDHash accepted by the JB
  always-true AMFI cdhash-trust patch.
- vphoned vp_register_path: fall back from the (still-gated) plain
  registerApplicationDictionary: to the containerized registration API, which
  works once the gate is patched (treat a nil registrationError as success
  since it returns NO even when it registers).

Verified on 17,3_27.0_24A5380h + cloudOS 26.4 (JB): -54 gone, Sileo registers
(uicache -l 0->1), vphoned installs+registers a test IPA (com.vphone.vptest) to
/var/containers/Bundle/Application end-to-end; clean boot (re-attest correct).
Documented as 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
2026-07-20 16:20:34 +03:00
zqxwceandClaude Opus 4.8 84f4887056 kernel: jb: Add container-manager exec-upcall force-success (iOS 27 wallpaper/temporary-sandbox fix)
The 26.4 vphone600 kernel resolves each process's containers at exec via a
synchronous MIG upcall to containermanagerd over the container-manager host
special port (HOST_CONTAINERD_PORT). iOS 27 DELETED this kernel-side upcall (the
stock 27 kernel has no HOST_CONTAINERD_PORT / CM_KERN_* protocol — container
resolution moved out of the kernel), so 27's containermanagerd no longer
implements the reply server. On the 26.4 kernel running a 27.0 userland the
upcall therefore fails (MACH_SEND_INVALID_DEST) for every platform app -> they
are autoboxed into the restrictive `temporary-sandbox` profile, which denies
mach-lookup com.apple.backboard.display.services -> Campo (the wallpaper
renderer) crash-loops (no wallpaper), plus intelligencetasksd / feedbackd.

Re-registering the host special port is a confirmed dead end: the 26.4 kernel
then SENDS the MIG request and BLOCKS for a reply 27 cannot produce -> early-boot
deadlock (SpringBoard never comes up).

Fix (patchContainerManagerUpcall): flip the `cbz w0,<success>` guard in
_hook_cred_label_update_execve (taken when the upcall returns 0) to an
unconditional `b <success>`, so a failed upcall takes the success path instead
of autobox/kill. Anchored structurally on the "failed to upcall to
containermanagerd" string xref (-> the cbz immediately before the string-load
adrp, preceded by the upcall bl, unique backward branch); replacement b from the
Keystone-backed ARM64Encoder. No-op-in-effect for version-matched userlands
(there the upcall succeeds, so the original cbz already branches to <success>).

- new: sources/FirmwarePatcher/Kernel/JBPatches/KernelJBPatchContainerUpcall.swift
- KernelJBPatcher.findAll: call patchContainerManagerUpcall after
  patchExecSecurityPolicyKill
- cfw_install.sh: document the port-25 launchd-cache approach as a dead end
  (no active code)
- research/0_binary_patch_comparison.md: add row JB-02d

Validated on-device (iPhone17,3 27.0 24A5380h + cloudOS 26.4 c0ecdb4b, JB):
iOS 27 wallpaper renders, Campo/SpringBoard/backboardd stable, clean boot (no
freeze, no panic). Patcher-level (patch-component --component kernel-jb on the
pristine 26.4 kernelcache): finds 0x1AB0654 cbz w0 -> b 0x1ab0564, emits record
container_manager_upcall_force_success, byte-identical to the on-device-validated
host-poke.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_013pk5tsoBeuu3jhkmnRFtic
2026-07-20 16:20:34 +03:00
zqxwceandClaude Opus 4.8 9c1227f89b kernel: jb: Fix iOS 27 native VZ-view display (force the kern present path)
iOS 27 userland on the 26.4 vphone600 kernel booted with a working GUI over the
in-guest TrollVNC capturer, but the normal vphone-cli window (the host VZ view)
stayed black. Root cause, proven at the instruction level in the 27.0 DSC
IOMobileFramebuffer: the host VZVirtualMachineView is fed by the guest
AppleParavirtGPU scanout, which the 26.4 kernel drives ONLY from the IOMFB
userclient SwapEnd (external method 5) -- the `_kern_Swap*` path that 26.x used
(and that the SwapEnd size patch fixed on 26.0/18.x). iOS 27 defaults the
paravirt display's present to IOMFB's parallel `_virt_Swap*` path: `_virt_SwapEnd`
performs no userclient call -- it invokes an in-process callback and hands the
composited IOSurface to a virtual-display consumer -- so frames never enter the
kernel userclient and the paravirt GPU never scans out (live AppleParavirtGPU
scheduler sat idle). TrollVNC still saw frames because it captures the composited
surface in-guest, independent of the paravirt scanout.

Fix = force the display's present back onto the kern/method-5 path, in two halves:

Userland (DSC), new patcher cfw_patch_iomfb_force_kern.py (cfw.py +
cfw_install.sh, 27-gated): the public `_IOMobileFramebufferSwap*` entrypoints are
thin dispatch trampolines (`cbz x0; ldr xN,[x0,#slot]; cbz xN; braaz xN`) that
tail-call a per-connection swap fp (kern or virt impl). Rewrite each trampoline's
first instruction to `b _kern_Swap<Name>` -- args untouched, so this is
behaviourally identical to the connection having selected the kern fp. Fully
dynamic: public + `_kern_` addrs resolved by name via `ipsw dyld symaddr`,
trampoline shape verified by Capstone, branch bytes from the Keystone `asm_at()`
helper, modified DSC code pages re-attested. Runtime: 31 entrypoints retargeted,
4 non-trampoline setters left on virt, required {SwapBegin,SwapEnd,SwapSetLayer}
present.

Kernel (KernelJBPatchIomfbSwap, re-enabled in KernelJBPatcher.findAll): iOS 27's
native SwapEnd struct is 0x6e0 bytes (26.x sent 0x588) and the 26.4 userclient
exact-checks 0x588 in two places, so method 5 would return kIOReturnBadArgument.
patchIomfbSwapEndVariableSize flips the dispatch-table checkStructureInputSize
0x588 -> kIOUCVariableStructureSize; patchIomfbSwapEndHandlerSize retargets the
handler's internal `cmp w2,#0x588` -> #0x6e0. 27's IOMFBSwapRec prefix matches
26.x, so the paravirt swap handler reads valid fields. patchParavirtDisplayPrimary
stays disabled (wrong theory, harmful -- see JB-02c).

Validated on-device (17,3_27.0_24A5380h + cloudOS 26.4 c0ecdb4b, JB): clean boot,
no kIOReturnBadArgument / SwapEnd rejection / SECURITY_POLICY kill / panic, and
the iOS 27 userland now renders AND is interactive in the native VZ view.

research/0_binary_patch_comparison.md: DSC-patch item 9 corrected (27 no longer
size-truncated), new item 11 (force-kern), JB-26/27 rows added, all marked
validated.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_013pk5tsoBeuu3jhkmnRFtic
2026-07-20 16:20:34 +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 Opus 4.8 679d3d0476 kernel: jb: Bypass exec ip_mac_return SECURITY_POLICY kill for newer userlands
Running iOS 27.0 userland on the 26.4 vphone600 kernel, every core platform
daemon (backboardd, cfprefsd, containermanagerd, locationd, CommCenter, ...)
died 3-5ms after xpcproxy spawn with exit reason namespace 9 / code 0x8
(OS_REASON_EXEC / EXEC_EXIT_REASON_SECURITY_POLICY). launchd throttled the
respawns and the boot deadlocked (all CPUs idle) before SpringBoard — no UI,
no networking. Root cause: AMFI's exec MAC hooks reject the 27.0 binaries'
code-sign validation category on the 26.4 kernel, setting imgp->ip_mac_return,
and XNU's exec path (kern_exec.c) SIGKILLs on `if (imgp->ip_mac_return != 0)`.

patch_exec_security_policy_kill flips the `cbz wN, <skip>` guard preceding the
os_reason_create(9,8) call to an unconditional `b <skip>`, making the kill block
unreachable — downstream of AMFI/TXM, so it covers the validation-category
reject regardless of which hook set the verdict. Anchored structurally (movz
w0,#9 ; movz w1,#8 preceded by ldr wN,[xM,#imm] ; cbz wN,<fwd>; W-register cbz
distinguishes the ip_mac_return site from the subsystem-root sibling). No-op in
effect for version-matched userlands (ip_mac_return == 0, so the cbz already
skips). Wired into the JB Group C dispatcher.

Validated on iPhone17,3_27.0_24A5380h + cloudOS 26.4 (c0ecdb4b): 0 SECURITY_POLICY
kills, core daemons launch, networking + SSH (dropbear :22222) come up. Remaining
gate: sandbox denies backboardd the IOMobileFramebuffer/IOSurface user clients,
so SpringBoard traps in FBSDisplayMonitor init (no display) -> UI not up yet.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_013pk5tsoBeuu3jhkmnRFtic
2026-07-20 16:20:34 +03:00
zqxwceandClaude Opus 4.8 a38fd3201f cfw: Fit iOS 27 dyld cache in the 26.x kernel shared region (maxSlide=0)
iOS 27.0's dyld shared cache (~5.95 GiB span) plus its 512 MiB header maxSlide
overflows the vphone600 26.x kernel's fixed 6 GiB shared region
(SHARED_REGION_SIZE_ARM64 = 0x180000000). At map time the kernel reserves
span + maxSlide, so _shared_region_map_and_slide returns ENOMEM, dyld cannot map
libSystem, and launchd (pid 1) panics at boot ("initproc failed to start").

Add cfw_patch_dsc_maxslide: zero the dyld_cache_header maxSlide (@0xF0) in the
main chunk when span + maxSlide exceeds the region, so the cache maps at slide 0
(iOS 27.0 fits with ~58 MiB spare). Self-gating (no-op for 26.x/18.x, which fit
with full slide) and no page re-attestation (header metadata, not a cs_validate'd
code page). Wired into cfw_install.sh after the IOMFB SwapEnd gate, so it applies
to regular/jb/exp (jb/exp run cfw_install.sh as their base).

Validated on iPhone17,3_27.0_24A5380h userland + cloudOS 26.4 (c0ecdb4b) JB:
dyld cache maps system-wide, launchd reaches first unlock, vphoned connects as
iOS 27.0.0, 0 panics.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_013pk5tsoBeuu3jhkmnRFtic
2026-07-20 16:20:34 +03:00
zqxwceandClaude Opus 4.8 8781e20c76 cfw: iBoot: disable skywalk fsw netagents on iOS 18 (if_attach_nx=0x3)
iOS 18.6.2 userland on the 26.1 vphone600 kernel has no working DNS: the
guest gets a correct resolver config (DHCP hands out 192.168.64.1, which
configd propagates to State:/Network/Global/DNS) and the path works (raw
UDP DNS to the gateway succeeds), but getaddrinfo fails EAI_NONAME because
mDNSResponder crash-loops. Every crash is identical: EXC_BREAKPOINT in
os_channel_create_extended, hit from Network.framework flow setup
(nw_channel_create_with_attributes). That is a skywalk userspace-channel
trap: the 26.1 kernel advertises skywalk, Network.framework tries to create
a flowswitch channel for its DNS flow, the channel-create syscall trips a
fatal trap in the 18.6.2 libsystem_kernel, and the resolver daemon dies.
26.x userland handles this path; 18.6.2 does not.

Fix: set boot-arg if_attach_nx=0x3 (SKYWALK_NETWORKING_BSD_ONLY =
IF_ATTACH_NX_NETIF_COMPAT | IF_ATTACH_NX_FLOWSWITCH) on iOS 18 bases. This
keeps the netif + flowswitch nexus (interface/host stack unaffected) but
leaves the FSW_TRANSPORT/IP netagents unset, so Network.framework uses the
BSD-socket path and mDNSResponder never creates the crashing channel. The
kernel boot-args come from the patched iBoot (kern.bootargs matches
IBootPatcher.bootArgs), so the arg is baked into the iBEC/LLB boot-args
patch, not the host NVRAM (which iBoot overrides).

- IBootPatcher gains `extraBootArgs`, inserted before the trailing %s in
  the patched boot-args string (ibec/llb).
- FirmwarePipeline sets extraBootArgs="if_attach_nx=0x3" for iOS 18 bases
  (iosBaseIs18), empty otherwise, on the iBEC and LLB factories.

Gated to iOS 18 bases: 26.x keeps the stock boot-args and is untouched.
Validated at runtime first (setting net.link.generic.system.enable_netagent
=0 makes DNS resolve reliably), then confirmed end-to-end on a fresh
17,3_18.6.2_22G100 jb restore: kern.bootargs shows if_attach_nx=0x3 and
DNS/networking works.

Documented in research/0_binary_patch_comparison.md (iBEC/LLB boot-args row).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Q7gbWrtKLu8rFGmpXHmu9t
2026-07-13 15:40:44 +03:00
zqxwceandClaude Fable 5 911152881e kernel: apply EXC_GUARD (Mach port guard) disable for iOS 18 bases
iOS 18.6.2 userland on the 26.1 vphone600 kernel crash-loops
runningboardd and SpringBoard, so the UI never takes over from the boot
logo. Crash reports show EXC_GUARD / GUARD_TYPE_MACH_PORT "flavor 10":
the 26.1 kernel fatally enforces a Mach port guard that iOS 18's older
userland trips (hardening the 18.x daemons predate).

The existing patchExcGuardBehavior() (kernel patch 27,
thread_guard_violation -> RET) fixes exactly this but was gated to the
dev variant only. Wire it to also apply on regular/jb/exp when the
iPhone base is iOS 18:

- FirmwarePipeline reads the base ProductVersion from
  iPhone-BuildManifest.plist (fw_prepare preserves it; the live
  BuildManifest reads the cloudOS 26.1 version, not the base) and sets
  applyExcGuard for 18.* bases.
- KernelPatcher gains an applyExcGuard flag; patch 27 now runs when
  isDev || applyExcGuard.

Scoped to iOS 18 bases only — 26.x bases boot without it, never set
applyExcGuard, and are unaffected. Validated on 17,3_18.6.2_22G100:
fw_patch_jb logs "iPhone base iOS: 18.6.2 (enabling ...)" and applies
thread_guard_violation -> RET at foff 0xB4FFCC. With this plus the
display SwapEnd fix, 18.6.2 boots to the Setup Assistant UI with
runningboardd and SpringBoard stable.

The keystore AppleSEPKeyStore sel-135 UnsupportedMode seen during
bring-up turned out to be non-fatal (tolerated by the CredentialManager)
and is not needed for boot, so no keystore patch is included.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-07-13 15:40:44 +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 Fable 5 81b0cd828c [kernel-jb] disable vm_map_protect Shape B (crashes debugger on 26.4+)
The 26.5 Shape B W^X matcher (mov #5 -> #7) mis-targets vm_map.c:6202
`prot &= ~VM_PROT_WRITE` -- the copy-on-write-preservation write-strip --
instead of the RWX/ALLEXEC gate at vm_map.c:5997. Widening it keeps write on
code-page protections, so a debugger's breakpoint write lands a writable PTE on
the code frame; SPTM rejects that (VIOLATION_ILLEGAL_MAP, page_fte->type=0xf),
killing any debugged process on 26.4+.

Isolation confirmed: with cs_bypass (patch_vm_fault_enter_prepare) left enabled
and Shape B disabled, the debugger works -- Shape B was the sole cause.

Retired on 26.5+ (not retargeted): on SPTM, code modification uses write-then-flip
via vm_protect(VM_PROT_COPY) -> XNU_USER_DEBUG. The debugger, MobileSubstrate
tweaks, and the JB's own plugins (vcc_patch_two_nops in libvcamcaptured.m) all use
this path; none need non-MAP_JIT RWX. Shape A (26.1-26.4, the real ALLEXEC gate)
is unaffected.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-07-05 17:39:00 +03:00
zqxwceandClaude Fable 5 729c3b644c cfw_install: jb/exp: Flip launchd hook to opt-out via DISABLE_LAUNCHD_HOOK
Inject launchdhook into pid 1 by default again for JB/EXP; set
DISABLE_LAUNCHD_HOOK=1 to skip. Also fixes a doubled-prefix typo in
cfw_install_exp.sh that made the previous env flag unreadable there.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-07-05 15:09:22 +03:00
xiahouzhen 7c3fdf17c5 Tighten launchdhook opt-in behavior 2026-07-05 15:09:22 +03:00
xiahouzhen 6167567f12 Make launchd hook injection opt-in 2026-07-05 15:09:22 +03:00
Gilbo 3b7cf92137 Fix typo NONE_INTERACTIVE --> NON_INTERACTIVE 2026-06-22 12:15:06 +03:00
Gilbo d34c023e55 [kernel-jb] retarget hooks broken by cloudOS 26.5 kernel drift
- hook_cred_label (sudo/setuid): resolve vfs_context_current generically; uthread offset drifted to 0x3F0
- proc_security_policy: anchor on PRIV_GLOBAL_PROC_INFO (0x3EA), not the drifted `cmp #0x21` switch literal
- proc_pidinfo: match the unique guard+EINVAL+flavor-switch shape (now inlined into proc_info_internal)
- task_conversion_eval: accept the kernel_task compare in either operand order
- io_secure_bsd_root: anchor on the kIOReturnNotPrivileged deny-CSEL; drop the moved [x19,#0x11A] context
- mac_mount: match the role-state ldrb + bit-6 test (Site 2 folded into one load on 26.5)
- spawn_validate_persona: anchor on the dual sibling [#8]/[#0xc] cbz reject
- vm_map_protect: handle both the 26.1/26.3 b.ne gate and the 26.5 W^X mask register (mov #5 -> #7)
- kcall10: locate the sysent table structurally; drop the brittle _nosys tiny-stub heuristic
- add tests/test_jb_kernel_patches.sh (make test_jb_patches[, QUICK=1]) over every supported cloudOS kernel

Fixes #342.

The 26.1-derived patchset silently skipped 9 hooks on 26.5 — the pipeline only
fails a component when it emits zero patches total, so a half-patched kernel
shipped as "success" and sudo broke with 'nosuid'.

Verified across 26.1/26.3/26.4/26.5
2026-06-22 12:15:06 +03:00
zqxwceandClaude Opus 4.7 ba70b6f523 camera: libcamfix substrate plugin + Camera.app photo delivery via CAMCaptureEngine
libcamfix.dylib is loaded into Camera.app (com.apple.camera) by
TweakLoader (the .app/-rule covers Camera.app automatically; the plist
filters to Bundles=[com.apple.camera]). It bridges the vphone shm
frames from libvcamcaptured into Camera.app's normal photo + preview
pipeline so the user can take real photos via the standard shutter.

Hooks (only fire for connections backed by AVCaptureDevice uid
"vphone:vcam:0"):

  - _setActiveFormat:    substitute device.formats.firstObject when
                         the session-preset->format lookup hands us a
                         nil format (would otherwise throw at launch).
  - capturePhoto         deliver a CMSampleBuffer (built from shm) via
                         the deprecated didFinishProcessingPhotoSample
                         delegate path — kept for test harnesses that
                         use the documented AVCapturePhotoOutput API.
  - beginMomentCapture / commitMomentCaptureToPhotoWithUniqueID:
                         Camera.app's actual shutter path. Skip orig
                         (would throw), stash the delegate at begin,
                         drive a synthesized AVCapturePhoto at commit.
  - cancelMomentCaptureWithUniqueID:    no-op (orig would throw).
  - AVCaptureSession _setRunning: / _setInterrupted: setters swallowed
                         for vcam-bound sessions, and isRunning /
                         isInterrupted getters force YES / NO so
                         Camera.app's "preview live" poll keeps the
                         viewfinder visible past ~4-5 s.
  - AVCaptureVideoPreviewLayer:  scan UIApplication.windows at 1 Hz
                         for layers bound to a vcam session and pump
                         CGImage frames into layer.contents at 30 Hz.
  - AVCapturePhoto fileDataRepresentation / CGImageRepresentation:
                         when the photo we synthesized is the receiver,
                         return the JPEG / CGImage we built from shm
                         instead of asking the (non-existent) photo
                         surface to encode itself.
  - CAMStillImageCaptureRequest: dynamically add three stubs
                         (resolvedSettings, unresolvedSettings,
                         lensStabilizationSupported) so AVCapturePhoto's
                         private 27-arg init does not throw on the
                         CAM-internal request we pass in.

Synthesized AVCapturePhoto construction:
  - extract the real CAMStillImageCaptureRequest for the current uid
    from CAMCaptureEngine._resultsQueueRegisteredStillImageRequests
    (Camera.app's pending-photo dict),
  - hand-build a minimal AVCaptureResolvedPhotoSettings via
    class_createInstance + ivar writes for uniqueID + dimensions +
    empty NSArray ivars (CFRetained so the dealloc chain stays valid),
  - feed both into AVCapturePhoto's documented 27-arg
    initWithTimestamp:photoSurface:... via NSInvocation,
  - tag the photo with the JPEG bytes via objc_setAssociatedObject
    so the fileDataRepresentation hook returns them.

Full AVF + CAM internal delegate sequence fired at commit time:
willBeginCaptureBeforeResolvingSettingsForUniqueID,
willBeginCaptureForResolvedSettings, willCapturePhotoForResolvedSettings,
didCapturePhotoForResolvedSettings, didFinishProcessingPhoto:error:,
didFinishCaptureForResolvedSettings:error:,
_didFinishStillImageCaptureForUniqueID:error:, and crucially
captureOutput:readyForResponsiveRequestAfterResolvedSettings:.
Without that last "responsive ready" signal AVF's 2-deep pipeline
never frees its slots and Camera.app's shutter stops accepting
input after the 2nd capture.

Install wiring in scripts/cfw_install_exp.sh:
  - build_libcamfix() — clang -arch arm64e -fobjc-arc -Os, frameworks
    AVFoundation / CoreImage / CoreMedia / CoreVideo / Foundation /
    ImageIO / IOSurface / MobileCoreServices / Photos / QuartzCore /
    UIKit, ldid-signed.
  - [JB-4.2] scp the dylib + plist into procursus/Library/MobileSubstrate/
    DynamicLibraries (same location as libvcamcaptured) and chmod /
    chown so TweakLoader picks them up on next boot.

End state: Camera.app on EXP shows live preview from the host-supplied
vcam frames, the shutter takes real photos that get saved into Photos
via Camera.app's own pipeline (no PHPhotoLibrary back-channel), and
the shutter button keeps working across many consecutive captures.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-06-20 01:12:16 +03:00
zqxwce a1732f7191 variants: Update patch count documentation 2026-05-24 18:18:52 +03:00
zqxwce f8388d085e IBootPatcher: Add bootx-handoff patch for 26.4+ 2026-05-24 18:18:52 +03:00
zqxwce af90c9a903 userland: Add DSC hv_vmm_present byte-5 mangle with sign-in blacklist and slot reattest (EXP only)
Companion user-mode patches to the kernel-side OID rename. Mangles
byte 5 of every `kern.hv_vmm_present` cstring inside DSC dylibs EXCEPT
those in `DONT_PATCH_INSTALL_NAMES` (sign-in / device-likeness consumers,
~15 entries). Patched dylibs query the renamed OID and get the truthful
1 (graphics + accel passthrough); blacklisted dylibs keep the original
cstring, hit ENOENT on the renamed kernel, defensively cache 0 ("not
running on a VM") for sign-in / device-attestation surfaces.

- `scripts/patchers/cfw_patch_hv_vmm_dsc.py` — DSC orchestrator. Walks
  every `kern.hv_vmm_present\\0` cstring in any executable mapping,
  resolves the containing dylib via Mach-O-header walk-back +
  LC_ID_DYLIB, applies the byte-5 mangle to non-blacklisted dylibs, and
  drives slot-hash re-attestation in the chunk's `CS_CodeDirectory`.
- `scripts/patchers/cfw_dsc_chunks.py` — pure-Python helper for the
  chunked DSC layout: vmaddr<->chunk-fileoff mapping, install-name
  walk-back, byte-level read/write at a vmaddr.
- `scripts/patchers/cfw_dsc_codesign.py` — per-page SHA-256 slot-hash
  re-attestation for DSC chunks (16 KiB pages). Required on
  `codeSigningMonitor == 2` (TXM) hardware where per-page hash checks
  would otherwise SIGKILL the patched dylibs at first demand-page-in.
- `scripts/patchers/cfw_patch_hv_vmm.py` — standalone Mach-O variant of
  the cstring mangle (kept for completeness; the historical
  standalone-binary loop step was removed in favor of the
  blacklist-flip-via-kernel-rename design).
- `scripts/patchers/cfw_patch_hv_vmm_rootfs.py` — rootfs-path inventory
  shared with the install scripts (former JB-3.5 / 6.5/7 loop input).
- `scripts/patch_hv_vmm_userland.sh` — thin wrapper used by the install
  script (`dsc` and `standalone` operations; `watchdogd` is added by
  the next commit).
- `scripts/patchers/cfw.py` — new subcommands: `patch-hv-vmm`,
  `patch-hv-vmm-dsc`, `list-hv-vmm-rootfs-paths`.
- `scripts/cfw_install_exp.sh` — adds a pre-step that decrypts the
  SystemOS Cryptex AEA into the cache location `cfw_install.sh` already
  uses, mounts it, applies the DSC patch, and unmounts. The unmodified
  base `cfw_install.sh` then picks up the cached (patched) DMG.

Research docs in this commit describe the full EXP variant comprehensively
(`research/0_binary_patch_comparison.md` top-of-doc note, EXP-Only
Kernel Methods section, DSC userland subsection, plus forward references
to EXP-JB-3.5 / EXP-JB-6 / EXP-JB-7 subsections wired up by the following
commits; `research/firmware_manifest_and_origins.md` sections 9-11
similarly forward-describe the DT and build-version pieces).

JB and DEV variants are NOT affected: their install scripts don't invoke
any of this.
2026-05-18 16:14:55 +03:00
24a9acdf71 kernel: add patch 27 — disable thread_guard_violation (EXC_GUARD)
* kernel: add patch #27 — disable thread_guard_violation (EXC_GUARD)

Research kernels fatally enforce Mach port guard violations via
thread_guard_violation() → AST delivery → EXC_GUARD. This kills any
app whose crash reporting SDK (Bugly, Crashlytics, KSCrash, etc.)
calls task_swap_exception_ports() to register Mach exception handlers.
Production iOS does not enforce these fatally.

Patch strategy: locate thread_guard_violation through an anchor chain
(entitlement string → set_exception_behavior_violation → inner BL) and
replace its PACIBSP prologue with RET so it returns immediately without
recording or delivering the violation.

Closes #291

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>

* review: remove SDK mentions, add patch #27 to patch comparison table

Address PR review feedback:
1. Remove specific SDK names from KernelPatchExcGuard.swift comments
2. Add patch #27 (thread_guard_violation) to research/0_binary_patch_comparison.md
3. Update kernel base patch counts 28→29 across all references

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>

* kernel: scope thread_guard_violation patch to dev variant only

Per maintainer review, the EXC_GUARD disable patch is only needed for the
dev variant. Regular cannot sideload the affected apps at all (no developer
mode), and JB already masks the crash via its extended patch set.

Add `isDev` flag to KernelPatcher, gate patchExcGuardBehavior() on it, and
have FirmwarePipeline pass the right value per variant.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>

* Apply suggestions from code review

Co-authored-by: zqxwce <[email protected]>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
Co-authored-by: zqxwce <[email protected]>
2026-04-20 14:56:14 +03:00
zqxwce 30fcc05ca5 refactor: Move all manual clones to be submodules (#218) 2026-03-16 01:40:05 +09:00
Managed via Tart d042596cc0 Complete Swift firmware patcher parity and CLI wiring
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
2026-03-11 15:05:49 +08:00
Lakr 7514e10d06 Tidy tweakloader README and adjust table spacing
Convert README header to ATX style and add spacing/blank lines for improved Markdown readability in scripts/tweakloader/README.md. Also adjust spacing in a table row in research/0_binary_patch_comparison.md to correct alignment/formatting.
2026-03-10 12:15:44 +08:00
Felipe Cavalcanti cd389412ec Add tweakloader to jailbreak install flow (#173) 2026-03-10 11:32:08 +08:00
Lakr 47f4003836 Merge branch 'main' into feature/private-display-recorder 2026-03-07 19:30:15 +08:00
Lakr cfee3ea076 Add JB finalizer script; remove IPA signing UI
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.
2026-03-07 18:34:49 +08:00
Lakr 048f4c7cc1 docs: fix outdated patch counts, remove process investigation notes
- Update firmware variant table (CLAUDE.md, AGENTS.md): correct patch
  totals to 51/64/126, add VPhoneMenuBattery.swift, setup_venv_linux.sh,
  tail_jb_patch_logs.sh to architecture tree
- kernel_patcher_verification.md: 25→26 patches (patch_apfs_get_dev_by_role)
- kernel_patch_sandbox.py: docstring 16-25→17-26
- kernel_patch_sandbox_hooks: consolidate to single 17-26 validation file
- txm_jb_patches.md: fix txm_jb.py references → txm_dev.py
- 0_binary_patch_comparison.md: split kernel counts (28 base + 59 JB methods)
- kernel_jb_patch_notes.md: add 2026-03-06 retarget notes for bsd_init_auth,
  io_secure_bsd_root, vm_fault_enter_prepare
- Remove 7 boot investigation process notes (boot_*.md)
2026-03-07 18:23:34 +08:00
Lakr b9b462d23f JB install: use external insert_dylib, preserve launchd entitlements, deploy pre-built dylibs
- 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
2026-03-07 18:07:27 +08:00