What Are the EXP-Only Research Patches Applied by KernelEXPPatcher?
The KernelEXPPatcher applies a single, specialized kernel modification—renaming the hv_vmm_present sysctl OID—that masks virtualization detection in the EXP (Experimental) variant of vPhone-CLI, allowing the system to present as bare-metal hardware while retaining VM acceleration capabilities.
The EXP-only research patches are exclusively documented in the research/0_binary_patch_comparison.md file within the Lakr233/vphone-cli repository. These modifications are orchestrated by KernelEXPPatcher, a Swift-based firmware patcher that executes after the generic KernelPatcher and before jailbreak-specific patches during the firmware installation pipeline.
Understanding the Experimental (EXP) Variant
The Experimental (EXP) build of vPhone-CLI introduces kernel-level modifications that are not applied when building the regular or standard jailbreak (JB) variants. According to the research documentation, KernelEXPPatcher inherits from KernelJBPatcherBase and activates only when the EXP flag is enabled during the build process. This isolation ensures that virtualization-masking behaviors do not interfere with standard jailbreak operations or stock firmware restoration.
The Core EXP-Only Kernel Patch: hv_vmm_present Rename
The only kernel-level method introduced by KernelEXPPatcher is the patch_hv_vmm_rename operation (designated as EXP-01, Group B). This patch consists of two complementary stages that modify the string "kern.hv_vmm_present" throughout the kernel and user-space boundaries.
Part A – Sysctl OID String Modification
KernelEXPPatcher locates the sysctl registration table within the kernel binary and modifies the OID string in-place. The patch overwrites the sixth character (byte 5) of the C-string, changing 'h' to 'X', transforming "kern.hv_vmm_present" into "kern.Xv_vmm_present".
// Conceptual implementation from KernelEXPPatchHvVmmRename.swift
func patchSysctlTable(in kernelData: inout Data) {
let targetString = "kern.hv_vmm_present"
let replacementIndex = 5 // Position of 'h'
if let range = kernelData.range(of: targetString.data(using: .utf8)!) {
kernelData[range.lowerBound + replacementIndex] = UInt8(ascii: "X")
}
}
After this modification, direct calls to sysctlbyname("kern.hv_vmm_present") return ENOENT (not found), while queries to "kern.Xv_vmm_present" return the actual virtualization state (typically 1).
Part B – In-Kernel Reference Mangling
To maintain internal consistency, KernelEXPPatcher applies the same byte-level transformation to every in-kernel occurrence of the original string literal. This ensures that internal components—AMFI, IO Crypto, Sandbox profile tokens, and APFS—continue to reference the renamed OID correctly without crashing.
// Kernel-level string literal patching
func mangleKernelStrings(in kernelData: inout Data) {
let original = "kern.hv_vmm_present".data(using: .utf8)!
var searchStart = kernelData.startIndex
while let range = kernelData[searchStart...].range(of: original) {
let absolutePos = range.lowerBound
kernelData[absolutePos + 5] = UInt8(ascii: "X")
searchStart = range.upperBound
}
}
DSC-Level Consistency
During post-restore firmware patching, the companion script cfw_patch_hv_vmm_dsc.py applies an equivalent mangling to every dylib within the dyld shared cache (DSC). This ensures that user-space daemons querying the sysctl see the same renamed OID.
# From scripts/patchers/cfw_patch_hv_vmm_dsc.py
def patch_dsc_sysctl(dsc_path, whitelist=None):
with open(dsc_path, 'r+b') as f:
content = bytearray(f.read())
original = b"kern.hv_vmm_present"
renamed = b"kern.Xv_vmm_present"
# Replace all occurrences except whitelisted binaries
content = content.replace(original, renamed)
f.seek(0)
f.write(content)
EXP-Only Firmware Modifications Dependent on the Kernel Patch
Several additional EXP-only modifications rely on the hv_vmm_present rename having been established by KernelEXPPatcher:
- watchdogd surgical patch (EXP-JB-3.5) – Re-attests the renamed OID through a two-instruction cache-slot rewrite
- DeviceTree post-restore identity rewrite (EXP-JB-6) – Adds new
/product/cameranodes and eight additional identity properties that reference the masked virtualization state - SystemVersion.plist ProductBuildVersion rewrite (EXP-JB-7) – Optionally changes the build identifier when
SPOOF_BUILDis set, contingent on the kernel's masked VM state
These modifications are coordinated by scripts/cfw_install_exp.sh, which invokes KernelEXPPatcher at the [EXP-JB-3.5] stage of the firmware installation pipeline.
# From scripts/cfw_install_exp.sh
# [EXP-JB-3.5] Apply kernel EXP patches
echo "[*] Applying KernelEXPPatcher..."
KernelEXPPatcher "${EXP_KERNEL_CACHE}" "${Patched_KERNEL}"
Source Code Structure and Implementation
The EXP-only patches are implemented across three critical files in the vPhone-CLI source tree:
sources/FirmwarePatcher/Kernel/KernelEXPPatcher.swift– Orchestrates the patch sequence and inherits fromKernelJBPatcherBasesources/FirmwarePatcher/Kernel/EXPPatches/KernelEXPPatchHvVmmRename.swift– Contains thepatch_hv_vmm_renamemethod implementing Parts A and Bresearch/0_binary_patch_comparison.md– Documents the complete EXP-01 patch specification and binary diff analysis
Summary
- KernelEXPPatcher applies exactly one kernel-level EXP-only patch: the
hv_vmm_presentsysctl OID rename. - The patch modifies byte 5 of the target string in both the sysctl table and all in-kernel references, changing
"kern.hv_vmm_present"to"kern.Xv_vmm_present". - User-space consistency is maintained by
cfw_patch_hv_vmm_dsc.py, which patches the dyld shared cache equivalently. - Additional EXP modifications (watchdogd, DeviceTree, SystemVersion) depend on this kernel patch but are applied separately during the
[EXP-JB-3.5]through[EXP-JB-7]stages. - These patches are exclusive to the Experimental variant and are not present in standard or JB builds.
Frequently Asked Questions
What is the difference between KernelEXPPatcher and the standard KernelPatcher?
KernelEXPPatcher runs exclusively during Experimental (EXP) builds and inherits from KernelJBPatcherBase, whereas the standard KernelPatcher handles generic kernel modifications for all variants. According to the source in sources/FirmwarePatcher/Kernel/KernelEXPPatcher.swift, the EXP patcher executes after the generic patcher and specializes in virtualization-masking behaviors that are too aggressive for standard jailbreak operations.
Why does the EXP variant rename hv_vmm_present instead of simply returning 0?
Renaming the OID entirely (from "kern.hv_vmm_present" to "kern.Xv_vmm_present") causes queries for the original name to return ENOENT, effectively hiding the VM's existence from detection tools. Simply returning 0 would still expose the sysctl's presence to sophisticated checks. This string-level rename ensures that legacy code paths expecting the non-existent OID behave as if running on bare-metal hardware, while the hypervisor can still query the renamed OID to confirm acceleration capabilities are active.
Which system components are affected by the in-kernel string mangling?
The Part B mangling affects every kernel extension and subsystem that hardcodes the "kern.hv_vmm_present" string literal. The research documentation identifies AMFI (Apple Mobile File Integrity), IO Crypto, Sandbox profile token validation, and APFS as critical components that continue functioning because their internal references are updated to point to "kern.Xv_vmm_present" instead of querying a non-existent sysctl.
Are the EXP-only patches included in the regular jailbreak build?
No. The EXP-only research patches are conditionally compiled and executed only when building the Experimental variant. The scripts/cfw_install_exp.sh script explicitly calls KernelEXPPatcher during the [EXP-JB-3.5] stage, while the standard jailbreak installation script (cfw_install_jb.sh) omits this call entirely, preserving the stock hv_vmm_present behavior for compatibility with standard iOS security policies.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →