mirror of
https://github.com/Lakr233/vphone-cli.git
synced 2026-04-05 04:59:05 +08:00
Included commits: - f8a54b8 Update JB kernel patch research notes Refresh and revalidate jailbreak kernel-patcher documentation and runtime-verification notes. Key updates: re-analyzed B13 (patch_bsd_init_auth) and retargeted recommended site to the FSIOC_KERNEL_ROOTAUTH return check in bsd_init rather than the old ldr/cbz/bl heuristic; clarified preferred NOP-of-CBNZ vs forcing ioctl return. Reworked C21 (patch_cred_label_update_execve) to preserve AMFI exec-time flow and instead clear restrictive csflags in a success-tail trampoline; disabled in default schedule until boot validation. Documented that C23 (patch_hook_cred_label_update_execve) was mis-targeting the wrapper (sub_FFFFFE00093D2CE4) instead of the real hook body (_hook_cred_label_update_execve), explaining boot failures and recommending retargeting. Noted syscallmask and vm_fault matcher problems (patch_syscallmask_apply_to_proc historical hit targeted _profile_syscallmask_destroy; patch_vm_fault_enter_prepare matcher resolves to pmap_lock_phys_page path), and updated the runtime-verification summary with follow-up findings and which methods are temporarily commented out/disabled in the default KernelJBPatcher schedule pending staged re-validation. - 6ebac65 fix: patch_bsd_init_auth - 5b224d3 fix: patch_io_secure_bsd_root - e6806bf docs: update patch notes - 0d89c5c Retarget vm_fault_enter_prepare jailbreak patch - 6b9d79b Rework C21 late-exit cred_label patch - ece8cc0 Clean C21 mov matcher encodings - ad2ea7c enabled fixed patch_cred_label_update_execve - c37b6b1 Rebuild syscallmask C22 patch - 363dd7a Rebuild JB C23 as faithful upstream trampoline - 129e648 Disable IOUC MACF; rebuild kcall10 & C22 docs Re-evaluate and rework several JB kernel patches and docs: mark patch_iouc_failed_macf as reverted/disabled (repo-local, over-broad early-return) and replace its patcher with a no-op implementation to emit zero writes by default; update research notes to explain the reanalysis and rationale. Rebuild patch_kcall10: replace the historical 10-arg design with an ABI-correct syscall-439 cave (target + 7 args -> uint64 return), add a new cave builder and munge32 reuse logic in the kcall10 patcher, and enable the method in KernelJBPatcher group. Clarify syscallmask (C22) semantics in docs: upstream C22 is an all-ones-mask retarget (not a NULL install) and keep the rebuilt all-ones wrapper as the authoritative baseline. Misc: minor refactors and helper additions (chained-pointer helpers, cave size/constants, validation and dry-run safeguards) to improve correctness and alignment with IDA/runtime verification. - e1b2365 Rebuild kcall10 as ABI-correct syscall cave - 23090d0 fix patch_iouc_failed_macf - 0056be2 Normalize formatting in research docs Apply whitespace and formatting cleanup across research markdown files for consistency and readability. Adjust table alignment and spacing in 00_patch_comparison_all_variants.md, normalize list/indentation spacing in patch_bsd_init_auth.md and patch_syscallmask_apply_to_proc.md, and add/clean blank lines and minor spacing in patch_kcall10.md. These are non-functional documentation changes only.
146 lines
4.9 KiB
Python
146 lines
4.9 KiB
Python
"""Mixin: KernelJBPatchBsdInitAuthMixin."""
|
|
|
|
from .kernel_jb_base import ARM64_OP_REG, ARM64_REG_W0, ARM64_REG_X0, NOP
|
|
|
|
|
|
class KernelJBPatchBsdInitAuthMixin:
|
|
_ROOTVP_PANIC_NEEDLE = b"rootvp not authenticated after mounting"
|
|
|
|
def patch_bsd_init_auth(self):
|
|
"""Bypass the real rootvp auth failure branch inside ``_bsd_init``.
|
|
|
|
Fresh analysis on ``kernelcache.research.vphone600`` shows the boot gate is
|
|
the in-function sequence:
|
|
|
|
call vnode ioctl handler for ``FSIOC_KERNEL_ROOTAUTH``
|
|
cbnz w0, panic_path
|
|
bl imageboot_needed
|
|
|
|
The older ``ldr/cbz/bl`` matcher was not semantically tied to ``_bsd_init``
|
|
and could false-hit unrelated functions. We now resolve the branch using the
|
|
panic string anchor and the surrounding local control-flow instead.
|
|
"""
|
|
self._log("\n[JB] _bsd_init: ignore FSIOC_KERNEL_ROOTAUTH failure")
|
|
|
|
func_start = self._resolve_symbol("_bsd_init")
|
|
if func_start < 0:
|
|
func_start = self._func_for_rootvp_anchor()
|
|
if func_start is None or func_start < 0:
|
|
self._log(" [-] _bsd_init not found")
|
|
return False
|
|
|
|
site = self._find_bsd_init_rootauth_site(func_start)
|
|
if site is None:
|
|
self._log(" [-] rootauth branch site not found")
|
|
return False
|
|
|
|
branch_off, state = site
|
|
if state == "patched":
|
|
self._log(f" [=] rootauth branch already bypassed at 0x{branch_off:X}")
|
|
return True
|
|
|
|
self.emit(branch_off, NOP, "NOP cbnz (rootvp auth) [_bsd_init]")
|
|
return True
|
|
|
|
def _find_bsd_init_rootauth_site(self, func_start):
|
|
panic_ref = self._rootvp_panic_ref_in_func(func_start)
|
|
if panic_ref is None:
|
|
return None
|
|
|
|
adrp_off, add_off = panic_ref
|
|
bl_panic_off = self._find_panic_call_near(add_off)
|
|
if bl_panic_off is None:
|
|
return None
|
|
|
|
err_lo = bl_panic_off - 0x40
|
|
err_hi = bl_panic_off + 4
|
|
imageboot_needed = self._resolve_symbol("_imageboot_needed")
|
|
|
|
candidates = []
|
|
scan_start = max(func_start, adrp_off - 0x400)
|
|
for off in range(scan_start, adrp_off, 4):
|
|
state = self._match_rootauth_branch_site(off, err_lo, err_hi, imageboot_needed)
|
|
if state is not None:
|
|
candidates.append((off, state))
|
|
|
|
if not candidates:
|
|
return None
|
|
|
|
if len(candidates) > 1:
|
|
live = [item for item in candidates if item[1] == "live"]
|
|
if len(live) == 1:
|
|
return live[0]
|
|
return None
|
|
|
|
return candidates[0]
|
|
|
|
def _rootvp_panic_ref_in_func(self, func_start):
|
|
str_off = self.find_string(self._ROOTVP_PANIC_NEEDLE)
|
|
if str_off < 0:
|
|
return None
|
|
|
|
refs = self.find_string_refs(str_off, *self.kern_text)
|
|
for adrp_off, add_off, _ in refs:
|
|
if self.find_function_start(adrp_off) == func_start:
|
|
return adrp_off, add_off
|
|
return None
|
|
|
|
def _find_panic_call_near(self, add_off):
|
|
for scan in range(add_off, min(add_off + 0x40, self.size), 4):
|
|
if self._is_bl(scan) == self.panic_off:
|
|
return scan
|
|
return None
|
|
|
|
def _match_rootauth_branch_site(self, off, err_lo, err_hi, imageboot_needed):
|
|
insns = self._disas_at(off, 1)
|
|
if not insns:
|
|
return None
|
|
insn = insns[0]
|
|
|
|
if not self._is_call(off - 4):
|
|
return None
|
|
if not self._has_imageboot_call_near(off, imageboot_needed):
|
|
return None
|
|
|
|
if insn.mnemonic == "nop":
|
|
return "patched"
|
|
|
|
if insn.mnemonic != "cbnz":
|
|
return None
|
|
if len(insn.operands) < 2 or insn.operands[0].type != ARM64_OP_REG:
|
|
return None
|
|
if insn.operands[0].reg not in (ARM64_REG_W0, ARM64_REG_X0):
|
|
return None
|
|
|
|
target, _ = self._decode_branch_target(off)
|
|
if target is None or not (err_lo <= target <= err_hi):
|
|
return None
|
|
|
|
return "live"
|
|
|
|
def _is_call(self, off):
|
|
if off < 0:
|
|
return False
|
|
insns = self._disas_at(off, 1)
|
|
return bool(insns) and insns[0].mnemonic.startswith("bl")
|
|
|
|
def _has_imageboot_call_near(self, off, imageboot_needed):
|
|
for scan in range(off + 4, min(off + 0x18, self.size), 4):
|
|
target = self._is_bl(scan)
|
|
if target < 0:
|
|
continue
|
|
if imageboot_needed < 0 or target == imageboot_needed:
|
|
return True
|
|
return False
|
|
|
|
def _func_for_rootvp_anchor(self):
|
|
needle = b"rootvp not authenticated after mounting @%s:%d"
|
|
str_off = self.find_string(needle)
|
|
if str_off < 0:
|
|
return None
|
|
refs = self.find_string_refs(str_off, *self.kern_text)
|
|
if not refs:
|
|
return None
|
|
fn = self.find_function_start(refs[0][0])
|
|
return fn if fn >= 0 else None
|