B10 patch_vm_map_protect
2026-03-06 PCC 26.1 Rework Status
- Preferred upstream reference:
/Users/qaq/Desktop/patch_fw.py. - Final status on PCC 26.1 research: match upstream.
- Upstream patch site: file offset
0x00BC024C(patch(0xBC024C, 0x1400000A)). - Final JB patcher site: file offset
0x00BC024C, VA0xfffffe0007bc424c. - Repo drift removed: the previous repo-only
0x00BC012C/TBNZ X24,#0x20site is no longer accepted because it does not match the known-good upstream gate and is not the correct XNU-backed write-downgrade decision point for PCC 26.1 research.
Preferred Design Target Check
- Match vs upstream:
match. - Why this is the preferred gate: upstream patches the
B.NEthat skips the block clearingVM_PROT_WRITEfrom combined read+write requests. IDA on PCC 26.1 research shows the same local block still exists unchanged. - Red-flag review result: the earlier repo drift to
0x00BC012Cwas a real divergence from upstream. It was removed rather than justified, because IDA + XNU semantics point back to the upstream gate.
Final Patch Site (PCC 26.1 Research)
- Function anchor: the in-image panic string
"vm_map_protect(%p,0x%llx,0x%llx) new=0x%x wired=%x @%s:%d", whose xref lands inside the samevm_map_protectbody. - Patched instruction:
0xfffffe0007bc424c/ file offset0x00BC024C. - Before:
b.ne #0xbc0274. - After:
b #0xbc0274. - Nearby validated block in IDA:
mov w9, #6bics wzr, w9, w20b.ne #0xbc0274← patchedtbnz w8, #0x16, #0xbc0274- ...
and w20, w20, #0xfffffffb
Why This Gate Is Correct
- Fact (IDA): the branch at
0x00BC024Cskips a small block whose only semantic effect on the requested protection register isand w20, w20, #0xfffffffb, i.e. clear bit0x4(VM_PROT_WRITE). - Fact (XNU):
research/reference/xnu/osfmk/vm/vm_map.ccontains the corresponding logic:if ((~v5 & 6) == 0 && (v22 & 0x400000) == 0) { ... v5 &= ~4u; }
- Inference: on PCC 26.1 research,
w20is the local requested-protection value and this block is still the write-downgrade path that upstream intended to bypass. - Conclusion: rewriting the first skip branch to unconditional
bpreserves the known-good upstream behavior: always bypass the downgrade block, instead of patching an earlier unrelated status-bit test.
Reveal Procedure Used In The Reworked Matcher
- Recover the function containing the in-image
vm_map_protect(panic string. - Scan only within that function.
- Find the unique local sequence:
mov wMask, #6bics wzr, wMask, wProtb.ne skiptbnz wEntryFlags, #22, skip- later in the skipped block:
and wProt, wProt, #~VM_PROT_WRITE
- Rewrite only that
b.neto an unconditional branch to the same target.
Focused Validation (2026-03-06)
- Research kernel used: extracted raw Mach-O
/tmp/vphone-kcache-research-26.1.raw. - Research outcome:
hitat0x00BC024C. - Research emitted patch:
b #0x28 [_vm_map_protect]. - Release kernel used: extracted raw Mach-O
/tmp/vphone-kcache-release-26.1.raw. - Release outcome:
hitat0x00B8424C. - Release emitted patch:
b #0x28 [_vm_map_protect]. - Method: focused
KernelJBPatcher.patch_vm_map_protect()dry-runs, in the Python environment this repository had on that date. Both the Python patcher and that environment are gone; the port isSources/FirmwarePatcher/Kernel/JailbreakPatches/. - Result: the reworked matcher hits the same semantic gate on both PCC 26.1 research and PCC 26.1 release, and the research hit matches upstream exactly.
Why This Should Generalize Beyond The Current Research Image
- The matcher does not key on a hardcoded offset, a specific file-layout delta, or a single fragile operand string.
- It anchors on an in-image
vm_map_protect(panic string that is tied to the same core VM function across variants. - Inside that function it requires a compact semantic micro-CFG, not a single mnemonic:
mov wMask, #6(combined read+write test)bics wzr, wMask, wProtb.ne skiptbnz wEntryFlags, #22, skip- later
and wProt, wProt, #~VM_PROT_WRITE
- That shape is directly backed by the XNU write-downgrade logic, so it should survive ordinary offset drift between PCC 26.1 research, PCC 26.1 release, and likely nearby 26.3 release kernels unless Apple materially restructures this code path.
- If Apple does materially restructure it, the matcher fails closed by requiring a unique hit rather than guessing.
Runtime Matcher Cost
- Search scope is limited to one recovered function body, not the whole kernel text.
- The scan is linear over that function with small fixed-width decode windows (
10instructions for the main pattern,1instruction for the local write-clear search). - This keeps the runtime cost negligible relative to the broader JB patch pass while still being much more semantic than the earlier shallow
tbnz bit>=24heuristic.
Superseded Earlier Analysis
The older 0x00BC012C / TBNZ X24,#0x20 analysis below is retained only as historical context. It is superseded by the 2026-03-06 rework above and should not be treated as the preferred patch design for PCC 26.1 research.
Patch Goal
Bypass a high-bit protection guard by converting a TBNZ check into unconditional B.
Binary Targets (IDA + Recovered Symbols)
- Recovered symbol:
vm_map_protectat0xfffffe0007bd08d8. - Anchor string:
"vm_map_protect(%p,0x%llx,0x%llx) new=0x%x wired=%x @%s:%d"at0xfffffe0007049e44. - Anchor xref:
0xfffffe0007bd0efcinvm_map_protect.
Call-Stack Analysis
Representative static callers of vm_map_protect include:
sub_FFFFFE0007AF3968sub_FFFFFE0007B90928sub_FFFFFE0007B9F844sub_FFFFFE0007FD6EB0- additional VM/subsystem callsites
Patch-Site / Byte-Level Change
- Selected guard site:
0xfffffe0007bd09a8 - Before:
- bytes:
78 24 00 B7 - asm:
TBNZ X24, #0x20, loc_FFFFFE0007BD0E34
- bytes:
- After:
- bytes:
23 01 00 14 - asm:
B #0x48C(to same target)
- bytes:
Pseudocode (Before)
Pseudocode (After)
Symbol Consistency
- Recovered symbol name and patch context are consistent.
Patch Metadata
- Patch document:
patch_vm_map_protect.md(B10). - Primary patcher module:
scripts/patchers/kernel_jb_patch_vm_protect.py. - Analysis mode: static binary analysis (IDA-MCP + disassembly + recovered symbols), no runtime patch execution.
Target Function(s) and Binary Location
- Primary target: recovered symbol
vm_map_protect. - Patchpoint:
0xfffffe0007bd09a8(tbnz-> unconditionalb).
Kernel Source File Location
- Expected XNU source:
osfmk/vm/vm_user.c(vm_map_protect). - Confidence:
high.
Function Call Stack
- Primary traced chain (from
Call-Stack Analysis): - Representative static callers of
vm_map_protectinclude: sub_FFFFFE0007AF3968sub_FFFFFE0007B90928sub_FFFFFE0007B9F844sub_FFFFFE0007FD6EB0- The upstream entry(s) and patched decision node are linked by direct xref/callsite evidence in this file.
Patch Hit Points
- Key patchpoint evidence (from
Patch-Site / Byte-Level Change): - Selected guard site:
0xfffffe0007bd09a8 - Before:
- bytes:
78 24 00 B7 - asm:
TBNZ X24, #0x20, loc_FFFFFE0007BD0E34 - After:
- bytes:
23 01 00 14 - The before/after instruction transform is constrained to this validated site.
Current Patch Search Logic
- Implemented in
scripts/patchers/kernel_jb_patch_vm_protect.py. - Site resolution uses anchor + opcode-shape + control-flow context; ambiguous candidates are rejected.
- The patch is applied only after a unique candidate is confirmed in-function.
- Anchor string:
"vm_map_protect(%p,0x%llx,0x%llx) new=0x%x wired=%x @%s:%d"at0xfffffe0007049e44. - Anchor xref:
0xfffffe0007bd0efcinvm_map_protect.
Validation (Static Evidence)
- Verified with IDA-MCP disassembly/decompilation, xrefs, and callgraph context for the selected site.
- Cross-checked against recovered symbols in
research/kernel_symbols/json/kernelcache.research.vphone600.bin.symbols.json. - Address-level evidence in this document is consistent with patcher matcher intent.
Expected Failure/Panic if Unpatched
- High-bit protect guard keeps enforcing restrictive branch, causing vm_protect denial in jailbreak memory workflows.
Risk / Side Effects
- This patch weakens a kernel policy gate by design and can broaden behavior beyond stock security assumptions.
- Potential side effects include reduced diagnostics fidelity and wider privileged surface for patched workflows.
Symbol Consistency Check
- Recovered-symbol status in
kernelcache.research.vphone600.bin.symbols.json:match. - Canonical symbol hit(s):
vm_map_protect. - Where canonical names are absent, this document relies on address-level control-flow and instruction evidence; analyst aliases are explicitly marked as aliases.
- IDA-MCP lookup snapshot (2026-03-05):
vm_map_protect->vm_map_protectat0xfffffe0007bd08d8.
Open Questions and Confidence
- Open question: verify future firmware drift does not move this site into an equivalent but semantically different branch.
- Overall confidence for this patch analysis:
high(symbol match + control-flow/byte evidence).
Evidence Appendix
- Detailed addresses, xrefs, and rationale are preserved in the existing analysis sections above.
- For byte-for-byte patch details, refer to the patch-site and call-trace subsections in this file.
Runtime + IDA Verification (2026-03-05, historical)
Historical note: this older runtime-verification block is preserved for traceability only. Its
0x00BC012C/0xFFFFFE0007BD09A8analysis is superseded by the 2026-03-06 upstream-aligned rework above, whose accepted site is0x00BC024C/0xFFFFFE0007BC424C.
- Verification timestamp (UTC):
2026-03-05T14:55:58.795709+00:00 - Kernel input:
/Users/qaq/Documents/Firmwares/PCC-CloudOS-26.3-23D128/kernelcache.research.vphone600 - Base VA:
0xFFFFFE0007004000 - Runtime status:
hit(1 patch writes, method_return=True) - Included in
KernelJBPatcher.find_all():False - IDA mapping:
1/1points in recognized functions;0points are code-cave/data-table writes. - IDA mapping status:
ok(IDA runtime mapping loaded.) - Call-chain mapping status:
ok(IDA call-chain report loaded.) - Call-chain validation:
1function nodes,1patch-point VAs. - IDA function sample:
vm_map_protect - Chain function sample:
vm_map_protect - Caller sample:
_Xmach_vm_protect,_Xprotect,__ZN27IOGuardPageMemoryDescriptor5doMapEP7_vm_mapPyjyy,mach_vm_protect_trap,mprotect,setrlimit - Callee sample:
lck_rw_done,pmap_protect_options,sub_FFFFFE0007B1D788,sub_FFFFFE0007B1EBF0,sub_FFFFFE0007B840E0,sub_FFFFFE0007B84C5C - Verdict:
questionable - Recommendation: Hit is valid but patch is inactive in find_all(); enable only after staged validation.
- Key verified points:
0xFFFFFE0007BD09A8(vm_map_protect): b #0x48C [_vm_map_protect] |782400b7 -> 23010014- Artifacts:
research/kernel_jailbreak_patches/runtime_verification/runtime_verification_report.json - Artifacts:
research/kernel_jailbreak_patches/runtime_verification/ida_runtime_patch_points.json - Artifacts:
research/kernel_jailbreak_patches/runtime_verification/ida_patch_chain_report.json - Artifacts:
Research/KernelJailbreakPatches/RuntimeVerification/ida_patch_chain_report.md
2026-03-06 Rework
- Upstream target (
/Users/qaq/Desktop/patch_fw.py):match. - Final research site:
0x00BC024C(0xFFFFFE0007BC424C). - Anchor class:
string. Runtime reveal starts from the in-image"vm_map_protect("string, resolves the function, then matches the unique write-downgrade blockmov #6 ; bics wzr,mask,prot ; b.ne skip ; tbnz #22,skip ; ... and prot,#~VM_PROT_WRITE. - Why this site: it is the exact upstream branch gate that conditionally strips
VM_PROT_WRITEbefore later VME updates. The older drift to0x00BC012Clands in unrelated preflight/error handling and is rejected. - Release/generalization rationale: the panic string and the local BICS/TBNZ/write-clear shape are source-backed and should survive stripped release kernels with low matcher cost.
- Performance note: one string-xref resolution and one function-local scan with a short semantic confirmation window.
- Focused PCC 26.1 research dry-run:
hit, 1 write at0x00BC024C.