Kernel-Patcher Guardrail Pattern in vphone-cli: AGENTS.md Safety Rules Explained
The kernel-patcher guardrail pattern defined in AGENTS.md enforces semantic, tool-driven kernel modifications that prohibit hardcoded offsets and require Capstone disassembly, Keystone assembly generation, and documented reveal procedures to ensure patches remain portable across firmware revisions.
The AGENTS.md file in the Lakr233/vphone-cli repository establishes a strict kernel-patcher guardrail pattern that governs how developers modify iOS kernels within the project. These rules ensure that every patch is resilient to firmware changes, reproducible across builds, and fully auditable through semantic anchoring and standardized tooling.
What Is the Kernel-Patcher Guardrail Pattern?
The kernel-patcher guardrail pattern is a comprehensive safety framework documented in AGENTS.md that mandates how kernel patchers must operate within the vphone-cli ecosystem. Rather than relying on brittle byte patterns or fixed memory addresses, the pattern requires developers to use dynamic analysis tools and semantic anchors to locate and modify kernel code, ensuring modifications survive across different XNU kernel versions.
The Ten Mandatory Safety Rules
According to the source code in AGENTS.md (lines 55–65), the guardrail pattern enforces ten specific requirements:
- No hard-coded offsets: Developers must never embed raw file offsets, virtual addresses, or pre-assembled instruction bytes in patch logic.
- Capstone-based instruction matching: All instruction identification must derive from Capstone disassembly results (mnemonic and operands), not literal string matching.
- Keystone-backed byte generation: Replacement instructions must be generated using Keystone-engine helpers or predefined constants like
NOPorMOV_W0_0. - Semantic anchoring: Patch points must be located via symbol look-ups, string XREFs, local call-flow analysis, or XNU correlation rather than arbitrary offsets.
- Documented reveal procedures: Before retargeting any patch, developers must write detailed reveal procedures and validation steps in research documents or commit notes.
- Specific workflow for
patch_bsd_init_auth: This critical patch requires a deterministic reveal flow including recovery ofbsd_init, locating the root-vp panic block, and identifying the unique in-functioncallbefore modification. - Standardized tooling: Patchers must use
capstonefor disassembly,keystone-enginefor assembly, andpyimg4for IM4P handling. - Dynamic pattern finding: Implementations must employ string anchors, ADRP+ADD XREFs, and BL-frequency analysis instead of static offsets.
- Mandatory patch logging: Every patch must log its offset and before/after state for debugging and verification.
- Virtual environment isolation: All Python patcher work must execute within the project-provided virtual environment created via
make setup_venv.
Core Guardrails for Safe Kernel Patching
Semantic Anchoring Over Static Offsets
The guardrail pattern strictly prohibits hardcoding file offsets or virtual addresses. Instead, as implemented in scripts/patchers/cfw.py, patchers must locate functions through symbol tables or cross-references. For example, when patching bsd_init_auth, the code recovers bsd_init through symbol look-up, then navigates local call-flow to find the target branch gate. This approach guarantees that patches are resilient to changes in kernel layout and can be applied to different firmware builds.
Tool-Driven Bytecode Manipulation
Every instruction match and replacement must flow through established disassembly and assembly engines. The pattern mandates Capstone for decoding instructions into mnemonics and operands, and Keystone for generating replacement bytes. This toolchain ensures that generated code respects the target ISA and keeps the patch codebase consistent, preventing the brittleness associated with manual byte manipulation.
Documented Reveal Procedures
Before modifying any patch target, developers must document the reveal procedure in files like research/0_binary_patch_comparison.md. This requirement ensures traceability and creates an audit trail explaining why specific patch points were selected. For the patch_bsd_init_auth workflow specifically, the allowed reveal flow is explicitly defined: recover bsd_init, locate the root-vp panic block, find the unique in-function call, identify cbnz w0/x0, panic and bl imageboot_needed, then patch the branch gate only.
Required Toolchain and Environment
The kernel-patcher guardrail pattern mandates a specific, battle-tested toolchain across the project:
capstone: For disassembling ARM64 instructions and extracting semantic metadata.keystone-engine: For assembling new instructions into valid machine code.pyimg4: For handling IM4P image formats during the patching process.- Virtual environment: All work must run inside the project venv created with
make setup_venvand activated viasource .venv/bin/activateto ensure dependency consistency and reproducible builds.
Practical Implementation Examples
Matching Instructions with Capstone
Rather than comparing raw bytes, the guardrail pattern requires semantic matching through Capstone:
from capstone import Cs, CS_ARCH_ARM64, CS_MODE_ARM
md = Cs(CS_ARCH_ARM64, CS_MODE_ARM)
code = b"\x00\x00\x80\xd2" # MOV X0, #0
for insn in md.disasm(code, 0x1000):
if insn.mnemonic == "mov" and insn.op_str == "x0, #0":
# Found the pattern – safe to replace
pass
This approach uses insn.mnemonic and insn.op_str derived from Capstone decode results, preventing brittle string-based matching and enabling semantic-aware detection of instruction patterns.
Generating Bytes with Keystone
Replacement instructions must use Keystone-backed helpers:
from keystone import Ks, KS_ARCH_ARM64, KS_MODE_ARM
ks = Ks(KS_ARCH_ARM64, KS_MODE_ARM)
encoding, _ = ks.asm("nop")
# `encoding` now contains the correct NOP bytes for ARM64
All replacement instruction bytes must come from such helpers or predefined constants like NOP or MOV_W0_0, guaranteeing that generated code respects the target instruction set architecture.
Semantic Symbol Lookups
Instead of hardcoded offsets, patchers use semantic anchors:
import macholib.MachO as MachO
def find_symbol(macho_path, symbol_name):
m = MachO.MachO(macho_path)
for header in m.headers:
for cmd in header.commands:
if cmd[0].get_cmd_name() == "LC_SYMTAB":
for sym in cmd[2]:
if sym[0] == symbol_name:
return sym[1] # address
return None
This function locates bsd_init by name rather than relying on fixed offsets, making the patch portable across kernel versions and reducing reliance on external symbol dumps.
Mandatory Patch Logging
Every modification requires logging for auditability:
def log_patch(addr, old_bytes, new_bytes):
print(f"[PATCH] 0x{addr:x}: {old_bytes.hex()} -> {new_bytes.hex()}")
Each patch is logged with its offset and before/after state, providing visibility for debugging and verification throughout the patching process.
Key Files and Their Roles
Several files enforce and demonstrate the kernel-patcher guardrail pattern:
AGENTS.md: The central document defining all guardrails and safety requirements.scripts/patchers/cfw.py: The entry point implementing guardrail-compliant patching workflows.research/0_binary_patch_comparison.md: Where reveal procedures and validation steps are recorded as required by the documentation guardrail.scripts/setup_venv.sh: Creates the isolated Python environment required for consistent patcher operation.
Summary
- The kernel-patcher guardrail pattern in
AGENTS.mdmandates semantic, tool-driven kernel modifications that eliminate hardcoded offsets. - All instruction matching must use Capstone disassembly results, while Keystone generates all replacement bytes to ensure ISA compliance.
- Semantic anchoring via symbol look-ups and XREFs replaces brittle offset-based patching, making patches portable across firmware revisions.
- The
patch_bsd_init_authworkflow requires explicit, documented reveal procedures before modification to ensure deterministic, reproducible results. - Mandatory patch logging and virtual environment usage ensure traceability and consistent builds across different development environments.
Frequently Asked Questions
What makes the kernel-patcher guardrail pattern different from traditional binary patching?
Traditional binary patching often relies on hardcoded offsets and byte patterns that break when firmware updates change memory layouts. The guardrail pattern enforces semantic anchoring using symbol tables and disassembly metadata, making patches resilient across different kernel versions and build configurations while maintaining a clear audit trail.
Why does AGENTS.md require Capstone and Keystone specifically?
Capstone provides architecture-aware disassembly that extracts instruction semantics (mnemonics and operands) rather than raw bytes, while Keystone ensures generated assembly is valid for the target ISA. Together, they create a tool-driven workflow that prevents manual byte manipulation errors and guarantees that patches respect ARM64 instruction semantics as required by the safety rules.
How does the patch_bsd_init_auth workflow demonstrate the guardrail pattern?
This specific workflow requires developers to follow a deterministic reveal procedure: recover bsd_init, locate the root-vp panic block, find the unique in-function call, identify the cbnz w0/x0, panic and bl imageboot_needed sequence, then patch only the branch gate. This enforces semantic navigation through control flow rather than arbitrary offsets, ensuring a deterministic and reproducible approach for this critical security patch.
What happens if a developer uses hardcoded offsets instead of semantic anchors?
Using hardcoded offsets violates the guardrail pattern defined in AGENTS.md and would result in patches that break when Apple updates the kernel or changes compiler optimizations. The pattern explicitly prohibits raw file offsets and virtual addresses to ensure longevity and maintainability of the patching infrastructure across firmware revisions.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →