Where to Find the vphone-cli Source Code for Firmware Patching

All firmware-patching logic in vphone-cli resides in the sources/FirmwarePatcher directory, organized around the Patcher protocol and orchestrated by the FirmwarePipeline class.

The vphone-cli repository by Lakr233 provides a Swift-based toolkit for virtualizing iOS devices. If you are looking to understand or modify how the tool patches firmware images, you will find the complete implementation under the dedicated sources/FirmwarePatcher path. This modular architecture handles everything from IM4P container parsing to ARM64 instruction-level modifications across the boot chain.

Core Architecture of the Firmware Patching System

The patching system is built on a protocol-oriented design that separates discovery, orchestration, and component-specific logic.

The Patcher Protocol

At the heart of the system lies the Patcher protocol defined in sources/FirmwarePatcher/Core/PatcherProtocol.swift. This protocol establishes the common API that every component patcher must implement:

  • findAll() → Discovers patchable locations within the binary
  • apply() → Writes modifications to the buffer
  • log() → Provides verbose output during operations

Each concrete implementation works with a BinaryBuffer instance and produces PatchRecord objects—defined in sources/FirmwarePatcher/Core/PatchRecord.swift—that capture metadata such as file offsets, original bytes, and disassembly context.

FirmwarePipeline Orchestrator

The FirmwarePipeline class in sources/FirmwarePatcher/Pipeline/FirmwarePipeline.swift serves as the high-level entry point. It manages the complete lifecycle of firmware modification:

  1. Discovery: Locates the Restore directory within the VM bundle
  2. Version Detection: Determines the base iOS version to enable conditional patches
  3. Component Loading: Uses ContainerFirmwareLoader to handle IM4P containers transparently
  4. Variant Selection: Builds a component list based on the selected variant (regular, dev, jb, exp, or less)
  5. Execution: Sequentially calls findAll() and apply() on each patcher
  6. Persistence: Writes patched payloads back to disk

Component-Specific Patcher Implementations

Individual patchers reside in subdirectories organized by firmware component. Each implements the Patcher protocol and contains ARM64 disassembly logic using the Capstone and Keystone libraries.

Boot Chain and TXM Patchers

The boot chain components—including AVPBooter, iBSS, iBEC, LLB, and TXM—are handled by dedicated patchers:

Kernel and DeviceTree Patchers

For higher-level firmware components:

Low-Level Binary Handling

The patching infrastructure relies on robust binary utilities for manipulation of raw firmware data.

IM4P Container Management

The IM4PHandler.swift file (sources/FirmwarePatcher/Binary/IM4PHandler.swift) provides transparent handling of IM4P containers. The ContainerFirmwareLoader class abstracts the extraction and repacking of payload data, allowing patchers to work with raw bytes without managing container headers manually.

BinaryBuffer Utilities

BinaryBuffer.swift (sources/FirmwarePatcher/Binary/BinaryBuffer.swift) offers low-level utilities for reading and writing bytes, searching for instruction patterns, and managing memory-mapped firmware images. All patchers interact with firmware data through this abstraction layer.

Using the Firmware Patching API

You can interact with the patching system either through the high-level pipeline or by instantiating individual patchers.

Running the Complete Pipeline

To execute all patches for a specific variant:

import Foundation
import VPhoneCore

let vmDir = URL(fileURLWithPath: "/path/to/vphone/vm")
let pipeline = FirmwarePipeline(
    vmDirectory: vmDir,
    variant: .jb,
    verbose: true,
    noBinpack: false,
    noVphoned: false,
    forceExcGuard: false,
    enableFrida: false
)

do {
    let patchRecords = try pipeline.patchAll()
    print("✅ Finished – applied \(patchRecords.count) patches")
} catch {
    print("❌ Patching failed: \(error)")
}

Applying Individual Patches

For targeted modifications to a specific component:

import Foundation

let txmURL = URL(fileURLWithPath: "/path/to/txm.im4p")
let loader = FirmwarePipeline.ContainerFirmwareLoader()
let rawData = try loader.load(from: txmURL)

let txmPatcher = TXMPatcher(data: rawData, verbose: true)
let records = try txmPatcher.findAll()
print("Found \(records.count) TXM patches")
try txmPatcher.apply()
try loader.save(txmPatcher.patchedData, to: txmURL)

Creating Custom Patchers

To implement a new patching component, conform to the Patcher protocol:

final class MyCustomPatcher: Patcher {
    let component = "mycomponent"
    let verbose: Bool
    private var buffer: BinaryBuffer
    private var patches: [PatchRecord] = []

    init(data: Data, verbose: Bool = true) {
        self.buffer = BinaryBuffer(data)
        self.verbose = verbose
    }

    func findAll() throws -> [PatchRecord] {
        // Locate target instructions and populate patches array
        return patches
    }

    func apply() throws -> Int {
        for record in patches {
            buffer.writeBytes(at: record.fileOffset, bytes: record.patchedBytes)
        }
        return patches.count
    }
}

Summary

  • The vphone-cli firmware patching source code is located entirely within the sources/FirmwarePatcher directory of the Lakr233/vphone-cli repository.
  • The architecture centers on the Patcher protocol (PatcherProtocol.swift), which defines the findAll() and apply() methods used by all components.
  • FirmwarePipeline.swift orchestrates the complete workflow, from discovering the Restore directory to writing patched binaries.
  • Component-specific logic is split across dedicated files like TXMPatcher.swift, KernelPatcher.swift, and DeviceTreePatcher.swift.
  • Low-level binary operations rely on BinaryBuffer.swift for byte manipulation and IM4PHandler.swift for container management.
  • All patchers record their changes using PatchRecord objects, enabling full audit trails of modifications.

Frequently Asked Questions

Where is the entry point for firmware patching in vphone-cli?

The entry point is the FirmwarePipeline class in sources/FirmwarePatcher/Pipeline/FirmwarePipeline.swift. This class provides the patchAll() method, which executes the complete patching workflow across all firmware components based on the selected variant (regular, dev, jb, or exp).

How does vphone-cli handle different patching variants like jailbreak or developer mode?

The pipeline builds a component list using factory closures that instantiate different patcher combinations based on the variant parameter passed during initialization. For example, the .jb variant includes TXMDevPatcher and KernelJBPatcher, while the .regular variant uses only base patchers like TXMPatcher and KernelPatcher.

What libraries does vphone-cli use for ARM64 disassembly and assembly?

According to the source code, vphone-cli utilizes the Capstone disassembly framework and the Keystone assembly engine. These libraries enable the patchers to locate specific instruction sequences in the firmware and generate replacement bytecode for patches.

Can I use vphone-cli patching logic outside of the full virtualization context?

Yes. While FirmwarePipeline provides the integrated workflow, you can import the VPhoneCore module and instantiate individual patchers directly. Pass raw firmware data to constructors like TXMPatcher(data:verbose:) or KernelPatcher(data:variant:verbose:), then call findAll() and apply() independently of the pipeline orchestrator.

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 →