Binary Kernelcache Patch Verification Report
Date: 2026-02-27
Scope
Verify that the dynamic kernel patch finder (scripts/patchers/kernel.py) produces
the same binary result as the legacy hardcoded patch list on vphone600, then
apply the dynamic patcher to a freshly extracted vresearch101 kernelcache.
Inputs
- Original vphone600 raw kernel:
/tmp/kc_vphone600_orig.raw - vphone600 upstream hardcoded patch list:
super-tart-vphone-private/CFW/patch_fw.py - Dynamic patcher:
scripts/patchers/kernel.py - VM kernelcache image (vresearch101):
VM/iPhone17,3_26.1_23B85_Restore/kernelcache.research.vresearch101
Method
- Apply legacy hardcoded patches to
/tmp/kc_vphone600_orig.rawusing binary replacement (32-bit writes) and save as/tmp/kc_vphone600_upstream.raw. - Run
KernelPatcher.find_all()on/tmp/kc_vphone600_orig.raw, apply all dynamic patches, and save as/tmp/kc_vphone600_dynamic.raw. - Compare the two patched binaries with
cmp -l. - Re-extract a clean vresearch101 kernelcache using
pyimg4 im4p extract, save as/tmp/kc_vresearch1_orig.raw. - Run the dynamic patcher on
/tmp/kc_vresearch1_orig.raw, save as/tmp/kc_vresearch1_dynamic.raw.
Outputs
/tmp/kc_vphone600_upstream.raw/tmp/kc_vphone600_dynamic.raw/tmp/kc_vresearch1_orig.raw/tmp/kc_vresearch1_dynamic.raw
Checksums (SHA-256)
/tmp/kc_vphone600_orig.raw:b6846048f3a60eab5f360fcc0f3dcb5198aa0476c86fb06eb42f6267cdbfcae0/tmp/kc_vphone600_upstream.raw:373e016d34ae5a2d8ba7ba96c920f4f6700dea503e3689d06a99e90ebec701c8/tmp/kc_vphone600_dynamic.raw:373e016d34ae5a2d8ba7ba96c920f4f6700dea503e3689d06a99e90ebec701c8/tmp/kc_vresearch1_orig.raw:c673c9b8226ea774d1d935427760e2e9a48200fd1daf0ef584dc88df0dccefde/tmp/kc_vresearch1_dynamic.raw:f36a78ce59c658df85ecdead56d46370a1107181689091cf798e529664f6e2b5
vphone600: Hardcoded vs Dynamic
Result: byte-identical output between hardcoded and dynamic patching.
KernelPatcherpatches found: 26- Hardcoded patches applied: 26
cmp -l /tmp/kc_vphone600_upstream.raw /tmp/kc_vphone600_dynamic.raw: no output (files identical)
Hardcoded Patch List (vphone600)
Offsets and 32-bit patch values, taken from patch_fw.py:
TXM Patch Details
Dynamic patcher locates the "TXM [Error]: CodeSignature" string, finds the
following tbnz in the log/error path, and NOPs it.
vphone600 disassembly around the patch (0xFFAB98)
Before:
After:
vresearch101: Dynamic Patch Run
Extraction:
Dynamic patcher results:
- Patches found/applied: 26
- TXM patch location:
0xFA6B98(NOPtbnz w8, #0, #0xfa6c80) - Patched output:
/tmp/kc_vresearch1_dynamic.raw
Conclusion
For vphone600, the dynamic patcher output is byte-identical to the legacy hardcoded patch list, indicating functional equivalence on this kernelcache. The same dynamic patcher also successfully patches the freshly extracted vresearch101 kernelcache with the expected TXM NOP and a full 26-patch set.
Targeted Re-Verification (2026-03-05)
Scope for this pass was limited to the user-requested kernel patches in
KernelPatcher.find_all() order:
- 6
patch_PE_i_can_has_debugger(mov x0,#1) - 7
patch_PE_i_can_has_debugger(ret) - 8
patch_post_validation_nop(NOP TXM post-validationtbnz) - 9
patch_post_validation_cmp(cmp w0,w0) - 10
patch_check_dyld_policy(BL -> mov w0,#1at@1)
Input kernel:
vm/iPhone17,3_26.1_23B85_Restore/kernelcache.research.vphone600(IM4P payload decompressed in-memory; no file write during verification)
Regular and Development both use the same kernel patch entrypoint:
scripts/fw_patch.py->patch_kernelcache()->KernelPatcher.apply()scripts/fw_patch_dev.pyreusespatch_kernelcachefromfw_patch.py
Verification Results
Structural Evidence (IDA + raw context)
- Patch 6/7 site is a dedicated tiny function entry at
0xFFFFFE00082CC138; patching first two instructions produces exactmov x0,#1; retstub. Call fanout observed by patcher histogram: 82 callers. - Patch 8 site is the
tbnzimmediately after the"TXM [Error]: CodeSignature"log call chain (ADRP+ADD string->BL->...->TBNZ), matching patch intent. - Patch 9 site is in AMFI code path with local pattern:
BL->CMP W0,#imm->B.NE; target instruction at0x...45ACiscmp w0,#2before replacement. - Patch 10 (@1) site is in the function containing
"com.apple.developer.swift-playgrounds-app.development-build"and matches the expectedBLfollowed by a conditional onW0; theBLat0x...50BCis replaced bymov w0,#1.
Conclusion (2026-03-05 pass)
The requested items 6/7/8/9/10 (with 10 interpreted as @1) all:
- resolve to deterministic patch sites on clean
kernelcache.research.vphone600, - replace the intended original instructions, and
- align with the expected code path in IDA.