How VMAware Detects ARM-Based Virtual Machines: Techniques and Implementation

VMAware detects ARM-based virtual machines by combining Windows translator detection for Rosetta 2, CPUID hypervisor leaf inspection for Apple Silicon, and brand-string matching for hypervisors like UTM and BareVisor.

VMAware is an open-source C++ library designed to identify virtualized environments across multiple processor architectures. Understanding how to detect ARM-based virtual machines is essential for security research, malware analysis, and system administration on Apple Silicon and ARM64 platforms. The library implements several architecture-specific techniques in src/vmaware.hpp that target the unique characteristics of ARM virtualization.

Detecting ARM Translation Layers (Rosetta 2)

ARM-based VMs often run x86 code through translation layers, particularly on Apple Silicon. VMAware provides specific mechanisms to identify when a process is executing under such translation.

Windows Translator Detection via IsWow64Process2

On Windows ARM64 systems, VMAware detects Rosetta 2-style translation by querying the operating system for process architecture mismatches. In vmaware.hpp at lines 3699–3775, the VM::is_running_under_translator() function calls IsWow64Process2 (with a fallback to GetProcessInformation) to compare the process machine type against the native host architecture.

If the function detects that a 64-bit x86 process (IMAGE_FILE_MACHINE_AMD64 or IMAGE_FILE_MACHINE_I386) is executing on an ARM64 host (IMAGE_FILE_MACHINE_ARM64), it returns true. This indicates the process is running under the Windows translation layer, analogous to Rosetta 2 on macOS.

// Detect if we are running under Rosetta 2 (ARM64 host, x86 process)
bool underRosetta = VM::is_running_under_translator();   // true on an x86 binary executed on Apple Silicon

CPUID-Based Detection for Apple Silicon

ARM processors that support virtualization extensions expose hypervisor information through CPUID leaves. VMAware inspects these leaves to identify specific ARM hypervisors.

Apple Virtualization Framework (Apple VZ) Detection

VMAware identifies Apple's native virtualization framework by querying the CPUID hypervisor leaf. In vmaware.hpp around lines 3699–3735, the cpu::cpu_manufacturer function checks for vendor strings including "VirtualApple" or "apple virtualization". When found, the library invokes core::add(brand_enum::APPLE_VZ) to register the detection.

The brand mapping table at line 6260 in vmaware.hpp explicitly maps the string "apple virtualization" to the APPLE_VZ brand enum, ensuring consistent identification across detection methods.

VM-ID Leaf Inspection

For ARM CPUs exposing the hypervisor CPUID leaf (0x40000000–0x40000100), VMAware employs cpu::vmid_template() to read the vendor signature. At lines 4770–4785 in vmaware.hpp, the vmid() function iterates through these leaves and compares returned strings against an internal map containing ARM-specific identifiers like "apple virtualization".

This technique catches hypervisors that expose standardized CPUID signatures on ARM64, including experimental and custom virtualization solutions.

Brand String Matching for ARM Hypervisors

Beyond CPUID inspection, VMAware performs string analysis on CPU brand identifiers to catch ARM-specific virtualization platforms.

The generic cpu_brand() routine, implemented at lines 4945–5025 in vmaware.hpp, scans processor brand strings for identifiers including "qemu", "kvm", "vbox", "bhyve", "parallels", "vmware", and "apple virtualization". This approach enables detection of ARM hypervisors that populate the CPU brand string with their identifiers, even when standard CPUID leaves provide ambiguous results.

UTM and BareVisor Detection

VMAware specifically targets two ARM-focused hypervisors through brand aggregation:

  • UTM: Detected by recognizing the Apple VZ hypervisor foundation (via CPUID) and confirming native ARM64 execution. The cli.cpp file at line 653 documents UTM as a supported brand that leverages the Apple Hypervisor framework on Apple Silicon.

  • BareVisor: This lightweight hypervisor supports both x86 and ARM architectures. VMAware matches its vendor string "Barevisor!" through the generic vmid_template() function, registering the BAREVISOR brand as documented in cli.cpp at line 640.

The Detection Aggregation Pipeline

VMAware combines ARM-specific checks with generic detection through a unified scoring system. When VM::detect() is invoked, the library executes the following pipeline:

  1. Argument parsing builds a bit-set of enabled techniques based on configuration flags.
  2. Technique execution runs each selected detection method, including ARM-specific translator checks and CPUID inspections.
  3. Brand scoring allows techniques to call core::add(brand_enum) directly, incrementing scores for matching hypervisors like APPLE_VZ, UTM, or BAREVISOR.
  4. Result determination selects the brand with the highest score via VM::brand().
  5. Memoization caches detection results to avoid re-running expensive ARM-specific checks on subsequent calls.

This architecture treats ARM hypervisor strings identically to x86 ones, enabling seamless cross-platform detection.

// Detect any ARM-based VM (Apple VZ, UTM, BareVisor, etc.)
bool isArmVm = VM::detect();   // runs all enabled techniques; returns true if any ARM VM is found

// Retrieve the detected brand name (e.g. "Apple VZ")
std::string brand = VM::brand();   // "Apple VZ", "UTM", "Barevisor", …

Summary

  • VMAware detects ARM-based virtual machines through Windows translator detection (IsWow64Process2), CPUID hypervisor leaf inspection (0x40000000–0x40000100), and brand-string matching.
  • Rosetta 2 detection identifies x86 processes running on ARM64 hosts by comparing nativeMachine against IMAGE_FILE_MACHINE_ARM64 in vmaware.hpp lines 3699–3775.
  • Apple Silicon support recognizes "VirtualApple" and "apple virtualization" vendor strings via cpu::vmid_template() and cpu_brand() functions.
  • ARM hypervisor coverage includes UTM (using Apple VZ framework), BareVisor, and standard hypervisors like QEMU and KVM through unified brand scoring in core::add().
  • Cross-platform consistency allows ARM detection techniques to integrate seamlessly with existing x86 VM detection logic.

Frequently Asked Questions

How does VMAware detect Rosetta 2 translation on Windows ARM devices?

VMAware detects Rosetta 2-style translation by calling IsWow64Process2 (or GetProcessInformation as a fallback) to check if the current process architecture differs from the native host architecture. If the system reports IMAGE_FILE_MACHINE_ARM64 as the native machine while the process runs as AMD64 or I386, VM::is_running_under_translator() returns true, indicating execution under the Windows x86-on-ARM translation layer.

Can VMAware detect UTM virtual machines on Apple Silicon Macs?

Yes, VMAware detects UTM by first identifying the underlying Apple Virtualization Framework (Apple VZ) through CPUID leaf inspection for the "apple virtualization" vendor string, then confirming the specific UTM brand through the detection pipeline. The library maps these identifiers to the UTM brand enum in its scoring system, as documented in src/cli.cpp at line 653.

What CPUID leaves does VMAware check for ARM hypervisor detection?

VMAware checks hypervisor CPUID leaves 0x40000000 through 0x40000100 using the cpu::vmid_template() function implemented at lines 4770–4785 in vmaware.hpp. These leaves contain vendor-specific signatures that reveal the presence of hypervisors like Apple VZ, BareVisor, and other ARM64 virtualization platforms.

Does VMAware support BareVisor detection on ARM platforms?

Yes, BareVisor is supported on both x86 and ARM architectures. VMAware detects it by matching the vendor string "Barevisor!" through the standard vmid_template() CPUID inspection routine, then registering the BAREVISOR brand via the internal scoring mechanism. This detection works identically across architectures, as documented in src/cli.cpp at line 640.

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 →