mirror of
https://github.com/Lakr233/vphone-cli.git
synced 2026-04-05 13:09:06 +08:00
Refactor TXM patching and fw_patch_jb flow
Separate dev vs JB TXM patches and streamline fw_patch_jb. fw_patch_dev now calls patch_txm and uses TXMPatcher as TXMDevPatcher; txm_dev.py doc/comments clarify it is dev-only and removes the trustcache bypass from the dev finder. fw_patch_jb was reorganized: COMPONENTS and JB_COMPONENTS lists define base and JB-only patches, the previous subprocess call to run fw_patch.py was removed, and component discovery/patching is unified (with updated messages). txm_jb now only implements the JB-exclusive selector24 extension, relying on dev patches being applied separately.
This commit is contained in:
@@ -17,13 +17,16 @@ from fw_patch import (
|
||||
patch_ibss,
|
||||
patch_kernelcache,
|
||||
patch_llb,
|
||||
patch_txm,
|
||||
patch_component,
|
||||
)
|
||||
from patchers.txm_dev import TXMPatcher
|
||||
from patchers.txm_dev import TXMPatcher as TXMDevPatcher
|
||||
|
||||
|
||||
def patch_txm_dev(data):
|
||||
p = TXMPatcher(data)
|
||||
if not patch_txm(data):
|
||||
return False
|
||||
p = TXMDevPatcher(data)
|
||||
n = p.apply()
|
||||
print(f" [+] {n} TXM dev patches applied dynamically")
|
||||
return n > 0
|
||||
|
||||
@@ -1,36 +1,32 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
fw_patch_jb.py — Apply jailbreak extension patches after base fw_patch.
|
||||
fw_patch_jb.py — Patch boot-chain components using dev patches + JB extensions.
|
||||
|
||||
Usage:
|
||||
python3 fw_patch_jb.py [vm_directory]
|
||||
|
||||
This script runs base `fw_patch.py` first, then applies additional JB-oriented
|
||||
patches found dynamically.
|
||||
This script extends fw_patch_dev with additional JB-oriented patches.
|
||||
"""
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
from fw_patch import (
|
||||
find_file,
|
||||
find_restore_dir,
|
||||
load_firmware,
|
||||
save_firmware,
|
||||
patch_avpbooter,
|
||||
patch_ibec,
|
||||
patch_ibss,
|
||||
patch_kernelcache,
|
||||
patch_llb,
|
||||
patch_component,
|
||||
)
|
||||
from fw_patch_dev import patch_txm_dev
|
||||
from patchers.iboot_jb import IBootJBPatcher
|
||||
from patchers.kernel_jb import KernelJBPatcher
|
||||
from patchers.txm_jb import TXMJBPatcher
|
||||
|
||||
|
||||
def patch_kernelcache_jb(data):
|
||||
kp = KernelJBPatcher(data)
|
||||
n = kp.apply()
|
||||
print(f" [+] {n} kernel JB patches applied dynamically")
|
||||
return n > 0
|
||||
|
||||
|
||||
def patch_ibss_jb(data):
|
||||
p = IBootJBPatcher(data, mode="ibss", label="Loaded iBSS")
|
||||
n = p.apply()
|
||||
@@ -45,7 +41,32 @@ def patch_txm_jb(data):
|
||||
return n > 0
|
||||
|
||||
|
||||
def patch_kernelcache_jb(data):
|
||||
kp = KernelJBPatcher(data)
|
||||
n = kp.apply()
|
||||
print(f" [+] {n} kernel JB patches applied dynamically")
|
||||
return n > 0
|
||||
|
||||
|
||||
# Base components — same as fw_patch_dev (dev TXM instead of base TXM).
|
||||
COMPONENTS = [
|
||||
# (name, search_base_is_restore, search_patterns, patch_function, preserve_payp)
|
||||
("AVPBooter", False, ["AVPBooter*.bin"], patch_avpbooter, False),
|
||||
("iBSS", True, ["Firmware/dfu/iBSS.vresearch101.RELEASE.im4p"], patch_ibss, False),
|
||||
("iBEC", True, ["Firmware/dfu/iBEC.vresearch101.RELEASE.im4p"], patch_ibec, False),
|
||||
(
|
||||
"LLB",
|
||||
True,
|
||||
["Firmware/all_flash/LLB.vresearch101.RELEASE.im4p"],
|
||||
patch_llb,
|
||||
False,
|
||||
),
|
||||
("TXM", True, ["Firmware/txm.iphoneos.research.im4p"], patch_txm_dev, True),
|
||||
("kernelcache", True, ["kernelcache.research.vphone600"], patch_kernelcache, True),
|
||||
]
|
||||
|
||||
# JB extension components — applied AFTER base components on the same files.
|
||||
JB_COMPONENTS = [
|
||||
# (name, search_base_is_restore, search_patterns, patch_function, preserve_payp)
|
||||
("iBSS (JB)", True, ["Firmware/dfu/iBSS.vresearch101.RELEASE.im4p"], patch_ibss_jb, False),
|
||||
("TXM (JB)", True, ["Firmware/txm.iphoneos.research.im4p"], patch_txm_jb, True),
|
||||
@@ -59,24 +80,6 @@ COMPONENTS = [
|
||||
]
|
||||
|
||||
|
||||
def patch_component(path, patch_fn, name, preserve_payp):
|
||||
print(f"\n{'=' * 60}")
|
||||
print(f" {name}: {path}")
|
||||
print(f"{'=' * 60}")
|
||||
|
||||
im4p, data, was_im4p, original_raw = load_firmware(path)
|
||||
fmt = "IM4P" if was_im4p else "raw"
|
||||
extra = f", fourcc={im4p.fourcc}" if was_im4p and im4p else ""
|
||||
print(f" format: {fmt}{extra}, {len(data)} bytes")
|
||||
|
||||
if not patch_fn(data):
|
||||
print(f" [-] FAILED: {name}")
|
||||
sys.exit(1)
|
||||
|
||||
save_firmware(path, im4p, data, was_im4p, original_raw if preserve_payp else None)
|
||||
print(f" [+] saved ({fmt})")
|
||||
|
||||
|
||||
def main():
|
||||
vm_dir = sys.argv[1] if len(sys.argv) > 1 else os.getcwd()
|
||||
vm_dir = os.path.abspath(vm_dir)
|
||||
@@ -85,12 +88,6 @@ def main():
|
||||
print(f"[-] Not a directory: {vm_dir}")
|
||||
sys.exit(1)
|
||||
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
fw_patch_script = os.path.join(script_dir, "fw_patch.py")
|
||||
|
||||
print("[*] Running base fw_patch first ...", flush=True)
|
||||
subprocess.run([sys.executable, fw_patch_script, vm_dir], check=True)
|
||||
|
||||
restore_dir = find_restore_dir(vm_dir)
|
||||
if not restore_dir:
|
||||
print(f"[-] No *Restore* directory found in {vm_dir}")
|
||||
@@ -98,15 +95,22 @@ def main():
|
||||
|
||||
print(f"[*] VM directory: {vm_dir}")
|
||||
print(f"[*] Restore directory: {restore_dir}")
|
||||
print(f"[*] Applying {len(COMPONENTS)} JB extension components ...")
|
||||
print(f"[*] Patching {len(COMPONENTS)} boot-chain components (jailbreak mode) ...")
|
||||
|
||||
for name, in_restore, patterns, patch_fn, preserve_payp in COMPONENTS:
|
||||
search_base = restore_dir if in_restore else vm_dir
|
||||
path = find_file(search_base, patterns, name)
|
||||
patch_component(path, patch_fn, name, preserve_payp)
|
||||
|
||||
if JB_COMPONENTS:
|
||||
print(f"\n[*] Applying {len(JB_COMPONENTS)} JB extension patches ...")
|
||||
for name, in_restore, patterns, patch_fn, preserve_payp in JB_COMPONENTS:
|
||||
search_base = restore_dir if in_restore else vm_dir
|
||||
path = find_file(search_base, patterns, name)
|
||||
patch_component(path, patch_fn, name, preserve_payp)
|
||||
|
||||
print(f"\n{'=' * 60}")
|
||||
print(" JB extension patching complete!")
|
||||
print(f" All components patched successfully (jailbreak mode)!")
|
||||
print(f"{'=' * 60}")
|
||||
|
||||
|
||||
|
||||
@@ -58,17 +58,13 @@ def _find_asm_pattern(data, asm_str):
|
||||
|
||||
|
||||
class TXMPatcher:
|
||||
"""Dynamic patcher for TXM images.
|
||||
"""Dev-only dynamic patcher for TXM images.
|
||||
|
||||
Patches:
|
||||
1. Trustcache binary-search BL → mov x0, #0
|
||||
(in the AMFI cert verification function identified by the
|
||||
unique constant 0x20446 loaded into w19)
|
||||
2. Selector24 hash extraction: nop LDR X1 + nop BL
|
||||
3. get-task-allow entitlement check BL → mov x0, #1
|
||||
4. Selector42|29: shellcode hook + manifest flag force
|
||||
5. debugger entitlement check BL → mov w0, #1
|
||||
6. developer-mode guard branch → nop
|
||||
Patches (dev-specific only — base trustcache bypass is in txm.py):
|
||||
1. get-task-allow entitlement check BL → mov x0, #1
|
||||
2. Selector42|29: shellcode hook + manifest flag force
|
||||
3. debugger entitlement check BL → mov w0, #1
|
||||
4. developer-mode guard branch → nop
|
||||
"""
|
||||
|
||||
def __init__(self, data, verbose=True):
|
||||
@@ -109,7 +105,6 @@ class TXMPatcher:
|
||||
|
||||
def find_all(self):
|
||||
self.patches = []
|
||||
self.patch_trustcache_bypass()
|
||||
self.patch_get_task_allow_force_true()
|
||||
self.patch_selector42_29_shellcode()
|
||||
self.patch_debugger_entitlement_force_true()
|
||||
|
||||
@@ -13,7 +13,11 @@ NOP = _asm("nop")
|
||||
|
||||
|
||||
class TXMJBPatcher(TXMDevPatcher):
|
||||
"""JB TXM patcher: dev TXM patches + selector24 extension."""
|
||||
"""JB-only TXM patcher: selector24 CS hash-extraction bypass.
|
||||
|
||||
Dev patches are applied separately by txm_dev.py; this class only
|
||||
adds the JB-exclusive selector24 extension.
|
||||
"""
|
||||
|
||||
def apply(self):
|
||||
self.find_all()
|
||||
@@ -26,10 +30,6 @@ class TXMJBPatcher(TXMDevPatcher):
|
||||
def find_all(self):
|
||||
self.patches = []
|
||||
self.patch_selector24_hash_extraction_nop()
|
||||
self.patch_get_task_allow_force_true()
|
||||
self.patch_selector42_29_shellcode()
|
||||
self.patch_debugger_entitlement_force_true()
|
||||
self.patch_developer_mode_bypass()
|
||||
return self.patches
|
||||
|
||||
def patch_selector24_hash_extraction_nop(self):
|
||||
|
||||
Reference in New Issue
Block a user