Enable 16 verified kernel JB patches, add per-patch research docs

Batch-tested all 24 kernel JB patches individually:
- 18 enabled: A1,A3,A4,B5,B7,B9-B20,C21,C22
- 3 PANIC: A2, B6 (proc_security_policy), B8 (convert_port_to_map), C23 (hook_cred_label_update_execve)
- 1 NOT_BOOT: C24 (kcall10)

Added research/kernel_patch_jb/ with per-patch analysis notes.
This commit is contained in:
Lakr
2026-03-04 20:08:00 +08:00
parent 9bb53b7368
commit 7daa2c4773
26 changed files with 669 additions and 25 deletions

3
.gitignore vendored
View File

@@ -320,4 +320,5 @@ TODO.md
/references/
scripts/vphoned/vphoned
sources/vphone-cli/VPhoneBuildInfo.swift
setup_logs/
setup_logs/
/testing_results

View File

@@ -0,0 +1,33 @@
# A1 `patch_amfi_cdhash_in_trustcache`
## 1) How the Patch Is Applied
- Source implementation: `scripts/patchers/kernel_jb_patch_amfi_trustcache.py`
- Match strategy: no string anchor; uses an AMFI function semantic sequence match (`mov x19, x2` -> `stp xzr,xzr,[sp,...]` -> `mov x2, sp` -> `bl` -> `mov x20, x0` -> `cbnz w0` -> `cbz x19`).
- Rewrite: replace the first 4 instructions at function entry with a stub:
1. `mov x0, #1`
2. `cbz x2, +8`
3. `str x0, [x2]`
4. `ret`
## 2) Expected Behavior
- Always report "CDHash is in trustcache" as true (return `1`).
- If the caller passes an out parameter (`x2` is non-null), write the same result back to the out pointer.
## 3) Target
- Target function logic: AMFI trustcache membership check (script label: `AMFIIsCDHashInTrustCache`).
- Security objective: bypass AMFI's key gate that verifies whether a signing hash is trusted.
## 4) IDA MCP Binary Evidence
- IDB: `/Users/qaq/Desktop/kernelcache.research.vphone600.macho`
- imagebase: `0xfffffe0007004000`
- An IDA semantic-sequence scan (same signature as the script) found 1 hit in the AMFI area:
- Function entry: `0xfffffe0008637880`
- This function is called by multiple AMFI paths (sample xrefs):
- `0xfffffe0008635de4`
- `0xfffffe000863e554`
- `0xfffffe0008641e0c`
- `0xfffffe00086432dc`
## 5) Risks and Side Effects
- Forces all CDHash trust decisions to allow, which is highly intrusive.
- If callers rely on the failure path for cleanup or auditing, this patch short-circuits that behavior.

View File

@@ -0,0 +1,28 @@
# A2 `patch_amfi_execve_kill_path` (currently commented as PANIC in the main flow)
## 1) How the Patch Is Applied
- Source implementation: `scripts/patchers/kernel_jb_patch_amfi_execve.py`
- Match strategy:
- String anchor: `"AMFI: hook..execve() killing"` (fallback: `"execve() killing"`).
- After finding the function that references this string, scan its early region for **two** `BL + (cbz/cbnz w0,...)` check sites.
- Rewrite: replace both `BL` instructions with `mov x0, #0` (direct success-result semantics).
## 2) Expected Behavior
- Short-circuit failure decisions in the AMFI execve kill helper and avoid entering the kill path.
## 3) Target
- Target function: execve-related AMFI helper (log string indicates the `hook..execve() killing ...` path).
- Security objective: relax execution-path checks and reduce termination on unsigned/invalid signatures.
## 4) IDA MCP Binary Evidence
- String hits (examples):
- `0xfffffe00071f71c2` `AMFI: hook..execve() killing ... unsigned code ...`
- `0xfffffe00071f73b8` `... Legacy VPN Plugin ...`
- `0xfffffe00071f740b` `... dyld signature cannot be verified ...`
- Xrefs for these strings all land in the same function:
- xref: `0xfffffe000863fcfc / 0xfffffe000863feb4 / 0xfffffe000863fef4`
- function start: `0xfffffe000863fc6c`
## 5) Risks and Side Effects
- This patch is already commented as `PANIC` in `find_all()`, indicating known stability risk on the current sample.
- Flattening two check return values may break downstream assumptions (for example, uninitialized state being treated as success).

View File

@@ -0,0 +1,24 @@
# B13 `patch_bsd_init_auth`
## How the patch works
- Source: `scripts/patchers/kernel_jb_patch_bsd_init_auth.py`.
- Locator strategy:
1. Try symbol `_bsd_init`.
2. Fallback pattern search: `ldr x0, [xN, #0x2b8]` -> `cbz x0, ...` -> `bl AUTH_FUNC`.
- Patch action:
- Replace the `BL AUTH_FUNC` with `mov x0, #0`.
## Expected outcome
- Force rootvp authentication check path to return success.
## Target
- Authentication helper call in `_bsd_init` boot path.
## IDA MCP evidence
- Related string anchor (used for cross-check): `0xfffffe000707d2fd`
- text: `"rootvp not authenticated after mounting @%s:%d"`
- xref: `0xfffffe0007f71bd8`
- containing function start: `0xfffffe0007f70da8`
## Risk
- Early boot filesystem trust checks are security-critical; bypass can permit untrusted root volume state.

View File

@@ -0,0 +1,34 @@
# B8 `patch_convert_port_to_map`
## How the patch works
- Source: `scripts/patchers/kernel_jb_patch_port_to_map.py`.
- Locator strategy:
1. Anchor panic string: `"userspace has control access to a kernel map"`.
2. Find xref to that string and nearby `BL _panic`.
3. Walk backward to locate the conditional branch entering the panic block.
- Patch action:
- Replace that conditional branch with unconditional `B` to `resume_off` (`bl_panic + 4`), so execution skips the panic call.
## Expected outcome
- Kernel no longer panics on this convert-port-to-map control-access check path.
## Target
- The panic edge in `_convert_port_to_map_with_flavor` (or equivalent stripped function), specifically the branch feeding the panic block.
## IDA MCP evidence
- Panic string: `0xfffffe0007040701`
- String xref site: `0xfffffe0007b06eac`
- Containing function start: `0xfffffe0007b06db8`
## Full call-stack sample (static, from IDA xrefs)
- This is one complete observed caller chain down to the patched function:
1. data dispatch ref: `0xfffffe00078ee8c8` -> function `sub_FFFFFE00089B17E0` (`0xfffffe00089b17e0`)
2. call at `0xfffffe00089b1c50`: `BL sub_FFFFFE0008A1F0A0`
3. call at `0xfffffe0008a1f31c`: `BL sub_FFFFFE0008A19DC8`
4. call at `0xfffffe0008a19e34`: `BL sub_FFFFFE0008A2D948`
5. call at `0xfffffe0008a2d9a4`: `BL sub_FFFFFE0007BD2544`
6. call at `0xfffffe0007bd2694`: `B sub_FFFFFE0007B06DB8`
7. panic-log reference inside target function: `0xfffffe0007b06eac`
## Risk
- This converts a hard fail (panic) into continue-execution behavior; if downstream invariants were relying on panic-stop, memory safety assumptions may no longer hold.

View File

@@ -0,0 +1,32 @@
# C21 `patch_cred_label_update_execve`
## How the patch works
- Source: `scripts/patchers/kernel_jb_patch_cred_label.py`.
- Locator strategy:
1. Try symbol containing `cred_label_update_execve`.
2. Fallback via AMFI execve-related string neighborhood.
3. Resolve function end and final return site.
- Patch action:
- Allocate code cave and inject shellcode that edits `cs_flags`:
- set `CS_PLATFORM_BINARY` and selected permissive flags,
- clear selected hard/kill bits,
- return success.
- Replace original function return with branch to shellcode cave.
## Expected outcome
- Force permissive credential/code-signing flags during execve cred-label update.
## Target
- Return edge of `_cred_label_update_execve`-related function (redirect to cave).
## IDA MCP evidence
- Relevant AMFI anchors used by locator:
- `AMFI: code signature validation failed` @ `0xfffffe00071f80bf`
- `execve() killing` strings around `0xfffffe00071f71c2` / `...73b8` / `...740b`
- These strings cluster in AMFI functions around:
- `0xfffffe0008641924`
- `0xfffffe000863fc6c`
## Risk
- This is a high-impact shellcode redirect patch; wrong cave/return resolution can panic.
- Direct cs_flags manipulation changes trust semantics globally for targeted execve paths.

