Commit Graph
257 Commits
Author SHA1 Message Date
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
zqxwceandClaude Opus 4.7 9b4e25569b camera: libvcamcaptured + cameracaptured TweakLoader allowlist + install wiring
libvcamcaptured.dylib is loaded into /usr/libexec/cameracaptured via
TweakLoader and registers a synthetic FigCaptureSource backed by the
vphone shm region. From AVF's point of view there is now a normal
"vphone:vcam:0" camera device that streams BGRA frames at the
session's requested width/height.

  scripts/vcamcaptured/                .gitignore (drop built .dylib),
                                       Makefile, libvcamcaptured.m,
                                       libvcamcaptured.plist (filter:
                                       Executables=["cameracaptured"]).

  scripts/tweakloader/TweakLoader.m    add /usr/libexec/cameracaptured
                                       to kVPhoneAllowedDaemonPaths so
                                       TweakLoader engages in a daemon
                                       (not just .app/) processes.

  scripts/cfw_install_exp.sh           build_libvcamcaptured() helper
                                       (clang + CoreMedia/CoreVideo/
                                       Foundation, ldid-signed) and
                                       new [JB-4.1] section that
                                       scp's the dylib + plist into
                                       procursus/Library/MobileSubstrate/
                                       DynamicLibraries.

Pairs with the host vphone-cli camera server + vphoned vcam vsock
listener already in this branch.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-06-20 01:12:16 +03:00
zqxwceandClaude Opus 4.7 c8de9c9cb7 camera: vphoned guest-side vcam vsock listener + shm writer
Guest-side counterpart to VPhoneCameraServer. vphoned runs inside
the VM and now hosts an extra vsock listener on port 1338 that
receives BGRA frames from the host and writes them into a memory-
mapped shm region at
/var/jb/var/mobile/Library/vphone-vcam-frame.shm with a packed
header (seq monotonic, width/height, bytes_per_row, pixel_format,
timestamp_ns, frame_index, pixels_length).

  vphoned_vcam.h        packed shm header layout + filename const.
  vphoned_vcam.m        VPVcamServer: accept loop, header parse,
                        seq-bump write, file-based debug log for
                        first-boot post-mortem.
  vphoned.m             Boot the vcam server alongside the existing
                        port-1337 control daemon.

Pairs with the host VPhoneCameraServer (1338 client) and the guest
libvcamcaptured (shm reader) added in the following commits.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-06-20 01:12:16 +03:00
zqxwceandClaude Opus 4.7 0223ad139c camera: Host-side virtual camera pipe (vphone-cli)
Mac-side feeder for the virtual camera. The host generates frames
(test pattern or video file) and pushes BGRA buffers over vsock to
the guest daemon vphoned, which mirrors them into the shm region
that the in-VM libvcamcaptured + libcamfix consume.

  VPhoneCameraServer        @MainActor vsock client to vphoned port
                            1338. Reconnects on transport failure
                            so the host can survive guest reboots.
  VPhoneFrameProducer       Test-pattern (hue-rolling gradient) and
                            VideoFile producers; emit BGRA at the
                            session's requested width/height/fps.
  VPhoneMenuCamera          Camera menu: pick source, start/stop
                            the feeder, show stream status.
  VPhoneMenuController/Connect/AppDelegate
                            Wire the menu into the existing menu
                            bar and start the server alongside the
                            other vsock services at VM boot.

End state: with a vphoned listener on the guest side, host-generated
BGRA frames appear in the shm region the camera daemon reads from.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-06-20 01:12:16 +03:00
zqxwceandClaude Opus 4.7 9bb5b87279 camera: Make Camera.app launch on EXP firmware
Three pieces of plumbing that together let Camera.app reach the
viewfinder UI on the EXP build:

1. DeviceTree: synthesize a /product/camera node so AVCaptureDevice
   discovery + permission gating finds a "front" camera slot for
   subsequent vcam injection (FirmwarePatcher/DeviceTreePatcher.swift).

2. DSC patch family in scripts/patchers/cfw_patch_camera_dsc.py:
     - NeutrinoCore short-circuit: rewrite the five
       +[_NUStyleTransfer*Processor processWithInputs:arguments:output:
       error:] class methods to `mov w0, #0; ret`. Without this Camera.app
       crashes inside NeutrinoCore the moment it tries to render the
       style picker.
     - AVCaptureDevice auth always-authorized:
       +[AVCaptureDevice authorizationStatusForMediaType:] -> `mov w0, #3;
       ret` (AVAuthorizationStatusAuthorized=3). Any process that probes
       camera authorization gets "Authorized" without going through TCC.

