# How to Patch iOS Boot Chain Components with FirmwarePatcher in vPhone-CLI

> Learn to patch iOS boot chain components like kernel and DSC with FirmwarePatcher in vPhone-CLI. Modify sysctl OIDs and C-strings to spoof real hardware detection.

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

---

**FirmwarePatcher in vPhone-CLI modifies kernel, dyld shared cache (DSC), and root-filesystem binaries to make a virtual iPhone report itself as real hardware by renaming sysctl OIDs and mangling hard-coded C-strings across the entire iOS boot chain.**

The **FirmwarePatcher** is a Python-based patching framework in the [Lakr233/vphone-cli](https://github.com/Lakr233/vphone-cli) repository that enables custom firmware (CFW) creation for virtualized iOS devices. It systematically transforms boot chain components to bypass hypervisor detection, allowing jailbreaks and hardware-like behavior in VM environments.

## Core Patching Strategy

The patcher targets **all layers of the iOS boot chain** with a unified byte-mangling approach:

1. **Kernel sysctl OID renaming** — `hv_vmm_present` becomes `Xv_vmm_present`
2. **Dyld shared cache (DSC) patching** — shared libraries get the same C-string transformation
3. **Root-filesystem binary mangling** — user-mode executables query the renamed OID
4. **Ancillary fixes** — watchdogd VM-checks, IOMFB swap-end handling, automatic re-signing

## FirmwarePatcher Architecture and Key Files

Understanding the source layout is essential for effective use:

| File | Purpose |
|------|---------|
| [`scripts/patchers/cfw.py`](https://github.com/Lakr233/vphone-cli/blob/main/scripts/patchers/cfw.py) | Central driver exposing all patch commands |
| [`scripts/patchers/cfw_patch_hv_vmm.py`](https://github.com/Lakr233/vphone-cli/blob/main/scripts/patchers/cfw_patch_hv_vmm.py) | Single Mach-O binary byte-mangler |
| [`scripts/patchers/cfw_patch_hv_vmm_dsc.py`](https://github.com/Lakr233/vphone-cli/blob/main/scripts/patchers/cfw_patch_hv_vmm_dsc.py) | DSC chunk walker and patcher |
| [`scripts/patchers/cfw_patch_hv_vmm_rootfs.py`](https://github.com/Lakr233/vphone-cli/blob/main/scripts/patchers/cfw_patch_hv_vmm_rootfs.py) | Root-fs orchestration and path management |
| [`scripts/patchers/cfw_macho_codesign.py`](https://github.com/Lakr233/vphone-cli/blob/main/scripts/patchers/cfw_macho_codesign.py) | Automatic Mach-O re-signing |
| [`scripts/patchers/cfw_patch_watchdogd.py`](https://github.com/Lakr233/vphone-cli/blob/main/scripts/patchers/cfw_patch_watchdogd.py) | Example daemon-specific patch |
| `Makefile` | Make targets (`fw_patch`, `fw_patch_jb`, etc.) |
| [`fw_prepare.sh`](https://github.com/Lakr233/vphone-cli/blob/main/fw_prepare.sh) | IPSW extraction and workspace setup |
| [`cfw_install.sh`](https://github.com/Lakr233/vphone-cli/blob/main/cfw_install.sh) | Final CFW installation to VM |

## Step-by-Step Firmware Patching Workflow

### 1. Install Dependencies

```bash
pip install -r requirements.txt

```

Required packages: `capstone`, `keystone-engine`, `pyimg4`.

### 2. Prepare the iOS Firmware

```bash
./fw_prepare.sh <IPSW_URL_OR_PATH>

```

This extracts the IPSW, merges the "cloudOS" rootfs, and creates a working directory structure.

### 3. Patch the Kernel and Root Filesystem

```bash
make fw_patch

```

Internally invokes [`./scripts/patchers/cfw_patch_hv_vmm_rootfs.py`](https://github.com/Lakr233/vphone-cli/blob/main/./scripts/patchers/cfw_patch_hv_vmm_rootfs.py) to:

- Rename the sysctl OID in kernel internals
- Mangle every `b"kern.hv_vmm_present\x00"` occurrence to `b"kern.Xv_vmm_present\x00"`

The function `cfw_patch_hv_vmm_rootfs.get_patch_paths()` locates binaries from `ALL_KNOWN_ROOTFS_PATHS` and applies `cfw_patch_hv_vmm.patch_hv_vmm` to each.

### 4. Patch the Dyld Shared Cache

```bash
python3 scripts/patchers/cfw.py patch-hv-vmm-dsc <chunks_dir> [--dry-run]

```

The `<chunks_dir>` is typically `/System/Library/Caches/com.apple.dyld` from the mounted SystemOS snapshot. The DSC patcher walks chunks, finds the needle C-string, applies byte 5 transformation (`h` → `X`), and re-attests modified pages.

### 5. Apply Daemon-Specific Patches

```bash
python3 scripts/patchers/cfw.py patch-watchdogd /usr/libexec/watchdogd

```

Additional commands target VM-related checks in specific daemons and frameworks like IOMFB.

### 6. Install the Patched CFW

```bash
./cfw_install.sh          # Standard variant

./cfw_install_jb.sh       # Jailbreak variant

```

## Code Examples

### Standalone Binary Patching

```python
from scripts.patchers.cfw_patch_hv_vmm import patch_hv_vmm

binary_path = "/usr/libexec/watchdogd"
patched_count = patch_hv_vmm(binary_path, dry_run=False)
print(f"Patched {patched_count} occurrence(s) in {binary_path}")

```

### Checking the Blacklist

Some binaries must remain unpatched to preserve functionality like device activation:

```python
from scripts.patchers.cfw_patch_hv_vmm_rootfs import DONT_PATCH_ROOTFS_PATHS

# Verify sign-in related daemons are protected

assert "/usr/libexec/mobileactivationd" in DONT_PATCH_ROOTFS_PATHS

```

### Direct DSC Patching (Advanced)

```bash
python3 scripts/patchers/cfw.py patch-hv-vmm-dsc \
    /path/to/dyld_shared_cache \
    --dry-run  # Preview changes without writing

```

## Idempotency and Safety Features

The FirmwarePatcher is **idempotent**: running commands multiple times skips already-patched binaries. The detection mechanism checks for the transformed needle `b"kern.Xv_vmm_present\x00"` before applying changes.

Automatic **code signature preservation** via [`cfw_macho_codesign.py`](https://github.com/Lakr233/vphone-cli/blob/main/cfw_macho_codesign.py) ensures patched binaries remain valid Mach-O files without manual intervention.

## Summary

- **FirmwarePatcher** transforms the entire iOS boot chain through unified C-string mangling (`hv_vmm_present` → `Xv_vmm_present`)
- Entry point is [`scripts/patchers/cfw.py`](https://github.com/Lakr233/vphone-cli/blob/main/scripts/patchers/cfw.py) with subcommands for kernel, DSC, rootfs, and daemon-specific patches
- Make targets (`make fw_patch`, `make fw_patch_jb`) automate the full workflow
- All patches are idempotent and automatically re-signed to maintain valid Mach-O structures
- Blacklists in [`cfw_patch_hv_vmm_rootfs.py`](https://github.com/Lakr233/vphone-cli/blob/main/cfw_patch_hv_vmm_rootfs.py) protect critical binaries like `mobileactivationd`

## Frequently Asked Questions

### What is the exact byte transformation applied by FirmwarePatcher?

The patcher changes byte 5 of the C-string from `h` to `X`: `"kern.hv_vmm_present\0"` becomes `"kern.Xv_vmm_present\0"`. This is applied consistently across kernel, DSC, and user-mode binaries so they all query the renamed sysctl OID.

### Can I patch only specific binaries instead of the entire firmware?

Yes. Use `cfw_patch_hv_vmm.patch_hv_vmm()` directly for single binaries, or modify `ALL_KNOWN_ROOTFS_PATHS` in [`cfw_patch_hv_vmm_rootfs.py`](https://github.com/Lakr233/vphone-cli/blob/main/cfw_patch_hv_vmm_rootfs.py) to limit the batch scope. The blacklist `DONT_PATCH_ROOTFS_PATHS` always takes precedence.

### How does FirmwarePatcher handle code signing?

[`cfw_macho_codesign.py`](https://github.com/Lakr233/vphone-cli/blob/main/cfw_macho_codesign.py) automatically re-signs any Mach-O file written back to disk. This happens transparently during `patch_hv_vmm()` operations—no manual `codesign` invocation is required.

### What is the difference between `make fw_patch` and `make fw_patch_jb`?

`fw_patch` creates a standard custom firmware for virtualization research. `fw_patch_jb` includes additional jailbreak-oriented patches and invokes [`cfw_install_jb.sh`](https://github.com/Lakr233/vphone-cli/blob/main/cfw_install_jb.sh) for installation. Both use the same core FirmwarePatcher infrastructure.