View File

@@ -0,0 +1,24 @@
# B12 `patch_dounmount`
## How the patch works
- Source: `scripts/patchers/kernel_jb_patch_dounmount.py`.
- Locator strategy:
1. Try symbol `_dounmount`.
2. Fallback anchor string `"dounmount:"` and inspect call targets.
3. Match sequence `mov w1,#0` + `mov x2,#0` + `bl ...` (MAC check pattern).
- Patch action:
- NOP the matched `BL` MAC-check call.
## Expected outcome
- Suppress unmount MAC check path and continue unmount operation.
## Target
- MAC authorization call site in `_dounmount` path.
## IDA MCP evidence
- String: `0xfffffe000705661c` (`"dounmount: no coveredvp ..."`)
- xref: `0xfffffe0007cac34c`
- containing function start: `0xfffffe0007cabaec`
## Risk
- Can bypass policy enforcement around unmount operations.

View File

@@ -0,0 +1,32 @@
# C23 `patch_hook_cred_label_update_execve`
## How the patch works
- Source: `scripts/patchers/kernel_jb_patch_hook_cred_label.py`.
- Locator strategy:
1. Resolve `vnode_getattr` (symbol or string-near function).
2. Find sandbox `mac_policy_ops` table from Seatbelt policy metadata.
3. Pick cred-label execve hook entry from early ops indices by function-size heuristic.
- Patch action:
- Inject cave shellcode that:
- builds inline `vfs_context`,
- calls `vnode_getattr`,
- propagates uid/gid into new credential,
- updates csflags,
- jumps back to original hook.
- Rewrite selected ops-table pointer entry to cave target (preserving auth-rebase upper bits).
## Expected outcome
- Interpose sandbox cred-label execve hook with custom ownership/credential propagation logic.
## Target
- One `mac_policy_ops` function-pointer entry plus injected hook shellcode cave.
## IDA MCP evidence
- `vnode_getattr` string-related hit:
- xref `0xfffffe00084c08ec` -> function start `0xfffffe00084c0718`
- Seatbelt policy anchor:
- `Seatbelt sandbox policy` @ `0xfffffe00075fd493`
- data xref @ `0xfffffe0007a58430` (policy config region)
## Risk
- Table-entry rewrite + shellcode interposition is invasive; incorrect index/cave selection can break sandbox hook dispatch.

View File

@@ -0,0 +1,25 @@
# B19 `patch_io_secure_bsd_root`
## How the patch works
- Source: `scripts/patchers/kernel_jb_patch_secure_root.py`.
- Locator strategy:
1. Try symbol `_IOSecureBSDRoot`.
2. Fallback string anchor `SecureRootName`.
3. In target function, locate first forward conditional branch (`cbz/cbnz/tbz/tbnz`).
- Patch action:
- Replace conditional branch with unconditional `B target`.
## Expected outcome
- Always take the forward branch and skip selected secure-root check path.
## Target
- Security decision branch inside `_IOSecureBSDRoot` flow.
## IDA MCP evidence
- `SecureRootName` occurrences:
- `0xfffffe00070a66a5` -> xref `0xfffffe000828f444` -> function start `0xfffffe000828f42c`
- `0xfffffe0007108f2d` -> xref `0xfffffe000836624c` -> function start `0xfffffe0008366008`
- Patch script uses first successful function resolution in scan order.
## Risk
- Secure-root checks are trust anchors; forcing the branch can weaken platform integrity assumptions.

View File

