# AMFI Bypass Mechanism in vphone-cli: How Unsigned Code Runs in Virtual iOS

> Discover how vphone-cli bypasses Apple's AMFI to run unsigned code on virtual iOS. Learn about kernel gate patching for unauthorized binary execution.

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

---

**vphone-cli neutralizes Apple Mobile File Integrity (AMFI) by patching four distinct kernel gates—launch constraints, trust-cache validation, execve kill paths, and post-validation compares—to allow unsigned binaries to execute inside the virtual iPhone.**

The vphone-cli project runs a virtual iPhone inside macOS using Apple’s Virtualization.framework, requiring the neutralization of AMFI code-signing enforcement so that custom firmware (CFW) and unsigned IPAs can boot and execute. This AMFI bypass mechanism is implemented entirely within the kernel-patching layer located in `sources/FirmwarePatcher/Kernel`, using semantic pattern matching to locate and rewrite critical ARM64 instructions in the iOS kernel image.


## How AMFI Blocks Unsigned Code in iOS

**Apple Mobile File Integrity (AMFI)** is the kernel subsystem responsible for enforcing code-signing policies, launch constraints, and trust-cache validation on iOS. When a process attempts to execute, AMFI verifies that its CDHash exists in the system trust cache and that the binary satisfies the current launch-constraint policy. If any check fails, the kernel immediately terminates the process or rejects the execution attempt, preventing unsigned or modified binaries from running.


## The Four AMFI Gates Patched by vphone-cli

The vphone-cli AMFI bypass targets four specific enforcement points in the kernel. Each patch replaces the original logic with a stub that forces success, effectively disabling the security check for the virtual machine environment.


### Launch-Constraint Gate (`_proc_check_launch_constraints`)

