VMAware Technique Table Internal Structure: Compile-Time Detection Array Architecture

The VMAware library organizes every VM detection routine into a static, compile-time initialized std::array indexed by enum values, where each entry stores a certainty score and a function pointer to the platform-specific detection logic.

The kernelwernel/vmaware repository implements its detection engine through a sophisticated technique table that enables zero-overhead dispatch across Windows, Linux, and macOS. This internal structure maps unique enum identifiers to executable detection routines while supporting both compile-time and runtime extensibility.

Core Data Structures

The technique Struct

At the heart of the system lies the technique struct defined in [src/vmaware.hpp](https://github.com/kernelwernel/vmaware/blob/main/src/vmaware.hpp) at lines 11641‑11644. This minimal structure contains two critical fields:

struct technique {
    u16 points;        // Certainty score (0-100%)
    bool(*run)();      // Function pointer to detection logic
};

The points field represents the confidence weight assigned to a successful detection, while run holds the address of the static C++ function that performs the actual VM check.

Static Table Storage

The master lookup table is declared at line 11659 as a compile-time initialized array:

static std::array<technique, enum_size + 1> technique_table;

This array is indexed directly by the enum_flags values defined at lines 553‑563, creating an O(1) mapping between technique identifiers and their executable logic. The enum includes placeholders marked with // ADD NEW TECHNIQUE ENUM NAME HERE for extending the framework.

Temporary Construction Pairs

To populate the table, VMAware uses a helper struct technique_entry (lines 11645‑11648) that pairs enum values with technique data during the build process:

struct technique_entry {
    enum_flags id;
    technique tech;
};

Compile-Time Table Construction

The Population Lambda

The table is populated through a constexpr lambda located at lines 12852‑12955. This compile-time logic iterates over a static array of technique_entry objects and assigns each to its indexed position:

for (const auto& entry : entries) {
    table[entry.id] = entry.tech;
}

Platform-Specific Guarding

Techniques are wrapped in OS-specific preprocessor blocks (#if WINDOWS, #if LINUX, #if APPLE) within the entries[] array. This conditional compilation ensures that only relevant detection routines are included in the final binary for each target platform. For example, a Windows-specific entry appears as:

{ VM::TRAP, {100, VM::trap} }   // Windows-only: 100% certainty

Runtime Execution Flow

The run_all Dispatcher

The execution engine resides in VM::core::run_all (lines 11732‑11835). This method iterates over the index range [technique_begin, technique_end) and performs the following operations for each technique_table[i]:

  1. Skips entries where run is nullptr
  2. Checks the bitset flag to determine if the technique is disabled via core::is_disabled
  3. Looks up cached results through memo::is_cached to avoid redundant execution
  4. Executes technique_data.run() if not cached
  5. Adds the technique's points (or an overridden last_detected_score) to the global confidence total
  6. Stores the result in the memo cache via memo::cache_store

Shortcut and Threshold Logic

When the shortcut flag is enabled, the loop aborts early if the accumulated score exceeds threshold_score or high_threshold_score, optimizing performance for high-confidence detections.

Extending the Technique Table

Runtime Custom Techniques

Beyond the static table, VMAware supports runtime extension through custom_table (lines 11661‑11663). Users can register up to 256 custom techniques via the VM::add_custom API:

bool my_custom_check() { return true; }

VM::add_custom(VM::core::custom_technique{
    VM::core::technique_count++,
    { 80, my_custom_check }
});

Custom entries participate in run_all exactly like built-in techniques after registration.

Automated Technique Addition

The repository includes auxiliary/add_technique.py, an interactive script that automates the insertion of new detection methods. The script updates:

  • The enum definition at the // ADD NEW TECHNIQUE ENUM NAME HERE marker
  • The static entries[] array in the technique table
  • Checklist entries in src/cli.cpp
  • Documentation rows in docs/documentation.md

The script also handles GPL-only techniques by wrapping generated code in /* GPL */ comments.

Practical Implementation Examples

Running Default Detection

// Initialize default flagset with all techniques enabled
VM::flagset flags = VM::generate_default();

// Execute with shortcut optimization (stops at threshold 150)
uint16_t score = VM::run_all(flags, VM::SHORTCUT);
std::cout << "VM confidence: " << score << "%\n";

Selective Technique Execution

VM::flagset flags = VM::generate_all();
flags.reset();                           // Clear all
flags.set(VM::FIRMWARE);                 // Enable specific Linux check
flags.set(VM::SMBIOS_VM_BIT);

// Run without shortcut (all selected techniques execute)
uint16_t score = VM::run_all(flags, false);

Adding Custom Detection Logic

// Define custom detection
bool detect_container_artifact() {
    return std::filesystem::exists("/.dockerenv");
}

// Register with 90% confidence
VM::add_custom(VM::core::custom_technique{
    VM::core::technique_count++,
    { 90, detect_container_artifact }
});

Summary

  • The technique table is a compile-time initialized std::array mapping enum indices to detection functions and certainty scores.
  • Each entry in [src/vmaware.hpp](https://github.com/kernelwernel/vmaware/blob/main/src/vmaware.hpp) lines 11641‑11644 contains a u16 points field and a bool(*run)() function pointer.
  • Platform-specific techniques are guarded by preprocessor blocks, ensuring only relevant code compiles for Windows, Linux, or macOS targets.
  • The run_all dispatcher (lines 11732‑11835) handles execution, memoization, scoring accumulation, and early termination via shortcut logic.
  • Runtime extensibility is supported through custom_table (lines 11661‑11663) with a maximum of 256 user-defined techniques.
  • The auxiliary/add_technique.py script automates the boilerplate required to add new built-in detection methods to the enum, table, CLI, and documentation.

Frequently Asked Questions

How does VMAware handle techniques that are not supported on the current operating system?

Unsupported techniques are excluded at compile time through preprocessor guards (#if WINDOWS, #if LINUX, #if APPLE) surrounding entries in the static entries[] array. This ensures the technique table only contains functions callable on the target platform, eliminating runtime checks or dead code.

Can the technique table be modified after the program starts?

The static technique_table itself is immutable at runtime, but VMAware provides the custom_table mechanism (lines 11661‑11663) which accepts new entries via VM::add_custom. These runtime additions are stored separately and merged into the execution flow by run_all, allowing dynamic extension without modifying the compiled table.

What is the performance cost of checking hundreds of techniques?

The table uses O(1) array indexing and supports shortcut optimization, which terminates execution early when the accumulated confidence score exceeds the configured threshold. Additionally, a memoization cache prevents redundant execution of techniques within the same process, minimizing CPU overhead for repeated scans.

Why does the technique struct use raw function pointers instead of std::function?

The bool(*run)() function pointer in the technique struct (lines 11641‑11644) provides zero-overhead abstraction compatible with compile-time initialization. Unlike std::function, raw pointers impose no allocation overhead, no type erasure costs, and allow the entire table to be constructed as a constexpr static array, ensuring minimal binary size and maximum dispatch speed.

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 →