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 NOP or MOV_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 of bsd_init, locating the root-vp panic block, and identifying the unique in-function call before modification.
  • Standardized tooling: Patchers must use capstone for disassembly, keystone-engine for assembly, and pyimg4 for 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_venv and activated via source .venv/bin/activate to 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:

Summary

  • The kernel-patcher guardrail pattern in AGENTS.md mandates 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_auth workflow 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →