# Hyper-X Detection Module in VMAware: How It Distinguishes Real VMs from Artifacts

> Discover how the Hyper-X detection module in VMAware distinguishes real VMs from artifacts using CPUID analysis hypervisor bit validation and OS inspection. Understand Hyper-V environments.

- Repository: [Louis/vmaware](https://github.com/kernelwernel/vmaware)
- Tags: deep-dive
- Published: 2026-03-05

---

**The Hyper-X detection module in VMAware uses CPUID leaf analysis, hypervisor bit validation, and OS-level artifact inspection to classify systems as genuine Hyper-V virtual machines, hosts with Hyper-V enabled, or non-Hyper-V environments.**

The **Hyper-X detection module** is a specialized subsystem within the VMAware library (kernelwernel/vmaware) designed to solve the complex problem of differentiating between actual Hyper-V virtual machines and bare-metal systems that merely exhibit Hyper-V artifacts. This distinction is critical for accurate virtualization detection, as simply enabling Hyper-V on a Windows host or certain security features can set hypervisor-related CPU flags that mimic VM signatures.

## Core Architecture of the Hyper-X Detection Module

### The hyperx_state Enum

At the heart of the module lies the `hyperx_state` enumeration defined in [`src/vmaware.hpp`](https://github.com/kernelwernel/vmaware/blob/main/src/vmaware.hpp) (lines 796–802). This enum provides four distinct classification states:

- **`HYPERV_REAL_VM`**: Indicates a genuine Hyper-V child partition with full virtualization
- **`HYPERV_ARTIFACT_VM`**: Signals a physical host with Hyper-V enabled (showing hypervisor bits but no VM isolation)
- **`HYPERV_ENLIGHTENMENT`**: Detects Hyper-V enlightenment features present in the system
- **`HYPERV_UNKNOWN`**: Default state when no Hyper-V evidence is found

### The util::hyper_x() Entry Point

The central detection logic resides in `vmaware::util::hyper_x()`, implemented starting at line 3772 in [`src/vmaware.hpp`](https://github.com/kernelwernel/vmaware/blob/main/src/vmaware.hpp). This function orchestrates the entire detection pipeline:

1. **Memoization check**: First queries `memo::hyperx` to avoid redundant CPUID operations
2. **Sequential validation**: Executes low-level hardware and OS checks in order of specificity
3. **State resolution**: Returns the appropriate `hyperx_state` value based on cumulative evidence

The implementation uses defensive logic: if any single check indicates a real Hyper-V VM, it immediately returns `HYPERV_REAL_VM`. Conversely, if only indirect artifacts exist without Hyper-V-specific leaves, it classifies the system as `HYPERV_ARTIFACT_VM`.

## Detection Heuristics and Implementation Details

### CPUID Leaf Analysis

The module performs deep inspection of processor identification leaves to verify Hyper-V presence:

- **Leaf 0x40000003**: Specifically checks for the Hyper-V child partition signature that indicates true virtualization
- **Leaf 1, ECX bit 31**: Validates the hypervisor present bit (required but not sufficient for Hyper-V detection)
- **Leaves 0x40000000–0x40000100**: Reads hypervisor vendor ID strings to confirm "Microsoft Hv" branding

These CPUID checks differentiate Hyper-V from other hypervisors like VMware or VirtualBox, which set different vendor strings in the 0x40000000 range.

### OS-Level Artifact Inspection

Beyond CPU features, the module examines operating system structures:

- **Linux systems**: Scans `/sys/hypervisor` entries for Hyper-V specific sysfs nodes
- **Windows systems**: Queries the `SYSTEM_HYPERVISOR_DETAIL_INFORMATION` structure via native API calls to detect hypervisor type and partition properties

This cross-platform approach ensures consistent detection across Windows Server, Windows 10/11, and various Linux distributions running on Hyper-V.

### Cross-Validation Logic

To prevent false positives, the module employs consistency checks that correlate CPUID results with OS artifacts. For example, if the hypervisor bit is set but the 0x40000003 leaf is absent, and no Hyper-V sysfs entries exist on Linux, the system is classified as `HYPERV_ARTIFACT_VM` rather than a real VM. This logic prevents misidentification of systems running with Hyper-V's Hypervisor-protected Code Integrity (HVCI) or Credential Guard enabled.

## Integration with VMAware's Detection Pipeline

### Technique Selection and Scoring

The **Hyper-X detection module** influences the broader VMAware detection strategy through conditional execution guards. Many VM detection techniques in [`src/vmaware.hpp`](https://github.com/kernelwernel/vmaware/blob/main/src/vmaware.hpp) (such as brand string checks at line 1140) first query `util::hyper_x()`:

- If the result is `HYPERV_ARTIFACT_VM`, certain brand-string or hypervisor-bit tests are skipped to avoid double-counting artifacts
- The hyper-X result feeds into the brand scoring algorithm, adjusting confidence levels for Hyper-V detection versus other hypervisors

### Memoization and Performance

The `memo::hyperx` cache system (referenced at lines 3776–3781) stores the detection result after the first invocation. Subsequent calls to `util::hyper_x()` return instantly from cache, ensuring that multiple detection techniques can query the Hyper-X state without repeating expensive CPUID operations. This design pattern appears throughout VMAware where `memo::hyperx::is_cached()` and `memo::hyperx::store()` manage persistent state.

## Practical Usage Examples

### Detecting Hyper-V State

The following example demonstrates basic usage of the Hyper-X detection module:

```cpp
#include "vmaware.hpp"
#include <iostream>

int main() {
    // Run the Hyper-X detector
    vmaware::util::hyperx_state state = vmaware::util::hyper_x();

    switch (state) {
        case vmaware::util::HYPERV_REAL_VM:
            std::cout << "Running inside a genuine Hyper-V VM.\n";
            break;
        case vmaware::util::HYPERV_ARTIFACT_VM:
            std::cout << "Hyper-V artifacts detected (host with Hyper-V enabled).\n";
            break;
        case vmaware::util::HYPERV_ENLIGHTENMENT:
            std::cout << "Hyper-V enlightenment features present.\n";
            break;
        default:
            std::cout << "No Hyper-V evidence found.\n";
    }
    return 0;
}

```

*Implementation reference*: `util::hyper_x()` – [`src/vmaware.hpp`](https://github.com/kernelwernel/vmaware/blob/main/src/vmaware.hpp) lines 3772–3816.

### Leveraging Cached Results

Because the module memoizes results, repeated calls are computationally cheap:

```cpp
// First call performs full detection
auto first_result = vmaware::util::hyper_x();

// Subsequent calls retrieve from cache instantly
auto cached_result = vmaware::util::hyper_x();
assert(first_result == cached_result);

```

*Memoization details*: `memo::hyperx::is_cached()` and `memo::hyperx::store()` – [`src/vmaware.hpp`](https://github.com/kernelwernel/vmaware/blob/main/src/vmaware.hpp) lines 3776–3781.

### Conditional Detection Techniques

Integrate Hyper-X checks to avoid false positives in custom detection logic:

```cpp
if (vmaware::util::hyper_x() != vmaware::util::HYPERV_ARTIFACT_VM) {
    // Only run if not a Hyper-V host artifact
    perform_hyperv_brand_check();
    check_hypervisor_bit();
}

```

This pattern mirrors VMAware's internal technique guards that prevent artifact double-counting.

## Summary

- The **Hyper-X detection module** classifies systems into four states: real VM, artifact host, enlightenment features, or unknown
- **Implementation** centers on `util::hyper_x()` in [`src/vmaware.hpp`](https://github.com/kernelwernel/vmaware/blob/main/src/vmaware.hpp) (line 3772), which checks CPUID leaves 0x40000003 and 0x40000000 for Hyper-V signatures
- **Cross-validation** correlates CPUID hypervisor bits with OS artifacts like `/sys/hypervisor` or Windows hypervisor information structures
- **Memoization** via `memo::hyperx` ensures subsequent calls return cached results without re-executing expensive CPUID instructions
- The module integrates with VMAware's scoring system to adjust detection confidence and prevent false positives from Hyper-V-enabled hosts

## Frequently Asked Questions

### How does the Hyper-X detection module differentiate between a real Hyper-V VM and a host with Hyper-V enabled?

The module checks for **CPUID leaf 0x40000003**, which is specific to Hyper-V child partitions and absent on bare-metal hosts with Hyper-V enabled. While both real VMs and enabled hosts set the hypervisor bit (CPUID leaf 1, ECX bit 31), only genuine VMs exhibit the 0x40000003 leaf signature and specific OS-level isolation artifacts. If only the hypervisor bit is present without the child partition leaf, the system is classified as `HYPERV_ARTIFACT_VM`.

### What is the performance impact of calling util::hyper_x() multiple times?

**Zero impact after the first call.** The module implements memoization through `memo::hyperx`, storing the detection result in a static cache after the initial execution (lines 3776–3781 in [`src/vmaware.hpp`](https://github.com/kernelwernel/vmaware/blob/main/src/vmaware.hpp)). All subsequent invocations of `util::hyper_x()` return the cached value instantly without re-executing CPUID instructions or OS queries.

### Can the Hyper-X detection module identify other hypervisors like VMware or VirtualBox?

**No**, the module is specifically designed for Hyper-V detection. While it reads the generic hypervisor present bit (which any hypervisor can set), the critical validation depends on vendor strings ("Microsoft Hv") and Hyper-V-specific CPUID leaves (0x40000003). Other hypervisors set different vendor IDs in the 0x40000000 leaf range, causing the module to return `HYPERV_UNKNOWN` for VMware, VirtualBox, or KVM environments.

### Where is the Hyper-X detection logic implemented in the VMAware source code?

The core implementation resides in **[`src/vmaware.hpp`](https://github.com/kernelwernel/vmaware/blob/main/src/vmaware.hpp)** starting at line 3772, within the `vmaware::util` namespace. The `hyperx_state` enum is defined at lines 796–802, while the memoization helpers appear alongside the main function. Integration points with other detection techniques appear throughout the header, particularly where `util::hyper_x()` guards prevent artifact double-counting (e.g., line 1140).