# How to Perform Firmware Patching with vphone‑cli: A Complete Guide to the Swift Patching Pipeline

> Master iOS firmware patching with vphone-cli. This guide details the Swift patching pipeline, modifying the boot chain using semantic analysis for efficient updates.

- Repository: [Lakr/vphone-cli](https://github.com/Lakr233/vphone-cli)
- Tags: how-to-guide
- Published: 2026-09-06

---

**vphone‑cli performs firmware patching through a pure‑Swift pipeline that modifies the iOS boot chain (iBSS → iBEC → LLB → kernel → kernel extensions) on the host machine using semantic analysis of ARM64 instructions rather than hard‑coded offsets.**

The patching system is orchestrated by a central `FirmwarePipeline` class that coordinates component‑specific patchers implementing the `Patcher` protocol. Users invoke this pipeline through the `patch‑firmware` command or Makefile shortcuts, with each **variant** (`regular`, `less`, `dev`, `jb`, `exp`) controlling which modifications are applied to the firmware components in a VM's `Restore` directory.

---

## Architecture Overview

### The Firmware Pipeline

At the heart of vphone‑cli's patching system is [`FirmwarePipeline.swift`](https://github.com/Lakr233/vphone-cli/blob/main/FirmwarePipeline.swift), which implements the end‑to‑end workflow:

- Loads firmware components from the VM directory (TXM files, kernel cache, device tree, AVP‑Booter, etc.)
- Instantiates the appropriate patcher for each component based on the selected variant
- Executes `patchAll()` to apply discovered modifications and write patched binaries back to disk

The pipeline is **variant‑aware**: it conditionally includes jailbreak hooks, development TXM patches, or experimental features depending on user input.

### The Patcher Protocol

All component patchers conform to `PatcherProtocol` defined in [`sources/FirmwarePatcher/Core/PatcherProtocol.swift`](https://github.com/Lakr233/vphone-cli/blob/main/sources/FirmwarePatcher/Core/PatcherProtocol.swift). The protocol requires:

```swift
protocol Patcher {
    func findAll() -> [PatchRecord]
    func apply()
    func log(_ message: String)
}

```

This abstraction allows each firmware component to implement custom discovery logic while sharing common infrastructure for instruction analysis and patch recording.

---

## Key Components and Their Roles

### TXM Patching (iBoot Chain)

**File:** [`sources/FirmwarePatcher/TXM/TXMPatcher.swift`](https://github.com/Lakr233/vphone-cli/blob/main/sources/FirmwarePatcher/TXM/TXMPatcher.swift)

The TXM patcher handles iBSS, iBEC, LLB, and related boot components. It locates critical boot routines using string references and control‑flow analysis, then applies patches to bypass signature checks or enable debug features.

### Kernel Patching Infrastructure

**Base File:** [`sources/FirmwarePatcher/Kernel/KernelPatcherBase.swift`](https://github.com/Lakr233/vphone-cli/blob/main/sources/FirmwarePatcher/Kernel/KernelPatcherBase.swift)

[`KernelPatcherBase.swift`](https://github.com/Lakr233/vphone-cli/blob/main/KernelPatcherBase.swift) provides the shared machinery for all kernel patchers:

- **Mach‑O parsing**: Locates `__TEXT` and `__DATA` segments, section headers, and symbol tables
- **ADRP/BL indexing**: Builds an index of ADRP‑ADD and BL instruction pairs for rapid target lookup
- **String reference search**: Finds Mach‑O string entries and resolves their virtual addresses
- **Patch emission**: The `emit(...)` routine creates `PatchRecord` structs with original bytes, replacement bytes, and metadata

This infrastructure enables **semantic patching**—discovering patch locations by analyzing instruction patterns rather than relying on version‑specific offsets.

### Core Kernel Patcher

**File:** [`sources/FirmwarePatcher/Kernel/KernelPatcher.swift`](https://github.com/Lakr233/vphone-cli/blob/main/sources/FirmwarePatcher/Kernel/KernelPatcher.swift)

[`KernelPatcher.swift`](https://github.com/Lakr233/vphone-cli/blob/main/KernelPatcher.swift) inherits from [`KernelPatcherBase.swift`](https://github.com/Lakr233/vphone-cli/blob/main/KernelPatcherBase.swift) and applies the foundational kernel patches:

- Panic function redirection
- Kext text range identification
- Virtual‑to‑file offset conversion

### Jailbreak and Experimental Variants

| Patcher | File | Purpose |
|---------|------|---------|
| `KernelJBPatcher` | [`sources/FirmwarePatcher/Kernel/KernelJBPatcher.swift`](https://github.com/Lakr233/vphone-cli/blob/main/sources/FirmwarePatcher/Kernel/KernelJBPatcher.swift) | Applies jailbreak‑specific hooks for code injection and sandbox relaxation |
| `KernelEXPPatcher` | [`sources/FirmwarePatcher/Kernel/KernelEXPPatcher.swift`](https://github.com/Lakr233/vphone-cli/blob/main/sources/FirmwarePatcher/Kernel/KernelEXPPatcher.swift) | Experimental patches including `hv_vmm` rename and DSC byte‑5 mangling |

Each inherits the base infrastructure and adds variant‑specific discovery logic.

---

## Invoking the Pipeline

### Command‑Line Interface

The `patch‑firmware` subcommand is implemented in `PatchFirmwareCLI` within [`sources/vphone-cli/VPhoneCLI.swift`](https://github.com/Lakr233/vphone-cli/blob/main/sources/vphone-cli/VPhoneCLI.swift) (lines 25–107). Available options:

| Flag | Description |
|------|-------------|
| `--vm-directory PATH` | Path to VM containing `Restore/` firmware files |
| `--variant {regular,less,dev,jb,exp}` | Patching variant to apply |
| `--records-out PATH` | Write JSON patch log for debugging |
| `--force-exc-guard` | Apply EXC_GUARD workaround patches |
| `--frida` | Enable Frida Stalker compatibility patches |

### Basic Usage

```bash

# Patch with regular variant (most common)

vphone-cli patch-firmware \
    --vm-directory ./vm \
    --variant regular

# Patch with jailbreak variant and output records

vphone-cli patch-firmware \
    --vm-directory ./vm \
    --variant jb \
    --records-out ./patch-records.json \
    --force-exc-guard

```

### Variant Selection Guide

- **`regular`**: Standard patches for production use
- **`less`**: Minimal patches for "patch‑less‑compatible" boot scenarios
- **`dev`**: Adds development TXM patches for debugging
- **`jb`**: Full jailbreak support with kernel hooks
- **`exp`**: Experimental features (requires understanding of implementation)

---

## Makefile Integration

The repository provides convenient Make targets in the root `Makefile` (lines 353–358 and related). These build the patcher binary and invoke it with proper flags:

```makefile

# Build the patcher binary

make patcher_build

# Patch with regular variant (equivalent CLI shown in comments)

make fw_patch

# $(PATCHER_BINARY) patch-firmware --vm-directory "$(VM_DIR_ABS)" --variant regular

# Jailbreak variant with optional flags

make fw_patch_jb FRIDA=1 FORCE_EXC_GUARD=1

# Minimal patches (requires sudo for VM manipulation)

make fw_patch_less

```

The Makefile handles path conversion, conditional flag injection, and dependency checking automatically.

---

## How Semantic Patching Works

Unlike traditional firmware tools that use hard‑coded file offsets, vphone‑cli's patchers **discover locations at runtime**:

1. **Disassembly**: [`ARM64Disassembler.swift`](https://github.com/Lakr233/vphone-cli/blob/main/ARM64Disassembler.swift) provides ARM64 instruction decoding
2. **Pattern matching**: ADRP + ADD sequences are matched to find pointer construction
3. **BL target resolution**: Branch-and-link instructions are indexed and resolved
4. **String table scanning**: Critical strings (e.g., `"AppleSEPManager"`, `"cryptex"`) are located and their references traced

This approach makes the pipeline resilient across iOS versions—as long as the semantic patterns remain stable, the same patcher works on new firmware without modification.

---

## Output and Debugging

### Patch Records

When `--records-out` is specified, the pipeline writes a JSON array of `PatchRecord` structs (defined in [`sources/FirmwarePatcher/Core/PatchRecord.swift`](https://github.com/Lakr233/vphone-cli/blob/main/sources/FirmwarePatcher/Core/PatchRecord.swift)):

```json
[
  {
    "component": "kernel",
    "patcher": "KernelJBPatcher",
    "virtualAddress": "0xfffffff0070080a0",
    "fileOffset": 123456,
    "originalBytes": "1f2003d5",
    "patchedBytes": "000080d2",
    "description": "Disable AMFI: ret0 patch"
  }
]

```

This enables auditing, regression testing, and forensic analysis of applied modifications.

### Logging

All patchers use the shared `log(_:)` helper to emit progress information. Set the environment variable `VPHONE_LOG=debug` for verbose output during patching operations.

---

## Summary

- **vphone‑cli** implements firmware patching through a Swift‑based pipeline centered on [`FirmwarePipeline.swift`](https://github.com/Lakr233/vphone-cli/blob/main/FirmwarePipeline.swift)
- **Five variants** (`regular`, `less`, `dev`, `jb`, `exp`) control which patches are applied
- **Semantic discovery** via [`ARM64Disassembler.swift`](https://github.com/Lakr233/vphone-cli/blob/main/ARM64Disassembler.swift) and [`KernelPatcherBase.swift`](https://github.com/Lakr233/vphone-cli/blob/main/KernelPatcherBase.swift) provides version resilience
- **Component patchers** for TXM, kernel base, jailbreak hooks, and experimental features each specialize the shared infrastructure
- **CLI and Makefile** interfaces provide flexible invocation for manual use and automation

---

## Frequently Asked Questions

### What iOS versions does vphone‑cli's firmware patching support?

The semantic patching approach targets ARM64 instruction patterns rather than version‑specific offsets. As implemented in [`KernelPatcherBase.swift`](https://github.com/Lakr233/vphone-cli/blob/main/KernelPatcherBase.swift), the pipeline analyzes ADRP/BL sequences and string references that remain stable across iOS releases. Specific version support depends on when Apple changes the underlying code structure being patched.

### Can I apply multiple variants in a single patch operation?

No—each patch operation selects exactly one variant. The `FirmwarePipeline` instantiation in [`VPhoneCLI.swift`](https://github.com/Lakr233/vphone-cli/blob/main/VPhoneCLI.swift) maps the `--variant` parameter to a single `FirmwarePipeline.Variant` case. To combine effects (e.g., `jb` with experimental features), you must run sequential patch operations or use a variant that encapsulates the desired combination.

### Why does `make fw_patch_less` require sudo while other targets do not?

The `less` variant manipulates VM state in ways that require elevated privileges for certain filesystem or virtualization operations. The Makefile explicitly checks for sudo availability before executing `fw_patch_less`, whereas standard variants operate entirely on firmware files within the VM directory without system‑level modifications.