@@ -0,0 +1,28 @@
# C24 `patch_kcall10`
## How the patch works
- Source: `scripts/patchers/kernel_jb_patch_kcall10.py`.
- Locator strategy:
1. Resolve `_nosys` (symbol or `mov w0,#0x4e; ret` pattern).
2. Scan DATA segments for `sysent` table signature (entry decoding points to `_nosys`).
3. Compute `sysent[439]` (`SYS_kas_info`) entry offset.
- Patch action:
- Inject `kcall10` shellcode in code cave (argument marshalling + `blr x16` + result write-back).
- Rewrite `sysent[439]` fields:
- `sy_call` -> cave VA
- `sy_munge32` -> `_munge_wwwwwwww` (if resolved)
- return type + arg metadata.
## Expected outcome
- Replace syscall 439 handler with arbitrary 10-arg kernel call trampoline behavior.
## Target
- `sysent[439]` table entry and cave shellcode block.
## IDA MCP evidence
- Pattern `mov w0,#0x4e; ret` appears in multiple tiny stubs (expected in this build).
- One strong candidate family is around `0xfffffe00084b5d3c` (tiny nosys-like stub with many data refs), consistent with table-dispatch use.
- This matches patch design that depends on data-table discovery rather than direct named symbol.
## Risk
- Syscall table rewrite is extremely invasive; wrong table/entry decode can hard panic the kernel.

View File

@@ -0,0 +1,26 @@
# B16 `patch_load_dylinker`
## How the patch works
- Source: `scripts/patchers/kernel_jb_patch_load_dylinker.py`.
- Locator strategy:
1. Try symbol `_load_dylinker`.
2. Otherwise find function with repeated PAC triplets:
- `tst xN, #0x40000000000000`
- `b.eq ...`
- `movk xN, #0xc8a2`
- repeated >= 3 times, usually in a function with no direct BL callers.
- Patch action:
- Replace the **last** `tst` with unconditional branch to the `b.eq` target.
## Expected outcome
- Always skip selected PAC re-sign/check path in chained-fixup rebase flow.
## Target
- PAC decision branch in `_load_dylinker`-related fixup path.
## IDA MCP evidence (current state)
- No direct stable string/symbol anchor for this stripped build.
- The patch design is pattern-based and function-profile-based; exact static site remains pending additional scripted narrowing.
## Risk
- PAC bypass in dylinker/fixup path is security-sensitive and can alter pointer-auth assumptions globally.

View File

@@ -0,0 +1,24 @@
# B11 `patch_mac_mount`
## How the patch works
- Source: `scripts/patchers/kernel_jb_patch_mac_mount.py`.
- Locator strategy:
1. Try symbols `___mac_mount` / `__mac_mount`.
2. Fallback anchor string `"mount_common()"`, then inspect BL targets for MAC-check shape.
- Patch action:
- NOP the `BL` check call followed by `CBNZ w0`.
- Optionally force `mov x8, xzr` at nearby state setup point.
## Expected outcome
- Bypass MAC mount decision path so mount flow keeps going.
## Target
- MAC policy check branch sequence in `___mac_mount`-related path.
## IDA MCP evidence
- String: `0xfffffe0007056a9d` (`"mount_common(): ..."`)
- xref: `0xfffffe0007ca8de0`
- containing function start: `0xfffffe0007ca7868`
## Risk
- Mount authorization bypass can weaken filesystem integrity assumptions.

View File

@@ -0,0 +1,25 @@
# B18 `patch_nvram_verify_permission`
## How the patch works
- Source: `scripts/patchers/kernel_jb_patch_nvram.py`.
- Locator strategy:
1. Try NVRAM verifyPermission symbol.
2. Fallback string anchor `krn.` and scan backward from its load site for nearby `tbz/tbnz` guard.
3. Secondary fallback: entitlement string `com.apple.private.iokit.nvram-write-access`.
- Patch action:
- NOP selected `tbz/tbnz` permission guard.
## Expected outcome
- Bypass NVRAM permission gating in verifyPermission path.
## Target
- Bit-test branch enforcing write permission policy in IONVRAM permission checks.
## IDA MCP evidence
- `krn.` anchor string: `0xfffffe0007156000`
- xrefs: `0xfffffe00084c2608`, `0xfffffe00084cd92c`
- entitlement anchor string: `0xfffffe00070a238f`
- xref: `0xfffffe000823810c` (function start `0xfffffe0008237ee8`)
## Risk
- NVRAM permission bypass can enable persistent config tampering.

View File

@@ -0,0 +1,27 @@
# B5 `patch_post_validation_additional`
## 1) How the Patch Is Applied
- Source implementation: `scripts/patchers/kernel_jb_patch_post_validation.py`
- Match strategy:
- Anchor string: `AMFI: code signature validation failed`
- Find callers that reference this string, then walk their `BL` callees.
- In the callee, locate `cmp w0, #imm` + `b.ne` patterns with a nearby preceding `bl`.
- Rewrite: change `cmp w0, #imm` to `cmp w0, w0`.
## 2) Expected Behavior
- Convert a postValidation failure comparison into an identity comparison, so `b.ne` loses its original reject semantics.
## 3) Target
- Target logic: additional reject path in AMFI code-sign post validation.
- Security objective: reduce forced rejection after signature-validation failure.
## 4) IDA MCP Binary Evidence
- String: `0xfffffe00071f80bf` `"AMFI: code signature validation failed.\n"`
- Xrefs (same function):
- `0xfffffe0008642290`
- `0xfffffe0008642bf0`
- `0xfffffe0008642e98`
- Corresponding function start: `0xfffffe0008641924`
## 5) Risks and Side Effects
- Turns a post-validation error-convergence condition into one that effectively never triggers rejection.

View File

@@ -0,0 +1,23 @@
# B7 `patch_proc_pidinfo`
## How the patch works
- Source: `scripts/patchers/kernel_jb_patch_proc_pidinfo.py`.
- Locator strategy:
1. Try symbol `_proc_pidinfo`.
2. Otherwise, re-find `_proc_info` using the same switch-pattern heuristic (`... #0x21`).
3. In early prologue window, collect first two `cbz/cbnz` guards (pid-0 / null-proc style guards).
- Patch action: NOP the first two guard branches.
## Expected outcome
- Bypass early pid/proc guard branches so pidinfo flow continues instead of early rejection.
## Target
- The early guard checks in `_proc_pidinfo` path (or the equivalent early guard sequence reached from `_proc_info`).
## IDA MCP evidence (current state)
- No stable symbol names are present in this stripped IDB.
- I validated that this patch is branch-guard NOP logic driven by pattern matching, but a unique static address pair was not resolved yet in short MCP windows.
- Status: patch semantics confirmed; exact two branch offsets pending extended automated sweep.
## Risk
- Removing these guards can expose process metadata paths that were expected to fail for invalid or restricted pid/proc states.

View File

@@ -0,0 +1,25 @@
# B6 `patch_proc_security_policy`
## How the patch works
- Source: `scripts/patchers/kernel_jb_patch_proc_security.py`.
- Locator strategy:
1. Try symbol `_proc_security_policy`.
2. If stripped, locate `_proc_info` by a switch-shape signature (`sub wN, wM, #1` + `cmp wN, #0x21`).
3. Inside that function, count BL targets and pick the most-called one as `_proc_security_policy`.
- Patch action: overwrite target function entry with:
- `mov x0, #0`
- `ret`
## Expected outcome
- Force `proc_security_policy` checks to return success.
## Target
- Targeted logic is the centralized process-security policy gate used by `proc_info` family paths.
## IDA MCP evidence (current state)
- This patch is mainly pattern-driven and symbol-first; this IDB is stripped.
- I validated related immediate patterns and candidate comparison sites in kernel text, but did not obtain a single uniquely provable `_proc_info -> most-called callee` chain within MCP single-call time limits.
- Status: behavior-level analysis confirmed from patch code; exact final function address is pending a longer multi-pass IDA sweep.
## Risk
- Turning this policy function into unconditional success can over-broaden process introspection and privilege surfaces.

View File