The original `_proc_check_launch_constraints` function returns a non-zero error when the kernel’s launch-constraint policy rejects a process. According to the source code in [`sources/FirmwarePatcher/Kernel/Patches/KernelPatchLaunchConstraints.swift`](https://github.com/Lakr233/vphone-cli/blob/main/sources/FirmwarePatcher/Kernel/Patches/KernelPatchLaunchConstraints.swift), the patch rewrites the function entry point to `mov w0,#0; ret`, forcing the function to return success (zero) regardless of the actual policy evaluation. This allows processes that violate launch constraints—such as those with modified entitlements—to start normally.


### Trust-Cache Gate (`AMFIIsCDHashInTrustCache`)

This gate checks whether a binary’s CDHash is present in the AMFI trust cache, returning `0` (reject) for unknown hashes. In [`sources/FirmwarePatcher/Kernel/JBPatches/KernelJBPatchAmfiTrustcache.swift`](https://github.com/Lakr233/vphone-cli/blob/main/sources/FirmwarePatcher/Kernel/JBPatches/KernelJBPatchAmfiTrustcache.swift), the patcher locates the unique AMFI function body using a semantic instruction pattern rather than hard-coded offsets. It then overwrites the first four instructions with a stub that stores `1` (true) and returns immediately, causing the kernel to treat all hashes as trusted.


### Execve Kill Path (Disabled)

The AMFI subsystem hooks `execve` and uses a `MOV W0,#1` instruction to signal a kill (reject) for binaries that fail policy checks. While [`sources/FirmwarePatcher/Kernel/JBPatches/KernelJBPatchAmfiExecve.swift`](https://github.com/Lakr233/vphone-cli/blob/main/sources/FirmwarePatcher/Kernel/JBPatches/KernelJBPatchAmfiExecve.swift) contains a patch to replace this with `MOV W0,#0` (turning the kill into an allow), this specific bypass is currently **disabled** in the codebase.


### Post-Validation Compare Gate

After AMFI’s SHA-256 validation, a `cmp w0,#imm; b.ne` instruction sequence can still reject binaries that pass the hash check but fail other policy validations. The patch in [`sources/FirmwarePatcher/Kernel/Patches/KernelPatchPostValidation.swift`](https://github.com/Lakr233/vphone-cli/blob/main/sources/FirmwarePatcher/Kernel/Patches/KernelPatchPostValidation.swift) replaces the compare with `cmp w0,w0`, which is always equal and therefore neutralizes the conditional branch that would otherwise terminate the process.


## Kernel Patching Implementation

All AMFI patches are applied through the **KernelJBPatcher** (jailbreak variant) or **KernelPatcher** (regular variant) classes during the custom firmware generation process. The patching workflow implemented in the CFW builder scripts (`scripts/patchers/cfw_*.py`) follows this sequence:

1. Load the decrypted kernel image into a mutable buffer.
2. Use **semantic function matching**—searching for characteristic ARM64 instruction sequences rather than static memory addresses—to locate the exact AMFI routines.
3. Emit new instruction encodings (`mov x0,#1`, `cbz x2,+8`, `str x0,[x2]`, `ret`, etc.) at the identified offsets.
4. Write the patched binary back to disk for the VM to boot.

This pattern-based approach ensures the patches remain functional across different iOS versions and firmware builds without requiring version-specific offset tables.


## Swift Code Example: Applying the AMFI Trust-Cache Patch

The following Swift snippet demonstrates how the vphone-cli patcher programmatically applies the trust-cache bypass:

```swift
import Foundation

// Assume `kernelBuffer` is a pre-loaded binary image and `patcher` is a KernelJBPatcher.
let patcher = KernelJBPatcher(buffer: kernelBuffer)

// Apply the AMFI trust-cache bypass (returns true on success).
if patcher.patchAmfiCdhashInTrustcache() {
    print("[+] AMFI trust-cache gate successfully bypassed")
} else {
    print("[-] Failed to locate or patch AMFI trust-cache function")
}

// Similarly, the launch-constraint stub can be applied:
if patcher.patchLaunchConstraints() {
    print("[+] Launch-constraint gate stubbed")
}

```

These methods are invoked internally by Python-based CFW builder scripts such as [`cfw_patch_xpc_lwcr.py`](https://github.com/Lakr233/vphone-cli/blob/main/cfw_patch_xpc_lwcr.py) when the jailbreak variant is selected during firmware generation.


## Prerequisites and Security Implications

The AMFI bypass mechanism requires **System Integrity Protection (SIP) and AMFI disabled** on the host macOS, as documented in [`sources/vphone-cli/VPhoneError.swift`](https://github.com/Lakr233/vphone-cli/blob/main/sources/vphone-cli/VPhoneError.swift) and enforced by the preflight script [`scripts/boot_host_preflight.sh`](https://github.com/Lakr233/vphone-cli/blob/main/scripts/boot_host_preflight.sh). The VM runs with private entitlements; without neutralizing these kernel gates, the iOS virtual machine would instantly reject any unsigned or re-signed code, preventing IPA installation, dynamic library loading, and developer-mode debugging features. This bypass is strictly limited to the virtualized environment and does not persist on physical devices.


## Summary

- **Four AMFI gates are patched**: launch constraints (`_proc_check_launch_constraints`), trust-cache validation (`AMFIIsCDHashInTrustCache`), execve kill paths, and post-validation compares.
- **Semantic pattern matching** locates functions by instruction sequences rather than static offsets, ensuring compatibility across iOS versions.
- **KernelJBPatcher** and **KernelPatcher** classes in `sources/FirmwarePatcher/Kernel/` implement the ARM64 instruction rewriting in Swift.
- **Host prerequisites** require SIP and AMFI disabled on macOS for the virtual iPhone to boot the patched custom firmware.
- **Unsigned code execution** becomes possible inside the VM, enabling IPA sideloading and dynamic library injection that standard iOS security policies would otherwise block.


## Frequently Asked Questions


### What is AMFI and why does vphone-cli need to bypass it?

**Apple Mobile File Integrity (AMFI)** is the iOS kernel subsystem that enforces code-signing and trust-cache validation. vphone-cli must bypass AMFI because the virtual iPhone runs custom firmware and unsigned IPAs that lack valid Apple signatures; without neutralizing these checks, the kernel would terminate any non-system binary immediately upon execution.


### Is the AMFI bypass in vphone-cli persistent across iOS updates?

Yes, because the patches rely on **semantic function matching** (identifying unique instruction patterns) rather than hard-coded memory offsets. As implemented in [`KernelJBPatchAmfiTrustcache.swift`](https://github.com/Lakr233/vphone-cli/blob/main/KernelJBPatchAmfiTrustcache.swift) and related files, the patcher searches for characteristic ARM64 sequences to locate AMFI routines dynamically, allowing the mechanism to adapt to new kernel builds without manual offset updates.


### Does the AMFI bypass require disabling SIP on the host Mac?

Yes. According to [`sources/vphone-cli/VPhoneError.swift`](https://github.com/Lakr233/vphone-cli/blob/main/sources/vphone-cli/VPhoneError.swift) and the startup routine in [`scripts/boot_host_preflight.sh`](https://github.com/Lakr233/vphone-cli/blob/main/scripts/boot_host_preflight.sh), both **System Integrity Protection (SIP)** and **AMFI** must be disabled on the host macOS for the virtual iPhone to boot and execute unsigned code. This is a strict prerequisite for the kernel-patching strategy to function safely within the virtualized environment.


### Can the AMFI bypass be used on physical iOS devices?

No. The bypass mechanism in vphone-cli is designed specifically for the virtualized environment created by Apple’s Virtualization.framework on macOS. The patches target kernel images loaded into memory buffers for VM booting and are not applicable to physical device boot chains, which use entirely different secure boot and hardware-backed signature verification mechanisms.