A VM / hypervisor / sandbox detection library for Rust – a faithful port of the VMAware C library with additional Windows-focused hardening.
GitHub: https://github.com/TomGousseau/VmawareRust
Crates.io: https://crates.io/crates/novmforbroadcom
| Feature | Description |
|---|---|
| 86 detection techniques | CPUID tricks, registry keys, driver lists, BIOS strings, firmware, kernel objects, and more |
| Hell's Gate + Halo's Gate | On Windows x86-64, all NtQuerySystemInformation / NtOpenDirectoryObject calls are issued via direct syscall instructions, completely bypassing the ntdll trampolines that Windows Defender ATP and other EDR products hook |
| Cross-platform | Compiles on Windows, Linux, and macOS; platform-appropriate techniques are selected automatically |
no_std-friendly API surface |
The public API (detect, brand, percentage, check) is simple and allocation-light |
| Single-header usable as a library | Add it to Cargo.toml and call vmaware::detect(None) |
# Cargo.toml
[dependencies]
vmaware = "0.2"use vmaware::{detect, brand, percentage, VMBrand};
fn main() {
if detect(None) {
println!("Virtual machine detected!");
println!("Brand: {}", brand(None).as_str());
println!("Confidence: {}%", percentage(None));
} else {
println!("No VM detected (confidence: {}%)", percentage(None));
}
}/// Returns true when a virtual machine is detected.
/// Pass `None` to run all applicable techniques.
pub fn detect(flags: Option<Flagset>) -> bool;
/// Returns the most likely VM brand.
pub fn brand(flags: Option<Flagset>) -> VMBrand;
/// VM confidence as a percentage (0–100).
pub fn percentage(flags: Option<Flagset>) -> u8;
/// Number of techniques that fired.
pub fn detected_count(flags: Option<Flagset>) -> usize;
/// All brands that contributed evidence.
pub fn multi_brand(flags: Option<Flagset>) -> Vec<VMBrand>;
/// Run a single technique by ID.
pub fn check(technique: Technique) -> bool;
/// Hyper-X environment classification (RealVM / ArtifactVM / Enlightenment).
pub fn hyperx() -> HyperXState;
/// Human-readable conclusion string.
pub fn conclusion(flags: Option<Flagset>) -> String;Use a Flagset to run only the techniques you care about:
use vmaware::{check, Technique, Flagset};
// Run a single named technique
let found = check(Technique::VmwareBackdoor);
// Run a custom subset
let mut fs = Flagset::new();
fs.set(Technique::HypervisorBit);
fs.set(Technique::Vmid);
fs.set(Technique::CpuBrand);
if vmaware::detect(Some(fs)) {
println!("Hypervisor detected via CPUID probes");
}EDR products such as Windows Defender ATP install userland hooks by
overwriting the first few bytes of sensitive ntdll stubs with a jmp to their
monitoring code. When NtQuerySystemInformation is called to enumerate loaded
drivers or query hypervisor information, the EDR intercepts the call and can
flag or block it.
VMAware avoids this by implementing Hell's Gate:
- The PEB (
gs:[0x60]) is walked directly to find ntdll's in-memory base
address — noGetModuleHandlecall. - ntdll's PE export table is parsed in-place to locate each NT stub's VA.
- The syscall number is read from the clean stub bytes
(4C 8B D1 B8 XX XX XX XX=mov r10,rcx ; mov eax,<nr>). - If a stub is hooked (starts with
E9/jmp), Halo's Gate recovers the
correct number by scanning ±32 neighbouring stubs whose numbers are
sequential. - The
syscallinstruction is executed directly from our own code page,
never passing through any hooked ntdll trampoline.
The public vmaware::syscall module exposes the resolver if you want to use
it in your own code:
#[cfg(all(windows, target_arch = "x86_64"))]
fn example() {
// Resolve the syscall number for any NT function.
if let Some(nr) = vmaware::syscall::resolve("NtQuerySystemInformation") {
println!("NtQuerySystemInformation syscall nr = {:#x}", nr);
}
}VMware, VirtualBox, QEMU/KVM, Hyper-V, Xen, Parallels, Docker, WSL, Bochs, DBVM, VPC, Sandboxie, Cuckoo, Wine, BlueStacks, Azure Hyper-V, AWS Nitro, GCE, OpenStack, AMD SEV/SEV-ES/SEV-SNP, and many more.
| Platform | Supported | Notes |
|---|---|---|
| Windows x86-64 | ✅ Full | Hell's Gate syscall spoofing active |
| Windows ARM64 | ✅ Partial | Syscall spoofing falls back to GetProcAddress |
| Linux x86-64 | ✅ Full | 31 Linux-specific techniques |
| macOS x86-64 / arm64 | 6 macOS techniques (stubs for rest) |
A VM is declared when the accumulated technique score reaches 150 points
out of a maximum of 300 points (HIGH_THRESHOLD_SCORE). Individual
technique scores range from 10 (low confidence, e.g. BootLogo) to 100
(definitive, e.g. VMware backdoor port, VmID CPUID response).
MIT – see LICENSE.
Original C/C++ library by kernelwernel.