@@ -0,0 +1,27 @@
# A4 `patch_sandbox_hooks_extended`
## 1) How the Patch Is Applied
- Source implementation: `scripts/patchers/kernel_jb_patch_sandbox_extended.py`
- Match strategy:
- Use `Seatbelt sandbox policy` plus sandbox-related structures to locate `mac_policy_conf`.
- From `mpc_ops`, obtain the sandbox `mac_policy_ops` table.
- Read hook function pointers by a fixed index list (245, 249, 250, ... 316).
- Rewrite: write 2 instructions at each matched hook entry:
- `mov x0, #0`
- `ret`
## 2) Expected Behavior
- Force many sandbox MAC hooks to return success, expanding allow coverage for file/process operations in the jailbreak environment.
## 3) Target
- Target object: extended sandbox hooks in `mac_policy_ops` (vnode/proc and related check points).
- Security objective: move from point bypasses to bulk policy allow.
## 4) IDA MCP Binary Evidence
- `Seatbelt sandbox policy` string hit: `0xfffffe00075fd493`
- Xref points to the policy-structure region: `0xfffffe0007a58430` (data reference)
- Script logic uses this structure to recover the `ops` table and patch hook entries in bulk (not a single-address patch).
## 5) Risks and Side Effects
- Very wide coverage, with a high chance of cross-subsystem side effects (filesystem, process, exec paths).
- If indices do not match the target build, the patch may hit wrong functions and trigger panic.

View File

@@ -0,0 +1,24 @@
# B17 `patch_shared_region_map`
## How the patch works
- Source: `scripts/patchers/kernel_jb_patch_shared_region.py`.
- Locator strategy:
1. Try symbol `_shared_region_map_and_slide_setup`.
2. Fallback string anchor: `/private/preboot/Cryptexes`.
3. In function body, find `cmp <reg>, <reg>` followed by `b.ne` style guard.
- Patch action:
- Rewrite compare to `cmp x0, x0`.
## Expected outcome
- Force compare result toward equality path, weakening rejection branch behavior.
## Target
- Shared region setup guard in `_shared_region_map_and_slide_setup` path.
## IDA MCP evidence
- Anchor string: `0xfffffe000708c481` (`/private/preboot/Cryptexes`)
- xref: `0xfffffe00080769dc`
- containing function start: `0xfffffe0008076260`
## Risk
- Shared-region mapping checks influence process memory layout/security assumptions.

View File

@@ -0,0 +1,23 @@
# B14 `patch_spawn_validate_persona`
## How the patch works
- Source: `scripts/patchers/kernel_jb_patch_spawn_persona.py`.
- Locator strategy:
1. Try symbol `_spawn_validate_persona`.
2. Fallback pattern match: `ldr wN, [xN, #0x600]` with nearby `tbnz wN, #1`.
- Patch action:
- NOP the `ldr` and the matched `tbnz` site.
## Expected outcome
- Disable persona validation decision branch in spawn path.
## Target
- Persona-flag load/check pair in `_spawn_validate_persona` flow.
## IDA MCP evidence (current state)
- No direct string anchor and no symbol names in this stripped IDB.
- Pattern-level behavior is clear from patch code, but this pass did not isolate one unique static address pair under MCP short execution windows.
- Status: semantics confirmed; concrete offsets pending longer scripted sweep.
## Risk
- Persona checks are part of process-creation security model; bypass can relax intended privilege boundaries.

View File

@@ -0,0 +1,30 @@
# C22 `patch_syscallmask_apply_to_proc`
## How the patch works
- Source: `scripts/patchers/kernel_jb_patch_syscallmask.py`.
- Locator strategy:
1. Try symbol `_syscallmask_apply_to_proc`.
2. Fallback string anchor `syscallmask.c`.
3. Resolve helper targets (`zalloc_ro_mut`, `proc_set_syscall_filter_mask`) from local call graph.
- Patch action:
- Inject large shellcode into cave:
- build/adjust syscall filter mask,
- call allocator helper,
- tail-branch to original filter-setter path.
- Patch original function to jump into cave after register setup.
## Expected outcome
- Replace default syscall mask application behavior with custom filter handling logic.
## Target
- `_syscallmask_apply_to_proc` body entry-side injection point and cave redirection.
## IDA MCP evidence
- Anchor string: `0xfffffe00075fcec6` (`"syscallmask.c"`)
- Sample xrefs/function starts:
- `0xfffffe0009399600` -> `0xfffffe00093995b4`
- `0xfffffe00093adb6c` -> `0xfffffe00093ac964`
- Additional related string: `sandbox.syscallmasks` present in IDB.
## Risk
- Large cave shellcode with multiple helper calls increases compatibility and control-flow risk.

View File

