Skip to main content

vmaware/
types.rs

1/// All known VM / sandbox brands. Repr as usize for array indexing.
2#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
3#[repr(usize)]
4pub enum VMBrand {
5    #[default]
6    Invalid = 0,
7    VBox,
8    VMware,
9    VMwareExpress,
10    VMwareESX,
11    VMwareGSX,
12    VMwareWorkstation,
13    VMwareFusion,
14    VMwareHard,
15    Bhyve,
16    KVM,
17    QEMU,
18    QEMUKVM,
19    KVMHyperV,
20    QEMUKVMHyperV,
21    HyperV,
22    HyperVVPC,
23    Parallels,
24    Xen,
25    ACRN,
26    QNX,
27    Hybrid,
28    Sandboxie,
29    Docker,
30    Wine,
31    VPC,
32    Anubis,
33    JoeBox,
34    ThreatExpert,
35    CWSandbox,
36    Comodo,
37    Bochs,
38    NVMM,
39    BSDVMM,
40    IntelHAXM,
41    Unisys,
42    LMHS,
43    Cuckoo,
44    BlueStacks,
45    Jailhouse,
46    AppleVZ,
47    IntelKGT,
48    AzureHyperV,
49    SimpleVisor,
50    HyperVRoot,
51    UML,
52    PowerVM,
53    GCE,
54    OpenStack,
55    KubeVirt,
56    AWSNitro,
57    Podman,
58    WSL,
59    OpenVZ,
60    Barevisor,
61    HyperPlatform,
62    MiniVisor,
63    IntelTDX,
64    LKVM,
65    AMDSEV,
66    AMDSEVes,
67    AMDSEVsnp,
68    NekoProject,
69    NoirVisor,
70    Qihoo,
71    NSJail,
72    DBVM,
73    UTM,
74    Compaq,
75    Insignia,
76    Connectix,
77    // sentinel – keep last
78    Count,
79}
80
81#[rustfmt::skip]
82static BRAND_STRINGS: &[&str] = &[
83    "Unknown",
84    "VirtualBox",
85    "VMware",
86    "VMware Express",
87    "VMware ESX",
88    "VMware GSX",
89    "VMware Workstation",
90    "VMware Fusion",
91    "VMware (with VmwareHardenedLoader)",
92    "bhyve",
93    "KVM",
94    "QEMU",
95    "QEMU+KVM",
96    "KVM Hyper-V Enlightenment",
97    "QEMU+KVM Hyper-V Enlightenment",
98    "Microsoft Hyper-V",
99    "Microsoft Virtual PC/Hyper-V",
100    "Parallels",
101    "Xen HVM",
102    "ACRN",
103    "QNX hypervisor",
104    "Hybrid Analysis",
105    "Sandboxie",
106    "Docker",
107    "Wine",
108    "Virtual PC",
109    "Anubis",
110    "JoeBox",
111    "ThreatExpert",
112    "CWSandbox",
113    "Comodo",
114    "Bochs",
115    "NetBSD NVMM",
116    "OpenBSD VMM",
117    "Intel HAXM",
118    "Unisys s-Par",
119    "Lockheed Martin LMHS",
120    "Cuckoo",
121    "BlueStacks",
122    "Jailhouse",
123    "Apple VZ",
124    "Intel KGT (Trusty)",
125    "Microsoft Azure Hyper-V",
126    "SimpleVisor",
127    "Hyper-V artifact (host with Hyper-V enabled)",
128    "User-mode Linux",
129    "IBM PowerVM",
130    "Google Compute Engine (KVM)",
131    "OpenStack (KVM)",
132    "KubeVirt (KVM)",
133    "AWS Nitro System (KVM-based)",
134    "Podman",
135    "WSL",
136    "OpenVZ",
137    "Barevisor",
138    "HyperPlatform",
139    "MiniVisor",
140    "Intel TDX",
141    "LKVM",
142    "AMD SEV",
143    "AMD SEV-ES",
144    "AMD SEV-SNP",
145    "Neko Project II",
146    "NoirVisor",
147    "Qihoo 360 Sandbox",
148    "nsjail",
149    "DBVM",
150    "UTM",
151    "Compaq FX!32",
152    "Insignia RealPC",
153    "Connectix Virtual PC",
154];
155
156impl VMBrand {
157    pub fn as_str(self) -> &'static str {
158        let idx = self as usize;
159        if idx < BRAND_STRINGS.len() {
160            BRAND_STRINGS[idx]
161        } else {
162            "Unknown"
163        }
164    }
165}
166
167/// Technique identifiers (bit indices in a Flagset).
168/// Ordering matches the C port's vm_enum_flags.
169#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
170#[repr(u8)]
171pub enum Technique {
172    // Windows-only
173    GpuCapabilities  = 0,
174    AcpiSignature    = 1,
175    PowerCapabilities = 2,
176    DiskSerial       = 3,
177    Ivshmem          = 4,
178    Drivers          = 5,
179    Handles          = 6,
180    VirtualProcessors = 7,
181    HypervisorQuery  = 8,
182    Audio            = 9,
183    Display          = 10,
184    Dll              = 11,
185    VmwareBackdoor   = 12,
186    Wine             = 13,
187    VirtualRegistry  = 14,
188    Mutex            = 15,
189    DeviceString     = 16,
190    VpcInvalid       = 17,
191    VmwareStr        = 18,
192    Gamarue          = 19,
193    CuckooDir        = 20,
194    CuckooPipe       = 21,
195    BootLogo         = 22,
196    Trap             = 23,
197    Ud               = 24,
198    Blockstep        = 25,
199    DbvmHypercall    = 26,
200    KernelObjects    = 27,
201    Nvram            = 28,
202    Edid             = 29,
203    CpuHeuristic     = 30,
204    Clock            = 31,
205    Msr              = 32,
206    KvmInterception  = 33,
207    Breakpoint       = 34,
208    // Linux + Windows
209    SystemRegisters  = 35,
210    Firmware         = 36,
211    Devices          = 37,
212    Azure            = 38,
213    // Linux-only
214    SmbiosVmBit      = 39,
215    Kmsg             = 40,
216    Cvendor          = 41,
217    QemuFwCfg        = 42,
218    Systemd          = 43,
219    Ctype            = 44,
220    Dockerenv        = 45,
221    Dmidecode        = 46,
222    Dmesg            = 47,
223    Hwmon            = 48,
224    LinuxUserHost    = 49,
225    VmwareIomem      = 50,
226    VmwareIoports    = 51,
227    VmwareScsi       = 52,
228    VmwareDmesg      = 53,
229    QemuVirtualDmi   = 54,
230    QemuUsb          = 55,
231    HypervisorDir    = 56,
232    UmlCpu           = 57,
233    VboxModule       = 58,
234    SysinfoProc      = 59,
235    DmiScan          = 60,
236    PodmanFile       = 61,
237    WslProc          = 62,
238    FileAccessHistory = 63,
239    Mac              = 64,
240    NsjailPid        = 65,
241    BluestacksFolders = 66,
242    AmdSevMsr        = 67,
243    Temperature      = 68,
244    Processes        = 69,
245    // Linux + macOS
246    ThreadCount      = 70,
247    // macOS-only
248    MacMemsize       = 71,
249    MacIokit         = 72,
250    MacSip           = 73,
251    IoregGrep        = 74,
252    Hwmodel          = 75,
253    MacSys           = 76,
254    // Cross-platform CPUID
255    HypervisorBit    = 77,
256    Vmid             = 78,
257    ThreadMismatch   = 79,
258    Timer            = 80,
259    CpuBrand         = 81,
260    HypervisorStr    = 82,
261    CpuidSignature   = 83,
262    BochsCpu         = 84,
263    KgtSignature     = 85,
264}
265
266impl Technique {
267    pub const COUNT: usize = 86;
268}
269
270/// A 128-bit bitset for technique flags (two u64 words).
271#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
272pub struct Flagset {
273    lo: u64,
274    hi: u64,
275}
276
277impl Flagset {
278    pub fn new() -> Self {
279        Self::default()
280    }
281
282    /// Build a Flagset from a slice of Techniques.
283    pub fn from_techniques(techs: &[Technique]) -> Self {
284        let mut fs = Self::new();
285        for &t in techs {
286            fs.set(t);
287        }
288        fs
289    }
290
291    /// Enable a technique bit.
292    pub fn set(&mut self, t: Technique) {
293        let idx = t as u8;
294        if idx < 64 {
295            self.lo |= 1u64 << idx;
296        } else {
297            self.hi |= 1u64 << (idx - 64);
298        }
299    }
300
301    /// Check if a technique bit is enabled.
302    pub fn is_set(&self, t: Technique) -> bool {
303        let idx = t as u8;
304        if idx < 64 {
305            (self.lo >> idx) & 1 != 0
306        } else {
307            (self.hi >> (idx - 64)) & 1 != 0
308        }
309    }
310
311    /// Returns true if no techniques are set (empty flagset).
312    pub fn is_empty(&self) -> bool {
313        self.lo == 0 && self.hi == 0
314    }
315
316    /// Enable every known technique.
317    pub fn all() -> Self {
318        // Techniques 0..COUNT
319        let mut fs = Self::new();
320        let count = Technique::COUNT as u8;
321        for idx in 0..count {
322            if idx < 64 {
323                fs.lo |= 1u64 << idx;
324            } else {
325                fs.hi |= 1u64 << (idx - 64);
326            }
327        }
328        fs
329    }
330}
331
332/// Hyper-X classification state.
333#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
334pub enum HyperXState {
335    #[default]
336    Unknown,
337    RealVM,
338    ArtifactVM,
339    Enlightenment,
340}
341
342// ── Detection threshold constants ─────────────────────────────────────────────
343pub const THRESHOLD_SCORE: u32 = 150;
344pub const HIGH_THRESHOLD_SCORE: u32 = 300;
345/// Early-exit when VM_SHORTCUT flag is set and threshold is reached.
346pub const VM_SHORTCUT: bool = true;