3. scripts/patch_camera_userland.sh + cfw.py registration so the install
   pipeline applies the two patches above against the chunked DSC during
   `make cfw_install_exp`.

Camera.app now launches and shows preview UI on EXP, even though the
actual vcam pipeline is wired up by the libvcamcaptured / libcamfix
commits that follow.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-06-20 01:12:16 +03:00
vinaykumar🍁 48c968ca1b Makefile: support absolute VM_DIR paths (e.g. external SSD) (#345)
The fw_patch* and restore_* targets built the VM directory argument as
$(CURDIR)/$(VM_DIR), which assumes VM_DIR is relative to the repo. An
absolute VM_DIR (e.g. /Volumes/ssd/vphone-vm) produced a broken joined
path like /Users/.../vphone-cli//Volumes/ssd/vphone-vm and failed with
'no such file'.

Add VM_DIR_ABS := $(abspath $(VM_DIR)) and use it for the VM directory
argument. abspath leaves absolute paths intact and joins relative ones
against CURDIR, so both the default 'vm' and absolute paths work. The
cd $(VM_DIR) targets were already absolute-safe and are unchanged.
2026-06-16 03:21:13 +08:00
Maximilian Paßandzqxwce 3b08751029 Fix Patchless for cloudOS 26.4 (#336)
* Fix Patchless for cloudOS 26.4

by dynamically matching and downloading the required apfs_sealvolume version.

* patchless: Add `seal.log` for `apfs_sealvolume` command

---------

Co-authored-by: zqxwce <[email protected]>
2026-05-28 13:55:05 +03:00
zqxwce d15d218fe2 ramdisk: Remove trollstore from RAMDISK_REMOVE list 2026-05-25 15:12:59 +03:00
zqxwce 35a33cac9f readme: Update tested environments 2026-05-24 18:18:52 +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 9eea357142 ramdisk_build: Remove usr/trollstore from ramdisk to free needed space 2026-05-24 18:18:52 +03:00
zqxwce 045d8050a3 install: Add opt-in ProductBuildVersion rewrite via SPOOF_BUILD (EXP-JB-7)
Adds the final EXP-only step: rewrite the userland-visible
`ProductBuildVersion` in `SystemVersion.plist` to a chosen build
identifier. Gated on the `SPOOF_BUILD` env var — when unset/empty, the
step is skipped entirely and the build identifier stays at whatever the
IPSW shipped.

The iPhone IPSW we install from ships with build identifier `23B85`
(iOS 26.1). iOS displays this string in Settings -> General -> About ->
"Build" and exposes it through `MGCopyAnswer("BuildVersion")`,
CoreFoundation's `_CFCopyServerVersionDictionary`, App Store telemetry,
and every other framework path that reads
`/System/Library/CoreServices/SystemVersion.plist`.

The build identifier lives in exactly two on-device plist files. Both
are plain XML/binary plists (no Apple-side per-file signature), and
both live on volumes that are writable at install time:

  /System/Library/CoreServices/SystemVersion.plist                                  (rootfs)
  /private/preboot/Cryptexes/OS/System/Library/CoreServices/SystemVersion.plist     (preboot)

EXP-JB-7 rewrites the `ProductBuildVersion` key in both plists to the
target value (typical: `23F77`). `ProductVersion` (`26.1`),
`ProductName` (`iPhone OS`), `BuildID`, `SystemImageID`, and
`ProductCopyright` are left untouched.

Order of operations: EXP-JB-7 runs AFTER EXP-JB-6 (post-restore DT
rewrite) so the post-restore identity work on `/mnt5` has completed
before the Cryptex's SystemVersion.plist (same volume) is touched.

Does NOT flip:
  - `sysctl kern.osversion` — comes from a kernel global initialized
    from boot args at boot time, not from this plist. To change it
    would require rebuilding the kernelcache with a different
    `OS_BUILD_VERSION` or patching the boot-args path — out of scope.
  - `SystemVersionCompat.plist` — carries a legacy iOS-19 marker for
    MacCatalyst-style queries; not user-visible, deliberately untouched.

- `scripts/patchers/cfw_patch_build_version.py` — host-side
  plistlib-based rewriter. Auto-detects XML vs binary plist format
  and preserves it on write. Idempotent — a re-run on an
  already-patched plist exits without rewriting.
- `scripts/cfw_install_exp.sh` — EXP-JB-7 phase: gated on
  `SPOOF_BUILD`; for each of the two plist paths it scp_from's the
  file to host, runs the patcher with the target id, scp_to's the
  file back. Tolerates missing-on-device with warn+continue.

Invocation:
  make setup_machine EXP=1 SPOOF_BUILD=23F77
  make cfw_install_exp SPOOF_BUILD=23F77

JB and DEV install scripts do NOT carry this step.
2026-05-18 16:14:55 +03:00
zqxwce 8bc903644f devicetree: Add post-restore identity rewrite for restore-fatal properties (EXP-JB-6)
The three restore-fatal DT root properties (root `model`, root
`target-type`, root `compatible[0]`) cannot be edited at fw_patch
time because `restored_external` / iBoot's restore mode cross-checks
them against the BuildManifest's signed `SupportedProductTypes`.
Editing them in the IPSW's `devicetree.im4p` causes the restore to
fail partway through.

But the cross-check fires ONLY during installation. After restore
completes, subsequent boots validate IM4P contents against the IM4M
only, which the existing iBSS/iBEC/LLB `image4_validate_property_callback`
bypass patches accept regardless. So an additional DT edit applied
AFTER restore but BEFORE the device reboots into the rootfs is
in-policy with the project's existing trust-chain bypass.

EXP-JB-6 exploits this. While the install pipeline still has `/mnt5`
(the preboot volume) mounted on the ramdisk, `cfw_install_exp.sh`:

  1. scp_from's `/mnt5/<boot-hash>/usr/standalone/firmware/devicetree.img4`
     to the host.
  2. Runs `scripts/patchers/cfw_patch_post_restore_dt.py`, which:
       - Unwraps IMG4 -> IM4P -> LZFSE-decompresses -> DT flat-binary
         blob (via pyimg4).
       - Rewrites three root properties:
           root `model`:       iPhone99,11        -> iPhone17,3
           root `target-type`: VPHONE600          -> D47
           root `compatible`:  reorder so D47AP is first, VPHONE600AP
                                second (IOKit's AppleVMApple1IO platform
                                bind still resolves via the second
                                entry; userland reads only the first
                                for `hw.model`).
       - Re-compresses LZFSE -> repacks IM4P -> repacks IMG4 with the
         ORIGINAL IM4M (the per-board ticket survives — the image4
         bypass already accepts any payload contents).
  3. scp_to's the modified img4 back to the same path.
  4. The device reboots out of ramdisk; iBoot loads the modified DT;
     kernel populates `machine_info` from the new property values.

Idempotent: the patcher detects target-state-already-met and exits
without rewriting.

Userland effects on next boot:
  - `sysctl hw.machine` -> "iPhone17,3" (was "iPhone99,11")
  - `sysctl hw.product` -> "iPhone17,3" (was "iPhone99,11")
  - `sysctl hw.model`   -> "D47AP"      (was "VPHONE600AP")
  - Settings -> General -> About -> Model Identifier picks up the new
    ProductType after the gestalt cache rebuilds.

- `scripts/patchers/cfw_patch_post_restore_dt.py` — host-side
  img4 <-> IM4P <-> DT flat-binary round-trip via pyimg4. Mirrors the
  DT format parser/serializer from `DeviceTreePatcher.swift`.
- `scripts/cfw_install_exp.sh` — EXP-JB-6 phase: discovers the
  boot-manifest-hash via the same `get_boot_manifest_hash` helper used
  by earlier install steps; tolerates a missing devicetree.img4 with
  warn-and-skip. JB and DEV install scripts do NOT carry this step.
2026-05-18 16:14:55 +03:00
zqxwce f22ed3e4bf devicetree: Add 8 identity-rewrite properties on EXP variant at fw_patch time
Splits `DeviceTreePatcher`'s property-patch list into two arrays:

  - `basePropertyPatches` (4 entries: `serial-number`,
    `home-button-type`, `artwork-device-subtype`,
    `island-notch-location`) — applied for every variant. Behaviour
    identical to pre-split.

  - `identityPropertyPatches` (8 entries — Tier 1b + 1c userland-facing
    identity surfaces) — applied only when `includeIdentityPatches` is
    true, which `FirmwarePipeline` sets exactly when `variant == .exp`.

The 8 EXP-only identity properties flip userland-visible identity toward
D47AP / iPhone17,3:

  - Tier 1b (5 properties, slot-length-preserving rewrites):
      device-tree.target-sub-type:        VPHONE600AP -> D47AP
      device-tree.compatible[1]:          iPhone99,11 -> iPhone17,3
                                           (reorder, VPHONE600AP kept first
                                            so IOKit's AppleVMApple1IO bind
                                            still resolves)
      device-tree/product.fdr-product-type: iPhone99,11 -> iPhone17,3
      device-tree/product.sub-product-type: iPhone99,11 -> iPhone17,3
      device-tree/product.unique-model:     VPHONE600AP -> D47AP

  - Tier 1c (3 properties — IOKit secondary matchers + Gestalt subtree
    rename, matched against the real D47AP DT):
      device-tree/arm-io.device_type:      vresearch1-io -> t8140-io
      device-tree/arm-io.soc-generation:   VResearch1    -> H17
      device-tree/product/vphone600-gestalt-variants.name (node rename):
                                            vphone600-gestalt-variants
                                            -> d47-gestalt-variants

Root `model` and root `target-type` are deliberately NOT in this list —
both have been empirically shown to break restore (signed-identity
cross-check in `restored_external`). Those edits run post-restore in a
later commit as EXP-JB-6.

- `sources/FirmwarePatcher/DeviceTree/DeviceTreePatcher.swift` — adds
  `includeIdentityPatches: Bool = false` to init (backwards-compatible
  default), stores it, splits `propertyPatches` into two static lists,
  iterates base first and then optionally identity in `applyPatches`.
- `sources/FirmwarePatcher/Pipeline/FirmwarePipeline.swift` — passes
  `includeIdentityPatches: variant == .exp` into the DT factory.

JB and other variants (regular, dev, less) leave the device's identity
properties untouched.
2026-05-18 16:14:55 +03:00
zqxwce 674a86bfd4 watchdogd: Add surgical hv_vmm_present cache patch (EXP-JB-3.5)
After the kernel-side OID rename (`KernelEXPPatchHvVmmRename`),
`sysctlbyname("kern.hv_vmm_present", ...)` returns ENOENT on this image.
`/usr/libexec/watchdogd` caches that answer at startup. On ENOENT the
cached byte stays at its BSS-zero default (`0`) and the downstream
`cbz w0, ...` at the IOWatchdog-lookup site takes a branch into
`_os_crash` -> `brk #1`; launchd's `_PanicOnCrash =
PanicOnConsecutiveCrash = true` flag in `com.apple.watchdogd.plist`
escalates the SIGTRAP to a kernel panic.

The cstring-mangle approach used for DSC dylibs doesn't apply here: we
want this binary to behave as if the sysctl returned 1, not as if it
returned ENOENT. Solution is a surgical 2-instruction patch that forces
the cached "am I a VM?" byte to 1 regardless of the sysctl result.

- `scripts/patchers/cfw_patch_watchdogd.py` — capstone-anchored pattern
  matcher + Keystone-assembled 2-insn patch. Two functions match the
  canonical caching shape on iPhone17,3 / iOS 26.1; both are patched.
  Net effect: `cbnz w0, skip` -> NOP and `cset wN, ne` -> `mov wN, #1`,
  forcing the cached byte to 1. watchdogd's pre-existing "detected
  virtual machine environment, exiting..." clean-exit branch runs
  instead of the trap path. Idempotent.
- `scripts/patchers/cfw_macho_codesign.py` — generic standalone-Mach-O
  page-hash re-attestation. Parses `LC_CODE_SIGNATURE` directly, reads
  page size from each `CS_CodeDirectory` header (4 KiB on watchdogd —
  not the DSC's 16 KiB), handles short tail slot length
  (`codeLimit - (n-1)*pageSize`), and updates every present CD. The
  resulting cdHash change is accepted by the JB `patch_amfi_cdhash_in_trustcache`
  kernel patch which accepts any cdHash; the patcher does NOT re-sign
  with ldid (preserving the original Apple-issued code-signing
  identifier is required for launchd's boot-task identity validation).
- `scripts/patchers/cfw.py` — adds `patch-watchdogd` subcommand.
- `scripts/patch_hv_vmm_userland.sh` — adds `watchdogd <binary>` op.
- `scripts/cfw_install_exp.sh` — invokes the patcher at step
  `[EXP-JB-3.5]` on the live `/mnt1/usr/libexec/watchdogd` (scp-down,
  patch, scp-up, chmod 0755). JB and DEV install scripts do NOT run
  this step.
2026-05-18 16:14:55 +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
zqxwce ee5e7d0fa2 kernel: Introduce EXP variant and hv_vmm_present OID rename (KernelEXPPatcher)
Introduces a new `exp` firmware variant on top of JB and ports the
`hv_vmm_present` sysctl rename to it.

Variant infrastructure
----------------------
- Adds `case exp` to `FirmwarePipeline.Variant`,
  `VPhoneCLI.PatchFirmwareCLI.VariantOption`, and
  `VPhoneVirtualMachine.Variant`. Every `switch variant` block in
  `FirmwarePipeline.buildComponentList` includes the new case.
- Adds `make fw_patch_exp` + `make cfw_install_exp` Makefile targets
  and an `EXP=1` flag for `make setup_machine`, mutually exclusive with
  `JB=1` / `DEV=1` / `LESS=1`. `SPOOF_BUILD` env var is threaded
  through for later use by the build-version step.
- Adds `--exp` to `scripts/setup_machine.sh` alongside `--jb` /
  `--dev` / `--less`. The post-install JB-Finalize block also fires
  for EXP (since EXP inherits the JB rootfs deployment).
- Adds `scripts/cfw_install_exp.sh` as the EXP install script
  starting point: identical phase set to `cfw_install_jb.sh` (JB-1..JB-5)
  with banner/header/footer updated for EXP. Subsequent commits in this
  branch add the EXP-only experimental phases on top.
- Updates the variants table in `AGENTS.md` / `README.md` and the
  three translated READMEs to include the new `Experimental (EXP)`
  row, plus a paragraph describing what EXP adds on top of JB.

Kernel patch
------------
- New `KernelEXPPatcher` orchestrator in
  `sources/FirmwarePatcher/Kernel/`, chained after `KernelPatcher` +
  `KernelJBPatcher` for the `.exp` variant only. Inherits
  `KernelJBPatcherBase` to reuse the JB symbol-table / ADRP-BL index /
  branch-encoder infrastructure.
- New `KernelEXPPatchHvVmmRename` patch in
  `sources/FirmwarePatcher/Kernel/EXPPatches/`. Part A flips byte 0 of
  the NUL-delimited `\\0hv_vmm_present\\0` cstring (the sysctl OID's
  `oid_name` value) — `'h'` -> `'X'` — so the kernel resolves
  `sysctlbyname("kern.hv_vmm_present")` as ENOENT and
  `sysctlbyname("kern.Xv_vmm_present")` to the OID's real int value.
  Part B mangles byte 5 of every kernel-internal occurrence of
  `kern.hv_vmm_present` so callers keep hitting the renamed OID; two
  byte-aligned forms are covered (NUL-delimited cstring + sandbox-profile
  name-token with trailing `\\x0f`).
- Patch IDs are `kernelcache_exp.hv_vmm_oid_rename` and
  `kernelcache_exp.hv_vmm_internal_caller_mangle`. Idempotent.
- `KernelJBPatcher` is unchanged at the call-site level (no
  `patchHvVmmRename` call); its docstring is updated to point at
  `KernelEXPPatcher` for the EXP-only patch.

JB and other variants are NOT affected: `cfw_install_jb.sh` and
`cfw_install_dev.sh` are untouched in this commit.
2026-05-18 16:14:55 +03:00
Maximilian Paß df9f0f2fa5 Add Scaler Accelerator 2026-05-16 16:19:18 +03:00
Joshua Seltzer f283d83e25 Add zstd dep to other README files and the setup_tools script 2026-05-07 16:01:37 +03:00
Joshua Seltzer 5e7fb738ef Add missing zstd dependency 2026-05-07 16:01:37 +03:00
Xplo8E a50cf42cd6 remove confirmation for non-destructive clean 2026-05-07 16:00:56 +03:00
Xplo8E 4ea2b1e794 Harden make clean behavior
Make the default clean target remove only build/tooling artifacts, add
confirmation prompts, and require explicit CLEAN_VM/CLEAN_IPSW flags before
removing VM or IPSW state. Document the behavior in README translations.
2026-05-07 16:00:56 +03:00
zqxwce 77d4a04c55 window: Show guest IP in subtitle once vphoned connects
vphoned now reports its primary non-loopback IPv4 address in the hello
response (preferring en*/pdp_ip* interfaces).
2026-04-30 12:27:59 +03:00
matteyeux e3f4877392 add missing quote for help option in Makefile 2026-04-30 11:47:58 +03:00
zqxwce 856576e93b docs: Add restore_offline documentation 2026-04-27 13:32:25 +03:00
renegadelink aaf91586eb make: surface ipsw fw aea failures in restore_offline (no more silent fallthrough) 2026-04-26 18:54:23 +03:00
renegadelink 6f3b16397b restore: add offline mode (cached SHSH + in-place AEA decryption) 2026-04-26 18:54:23 +03:00
Maximilian Paß bde1ff3a83 [Patchless] Fix Panic Regex 2026-04-24 00:19:28 +03:00
Maximilian Paß a6f0bf4326 [Patchless] Add noVphone Flag 2026-04-24 00:19:28 +03:00
Maximilian Paß bca4450a6c [Patchless] Add Binpack (incl SSH) 2026-04-24 00:19:28 +03:00
Maximilian Paß a89b034ced [Patchless] Clarify Readme 2026-04-21 23:37:07 +03:00
Maximilian Paß e2ae79b827 [Patchless] Use embedded AEA key 2026-04-21 23:37:07 +03:00
Maximilian Paß 7b6fd7883c [Patchless] Remap fs only on change 2026-04-21 23:37:07 +03:00
Maximilian Paß e6dd6ef722 Add Entropy and Accelerator Devices 2026-04-21 22:05:47 +03:00
sindo 5f151aca45 make: fix vm_list exit code when backups exist
[ "$$found" = "0" ] && echo ... returns exit 1 when backups exist,
which propagates as a make rule failure. Replace it with if/fi so the
target exits successfully in both cases.
2026-04-21 22:04:00 +03:00
zqxwce 120d6f9862 venv: Fix python3 locating for enviornments using uv 2026-04-20 17:23:32 +03:00
zqxwce 3b48ce6cf3 iosbinpack64: dev_overlay: Move dev overlay to before install 2026-04-20 17:23:32 +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 367209a1e4 amfidont: Simplify start_amfidont_for_vphone.sh 2026-04-15 16:41:07 +03:00
zqxwce 7d09a1bb0e patchless: Add support for non SIP/AMFI disabled systems 2026-04-15 16:41:07 +03:00
RowSalmon 65aa42f2c1 Update README.md
It could be more clear that git submodules must be installed.

In my case, I  missed this, leading to hours of troubleshooting. 

This commit seeks to make it more clear what steps are needed to install dependencies.
2026-04-10 14:40:58 +03:00
zqxwce 45c3df7609 setup_tools: Limit apfs_sealvolume download to patchless variant only 2026-04-08 18:31:14 +03:00
Maximilian Paßandzqxwce 8188761e24 [Patchless] Add AMFI preflight test
Co-authored-by: zqxwce <[email protected]>
2026-04-08 18:29:01 +03:00
Maximilian Paßanddevin d3395aee95 [Patchless] Fix Posix file permissions
Co-authored-by: devin <[email protected]>
2026-04-08 18:29:01 +03:00
Maximilian Paß ecf1c327fc [Patchless] Add vphoned 2026-04-08 18:29:01 +03:00
Maximilian Paß a65eacf126 [Patchless] Add iBEC/LLB Patching for Serial Logs 2026-04-08 18:29:01 +03:00
Maximilian Paß b81fa62a11 Introduce Patchless Variant 2026-04-08 18:29:01 +03:00
Maximilian Paß 3024223b0c [Patchless] Add Mobile Activation Patch 2026-04-08 18:29:01 +03:00
Maximilian Paß c5ee950a95 [Patchless] Add GPU Driver 2026-04-08 18:29:01 +03:00