@@ -0,0 +1,26 @@
# A3 `patch_task_conversion_eval_internal`
## 1) How the Patch Is Applied
- Source implementation: `scripts/patchers/kernel_jb_patch_task_conversion.py`
- Match strategy: pure instruction-semantic matching (no string anchor):
- `ldr Xn, [Xn]`
- `cmp Xn, x0`
- `b.eq ...`
- `cmp Xn, x1`
- `b.eq ...`
- Rewrite: change `cmp Xn, x0` to `cmp xzr, xzr` (identity compare, effectively making the equal-path reachable unconditionally).
## 2) Expected Behavior
- Relax the internal guard in task conversion so later comparison branches are more likely to take the allow path.
## 3) Target
- Target logic: core identity/relationship check point inside `_task_conversion_eval_internal`.
- Security objective: reduce task-conversion denial rate to support task-related privilege escalation chains.
## 4) IDA MCP Binary Evidence
- This patch has no stable string anchor, and the current IDB is stripped (no symbols).
- Pattern-level scans via IDA MCP were attempted (`cmp` + double `b.eq` structure), but did not converge to a unique address within the MCP single-run 15s limit.
- Conclusion: keep this document in "pattern confirmed, address pending" state for now.
## 5) Risks and Side Effects
- This kind of `cmp` short-circuit affects task security boundaries. If the hit point is wrong, it can cause permission-model corruption or panic.

View File

@@ -0,0 +1,27 @@
# B15 `patch_task_for_pid`
## How the patch works
- Source: `scripts/patchers/kernel_jb_patch_task_for_pid.py`.
- Locator strategy:
1. Try symbol `_task_for_pid`.
2. Otherwise scan for a trap-like function profile:
- no direct BL callers,
- multiple `ldadda`,
- repeated `ldr wN, [xN, #0x490]` + `str wN, [xN, #0xc]`,
- `movk ..., #0xc8a2`,
- BL to high-caller target.
- Patch action:
- NOP the second `ldr ... #0x490` (target proc security copy).
## Expected outcome
- Skip copying restrictive proc_ro security state in task_for_pid path.
## Target
- Security-copy instruction sequence in `_task_for_pid` internals.
## IDA MCP evidence (current state)
- Relevant policy strings exist (`task_for_pid-allow`, AMFI task_for_pid log), but those resolve mainly to AMFI policy handlers, not directly to the trap implementation this patch targets.
- This patch relies on multi-feature structural matching rather than a single anchor; exact final patch offset is pending deeper automated scan.
## Risk
- task_for_pid hardening bypass is high-impact and can enable broader task-port access.

View File

@@ -0,0 +1,24 @@
# B20 `patch_thid_should_crash`
## How the patch works
- Source: `scripts/patchers/kernel_jb_patch_thid_crash.py`.
- Locator strategy:
1. Try symbol `_thid_should_crash`.
2. Fallback by locating `"thid_should_crash"` sysctl-name string in data.
3. Walk nearby sysctl-related data entries to recover the backing variable pointer.
- Patch action:
- Write `0x00000000` to the resolved global int variable.
## Expected outcome
- Disable crash behavior controlled by `_thid_should_crash` flag.
## Target
- Global data variable (not code) backing the `thid_should_crash` sysctl path.
## IDA MCP evidence
- String: `0xfffffe0009790bc0` (`"thid_should_crash"`)
- data xref nearby: `0xfffffe0009790bd8`
- This matches patch design: derive writable flag address from adjacent sysctl metadata.
## Risk
- Directly mutating global crash-control flags can hide error paths expected during diagnostics.

View File

@@ -0,0 +1,26 @@
# B9 `patch_vm_fault_enter_prepare`
## How the patch works
- Source: `scripts/patchers/kernel_jb_patch_vm_fault.py`.
- Locator strategy:
1. Try symbol `_vm_fault_enter_prepare`.
2. Fallback string anchor: `"vm_fault_enter_prepare"`.
3. Find a `BL` to a rarely-called function, followed within 4 instructions by `TBZ/TBNZ w0`.
- Patch action:
- NOP the selected `BL` site.
## Expected outcome
- Skip a PMAP-related check helper invocation in vm fault preparation path.
## Target
- A specific check call inside `vm_fault_enter_prepare` path that gates later behavior via `w0` bit test branch.
## IDA MCP evidence
- String: `0xfffffe0007048b3f` (`"vm_fault_enter_prepare"`)
- xrefs:
- `0xfffffe0007badae8`
- `0xfffffe0007bae6d0`
- containing function start: `0xfffffe0007bada3c`
## Risk
- Bypassing vm fault guard logic can destabilize memory-management safety paths and produce hard-to-debug faults.

