Skip to content
λmaldev wiki/
pagesSandbox & VM Detection
T1497WindowsLinuxC / C++WMICPUID

Sandbox & VM Detection

updated 2026-08-047 min readthehackersbrain
Authorized use only. This material is published for detection engineering, malware analysis and authorized red-team engagements. Running these techniques against systems you do not own or have written permission to test is illegal.

Overview

An automated sandbox detonates samples at scale, with no human interaction and a known environment. Sandbox detection is the act of fingerprinting that environment and aborting (or behaving benignly) when it is detected. The goal is not to be stealthy — it is to produce a clean sandbox report while the real behaviour only executes on a genuine target.

Every check is a signature. A sample that calls IsDebuggerPresent, reads the VBOX registry key, then calls ExitProcess is more suspicious than one that does not, because benign software has no reason to do those things. Used judiciously, a few cheap environment checks raise the cost of automated analysis; used aggressively, they become the most reliable indicator in the report.

Note.

Modern sandboxes patch many of the obvious detection vectors: they fake process counts, move the mouse cursor, and accelerate Sleep but report the original value from GetTickCount. Combinations of checks are harder to neutralise than any single check.

The call chain

  1. 1
    CPUID leaf 1 / 0x40000000
    Hypervisor present bit (ECX bit 31) and vendor string identify VMware, VirtualBox, Hyper-V, KVM.
  2. 2
    registry / WMI artefact checks
    Query HARDWARE\DESCRIPTION\System for typical VM strings (VBOX, VMWARE, QEMU).
  3. 3
    timing checks
    RDTSC delta around a CPUID call is inflated inside a hypervisor or when single-stepping a debugger.
  4. 4
    user-activity heuristics
    Check mouse movement, foreground window, number of running processes, disk size, uptime.
  5. 5
    sleep acceleration check
    Sleep(2000) and measure wall time; sandboxes often accelerate sleep to run samples faster.

Reference implementation

sandbox_check.cC
#include <windows.h>
#include <intrin.h>

// 1. CPUID hypervisor bit
static BOOL cpuid_vm(void) {
  int regs[4] = {0};
  __cpuid(regs, 1);
  return (regs[2] >> 31) & 1;  // ECX bit 31
}

// 2. Hypervisor vendor string via leaf 0x40000000
static BOOL cpuid_vendor(void) {
  int regs[4] = {0};
  __cpuid(regs, 0x40000000);
  char vendor[13] = {0};
  memcpy(vendor,     &regs[1], 4);
  memcpy(vendor + 4, &regs[2], 4);
  memcpy(vendor + 8, &regs[3], 4);
  return (strstr(vendor, "VMware")   ||
          strstr(vendor, "VBoxHyperV") ||
          strstr(vendor, "KVMKVMKVM"));
}

// 3. Registry artefact
static BOOL registry_vm(void) {
  HKEY hk;
  if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,
          "HARDWARE\DESCRIPTION\System",
          0, KEY_READ, &hk) != ERROR_SUCCESS)
      return FALSE;
  char buf[256] = {0};
  DWORD sz = sizeof buf;
  RegQueryValueExA(hk, "SystemBiosVersion", NULL, NULL,
                   (LPBYTE)buf, &sz);
  RegCloseKey(hk);
  return (strstr(buf, "VBOX")  ||
          strstr(buf, "VMWARE") ||
          strstr(buf, "QEMU"));
}

// 4. Sleep acceleration check
static BOOL sleep_accel(void) {
  DWORD t0 = GetTickCount();
  Sleep(2000);
  DWORD elapsed = GetTickCount() - t0;
  return elapsed < 1500;  // slept for less than asked
}

// 5. Human activity: mouse has moved since boot
static BOOL no_mouse_movement(void) {
  POINT p1, p2;
  GetCursorPos(&p1);
  Sleep(200);
  GetCursorPos(&p2);
  return (p1.x == p2.x && p1.y == p2.y);
}

// 6. Suspiciously few processes (sandboxes often run minimal process lists)
static BOOL too_few_processes(void) {
  HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  PROCESSENTRY32 pe = { .dwSize = sizeof pe };
  int count = 0;
  if (Process32First(snap, &pe))
      do { count++; } while (Process32Next(snap, &pe));
  CloseHandle(snap);
  return count < 30;
}

BOOL in_sandbox(void) {
  return cpuid_vm()        ||
         cpuid_vendor()    ||
         registry_vm()     ||
         sleep_accel()     ||
         no_mouse_movement() ||
         too_few_processes();
}

Check taxonomy

Category Check Defeat by sandbox
Hardware CPUID HV bit Patched in KVM with kvm-hint-dedicated=on
Hardware CPUID vendor string Spoofed in some hypervisors
Registry BIOS / system strings Cleaned in hardened sandboxes
Timing RDTSC delta inflation Patched in hardware-assisted VMs
Timing Sleep acceleration Reported correctly but still accelerated in some
User behaviour Mouse movement Fake mouse events injected
User behaviour Process count Dozens of decoy processes spawned
Disk Total disk < 80 GB Large virtual disks used in hardened sandboxes

No single check is reliable against a hardened sandbox. Stacking orthogonal checks makes comprehensive neutralisation progressively more expensive.

Detection

BEHAVIOURAL
Process that exits immediately after a CPUID call or a WMI query for hardware strings.
YARA
CPUID + conditional branch pattern, or string literals "VBOX", "VMWARE", "QEMU" in .data.
SANDBOX
Instrument the anti-analysis checks themselves — log what the sample queried and what it decided.

Sandbox operators instrument the checks at the hypervisor or API-hook layer — log what each sample queried and what it concluded, even if the sample then exits cleanly. A sample that touches five or more environment-sensing APIs in its first 500ms of execution is a strong heuristic for a payload that is performing a go/no-go decision.

Was this page useful?edit this page ↗