mirror of
https://github.com/Lakr233/vphone-cli.git
synced 2026-04-05 04:59:05 +08:00
80 lines
2.9 KiB
Python
80 lines
2.9 KiB
Python
"""Mixin: KernelJBPatchProcPidinfoMixin."""
|
|
|
|
from .kernel_jb_base import ARM64_OP_IMM, NOP
|
|
|
|
|
|
class KernelJBPatchProcPidinfoMixin:
|
|
def patch_proc_pidinfo(self):
|
|
"""Bypass pid-0 checks in _proc_info: NOP first 2 CBZ/CBNZ on w-regs.
|
|
|
|
Anchor: find _proc_info via its switch-table pattern, then NOP the
|
|
first two CBZ/CBNZ instructions that guard against pid 0.
|
|
"""
|
|
self._log("\n[JB] _proc_pidinfo: NOP pid-0 guard (2 sites)")
|
|
|
|
# Try symbol first
|
|
foff = self._resolve_symbol("_proc_pidinfo")
|
|
if foff >= 0:
|
|
func_end = min(foff + 0x80, self.size)
|
|
hits = []
|
|
for off in range(foff, func_end, 4):
|
|
d = self._disas_at(off)
|
|
if (
|
|
d
|
|
and d[0].mnemonic in ("cbz", "cbnz")
|
|
and d[0].op_str.startswith("w")
|
|
):
|
|
hits.append(off)
|
|
if len(hits) >= 2:
|
|
self.emit(hits[0], NOP, "NOP [_proc_pidinfo pid-0 guard A]")
|
|
self.emit(hits[1], NOP, "NOP [_proc_pidinfo pid-0 guard B]")
|
|
return True
|
|
|
|
# Find _proc_info by switch table pattern (same as proc_security_policy)
|
|
proc_info_func = -1
|
|
ks, ke = self.kern_text
|
|
for off in range(ks, ke - 8, 4):
|
|
d = self._disas_at(off, 2)
|
|
if len(d) < 2:
|
|
continue
|
|
i0, i1 = d[0], d[1]
|
|
if i0.mnemonic != "sub" or i1.mnemonic != "cmp":
|
|
continue
|
|
if len(i0.operands) < 3:
|
|
continue
|
|
if i0.operands[2].type != ARM64_OP_IMM or i0.operands[2].imm != 1:
|
|
continue
|
|
if len(i1.operands) < 2:
|
|
continue
|
|
if i1.operands[1].type != ARM64_OP_IMM or i1.operands[1].imm != 0x21:
|
|
continue
|
|
if i0.operands[0].reg != i1.operands[0].reg:
|
|
continue
|
|
proc_info_func = self.find_function_start(off)
|
|
break
|
|
|
|
if proc_info_func < 0:
|
|
self._log(" [-] _proc_info function not found")
|
|
return False
|
|
|
|
# Find first CBZ x0 (null proc check) and the CBZ/CBNZ wN after
|
|
# the first BL in the prologue region
|
|
hits = []
|
|
prologue_end = min(proc_info_func + 0x80, self.size)
|
|
for off in range(proc_info_func, prologue_end, 4):
|
|
d = self._disas_at(off)
|
|
if not d:
|
|
continue
|
|
i = d[0]
|
|
if i.mnemonic in ("cbz", "cbnz"):
|
|
# CBZ x0 (null check) or CBZ wN (pid-0 check)
|
|
hits.append(off)
|
|
|
|
if len(hits) < 2:
|
|
self._log(f" [-] expected 2+ early CBZ/CBNZ, found {len(hits)}")
|
|
return False
|
|
|
|
self.emit(hits[0], NOP, "NOP [_proc_pidinfo pid-0 guard A]")
|
|
self.emit(hits[1], NOP, "NOP [_proc_pidinfo pid-0 guard B]")
|
|
return True
|