View File

@@ -0,0 +1,24 @@
# B10 `patch_vm_map_protect`
## How the patch works
- Source: `scripts/patchers/kernel_jb_patch_vm_protect.py`.
- Locator strategy:
1. Try symbol `_vm_map_protect`.
2. Fallback string anchor: `"vm_map_protect("`.
3. In function body, find forward `TBNZ` with high bit test (`bit >= 24`) used as guard.
- Patch action:
- Rewrite that conditional `TBNZ` into unconditional `B target`.
## Expected outcome
- Force bypass of a protection-check branch in `vm_map_protect` flow.
## Target
- High-bit permission/attribute guard branch in vm_map_protect path.
## IDA MCP evidence
- String: `0xfffffe0007049ab7` (`"vm_map_protect(%p,...)"`)
- xref: `0xfffffe0007bc4680`
- containing function start: `0xfffffe0007bc405c`
## Risk
- This may allow mapping/protection transitions that original VM policy intended to reject.

View File

@@ -57,35 +57,37 @@ class KernelJBPatcher(
def find_all(self):
self.patches = []
# Commented patches are broken to boot into panic.
# Group A: Existing patches
# self.patch_amfi_cdhash_in_trustcache() # A1
# self.patch_amfi_execve_kill_path() # A2
# self.patch_task_conversion_eval_internal() # A3
# self.patch_sandbox_hooks_extended() # A4
self.patch_amfi_cdhash_in_trustcache() # A1
# self.patch_amfi_execve_kill_path() # A2 (PANIC)
self.patch_task_conversion_eval_internal() # A3
self.patch_sandbox_hooks_extended() # A4
# Group B: Simple patches (string-anchored / pattern-matched)
# self.patch_post_validation_additional() # B5
# self.patch_proc_security_policy() # B6
# self.patch_proc_pidinfo() # B7
# self.patch_convert_port_to_map() # B8
# self.patch_vm_fault_enter_prepare() # B9
# self.patch_vm_map_protect() # B10
# self.patch_mac_mount() # B11
# self.patch_dounmount() # B12
# self.patch_bsd_init_auth() # B13
# self.patch_spawn_validate_persona() # B14
# self.patch_task_for_pid() # B15
# self.patch_load_dylinker() # B16
# self.patch_shared_region_map() # B17
# self.patch_nvram_verify_permission() # B18
# self.patch_io_secure_bsd_root() # B19
# self.patch_thid_should_crash() # B20
self.patch_post_validation_additional() # B5
# self.patch_proc_security_policy() # B6 (PANIC)
self.patch_proc_pidinfo() # B7
# self.patch_convert_port_to_map() # B8 (PANIC)
self.patch_vm_fault_enter_prepare() # B9
self.patch_vm_map_protect() # B10
self.patch_mac_mount() # B11
self.patch_dounmount() # B12
self.patch_bsd_init_auth() # B13
self.patch_spawn_validate_persona() # B14
self.patch_task_for_pid() # B15
self.patch_load_dylinker() # B16
self.patch_shared_region_map() # B17
self.patch_nvram_verify_permission() # B18
self.patch_io_secure_bsd_root() # B19
self.patch_thid_should_crash() # B20
# Group C: Complex shellcode patches
# self.patch_cred_label_update_execve() # C21
# self.patch_syscallmask_apply_to_proc() # C22
# self.patch_hook_cred_label_update_execve() # C23
# self.patch_kcall10() # C24
self.patch_cred_label_update_execve() # C21
self.patch_syscallmask_apply_to_proc() # C22
# self.patch_hook_cred_label_update_execve() # C23 (PANIC)
# self.patch_kcall10() # C24 (NOT_BOOT)
return self.patches