//go:build antivm && windows package core import ( "log" "os" "runtime" "strings" "syscall" "unsafe" "golang.org/x/sys/windows" "golang.org/x/sys/windows/registry" ) func init() { registerWindowsChecks() } func registerWindowsChecks() { // Protocol: name, fn, certainty // 150% registerCheck("dbvm", dbvmCheck, 150) // 100% registerCheck("wine", wineDetection, 100) registerCheck("mutex", vmMutex, 100) registerCheck("drivers", vmDrivers, 100) registerCheck("disk_serial", diskSerialVM, 100) registerCheck("ivshmem", ivshmemCheck, 100) registerCheck("handles", handlesCheck, 100) registerCheck("virtual_processors", virtualProcessors, 100) registerCheck("hypervisor_query", hypervisorQuery, 100) registerCheck("acpi_signature", acpiSignatureCheck, 100) registerCheck("firmware_tables", firmwareTablesCheck, 100) registerCheck("boot_logo", bootLogoCheck, 100) registerCheck("kernel_objects", kernelObjectsCheck, 100) registerCheck("nvram", nvramCheck, 100) registerCheck("edid", edidCheck, 100) registerCheck("clock_timing", clockTiming, 100) // 95% registerCheck("devices_pci", devicesPCICheck, 95) // 90% registerCheck("virtual_registry", virtualRegistryCheck, 90) registerCheck("cpu_heuristic", cpuHeuristicCheck, 90) // 75% (32-bit only) registerCheck("vpc_invalid", vpcInvalidCheck, 75) // 50% registerCheck("dll", vmDLLs, 50) // 45% registerCheck("clock", clockCheck, 45) // 40% registerCheck("processes", vmProcessesWindows, 40) // 30% registerCheck("cuckoo_dir", cuckooDirCheck, 30) registerCheck("cuckoo_pipe", cuckooPipeCheck, 30) registerCheck("azure", azureHostname, 30) // 25% registerCheck("display", displayCheck, 25) registerCheck("audio", audioDevices, 25) registerCheck("gpu", gpuCapabilities, 25) registerCheck("device_string", deviceStringCheck, 25) registerCheck("power_capabilities", powerCapabilitiesCheck, 25) // 10% registerCheck("gamarue", gamarueCheck, 10) } var vmSysDir = os.Getenv("SYSTEMROOT") + "\\System32\\" // --- 150% --- var vmDLLList = []string{ "vboxhook.dll", "vboxmrxnp.dll", "vboxogl.dll", "vboxoglarrayspu.dll", "vboxoglcrutil.dll", "vboxoglfeedbackspu.dll", "vboxoglpackspu.dll", "vboxoglpassthroughspu.dll", "vboxservice.exe", "vboxtray.exe", "vmtoolsd.exe", "vmacthlp.exe", "vmsrvc.exe", "vmusrvc.exe", "vmserv.exe", "vmwaretray.exe", "vmwareuser.exe", "xenservice.exe", "xsvc.exe", } func vmDLLs() bool { for _, dll := range vmDLLList { if _, err := os.Stat(vmSysDir + dll); err == nil { log.Printf("[antivm] windows_dll: found %s", dll) return true } } getModuleHandle := syscall.NewLazyDLL("kernel32.dll").NewProc("GetModuleHandleW") if getModuleHandle.Find() != nil { return false } for _, dll := range []string{"VBoxHook.dll", "VBoxOGL.dll", "vmware-vmx.dll"} { dllName, _ := syscall.UTF16PtrFromString(dll) if dllName == nil { continue } ret, _, _ := getModuleHandle.Call(uintptr(unsafe.Pointer(dllName))) if ret != 0 { return true } } return false } func dbvmCheck() bool { ntdll := syscall.NewLazyDLL("ntdll.dll") dbvm := ntdll.NewProc("DbvmCheck") return dbvm.Find() == nil } func vmDrivers() bool { scsiPaths := []string{ `HARDWARE\DEVICEMAP\Scsi\Scsi Port 0\Scsi Bus 0\Target Id 0\Logical Unit Id 0`, `HARDWARE\DEVICEMAP\Scsi\Scsi Port 1\Scsi Bus 0\Target Id 0\Logical Unit Id 0`, `HARDWARE\DEVICEMAP\Scsi\Scsi Port 2\Scsi Bus 0\Target Id 0\Logical Unit Id 0`, } vmTags := []string{"VBOX", "VMWARE", "QEMU", "XEN", "VIRTUAL"} for _, path := range scsiPaths { k, err := registry.OpenKey(registry.LOCAL_MACHINE, path, registry.QUERY_VALUE) if err != nil { continue } val, _, err := k.GetStringValue("Identifier") k.Close() if err != nil { continue } upper := strings.ToUpper(val) for _, tag := range vmTags { if strings.Contains(upper, tag) { return true } } } return false } func vmMutex() bool { snap, err := windows.CreateToolhelp32Snapshot(windows.TH32CS_SNAPPROCESS, 0) if err != nil { return false } defer windows.CloseHandle(snap) var entry windows.ProcessEntry32 entry.Size = uint32(unsafe.Sizeof(entry)) if err := windows.Process32First(snap, &entry); err != nil { return false } vmProcs := []string{ "vboxservice.exe", "vboxtray.exe", "vboxcontrol.exe", "vmtoolsd.exe", "vmwaretray.exe", "vmwareuser.exe", "vmupgradehelper.exe", "vmacthlp.exe", "xenservice.exe", "prl_cc.exe", "prl_tools.exe", } for { name := strings.ToLower(syscall.UTF16ToString(entry.ExeFile[:])) for _, vm := range vmProcs { if name == vm { return true } } if err := windows.Process32Next(snap, &entry); err != nil { break } } return false } func vmProcessesWindows() bool { return vmMutex() } func diskSerialVM() bool { k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SYSTEM\CurrentControlSet\Services\Disk\Enum`, registry.QUERY_VALUE) if err != nil { return false } defer k.Close() val, _, err := k.GetStringValue("0") if err != nil { return false } upper := strings.ToUpper(val) for _, tag := range []string{"VBOX", "VMWARE", "QEMU", "XEN"} { if strings.Contains(upper, tag) { return true } } return false } func ivshmemCheck() bool { k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SYSTEM\CurrentControlSet\Enum\PCI`, registry.ENUMERATE_SUB_KEYS) if err != nil { return false } defer k.Close() subs, err := k.ReadSubKeyNames(0) if err != nil { return false } for _, sub := range subs { if strings.Contains(strings.ToLower(sub), "1af4") || strings.Contains(strings.ToLower(sub), "ivshmem") { return true } } return false } func handlesCheck() bool { k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SYSTEM\CurrentControlSet\Enum\PCI`, registry.ENUMERATE_SUB_KEYS) if err != nil { return false } defer k.Close() subs, _ := k.ReadSubKeyNames(0) vmDevices := []string{"15ad", "80ee", "1af4"} for _, sub := range subs { for _, vm := range vmDevices { if strings.HasPrefix(strings.ToLower(sub), vm) { return true } } } return false } func virtualProcessors() bool { return runtime.NumCPU() < 2 } func hypervisorQuery() bool { ntdll := syscall.NewLazyDLL("ntdll.dll") ntQuery := ntdll.NewProc("NtQuerySystemInformation") if ntQuery.Find() != nil { return false } // SystemHypervisorInformation = 0x9f var buf [256]byte ret, _, _ := ntQuery.Call(0x9f, uintptr(unsafe.Pointer(&buf[0])), uintptr(len(buf)), 0) return ret == 0 } func acpiSignatureCheck() bool { k, err := registry.OpenKey(registry.LOCAL_MACHINE, `HARDWARE\ACPI\DSDT`, registry.ENUMERATE_SUB_KEYS) if err != nil { return false } defer k.Close() subs, _ := k.ReadSubKeyNames(0) for _, sub := range subs { lower := strings.ToLower(sub) if strings.Contains(lower, "vbox") || strings.Contains(lower, "vmw") || strings.Contains(lower, "qemu") || strings.Contains(lower, "xen") { return true } } return false } func firmwareTablesCheck() bool { k, err := registry.OpenKey(registry.LOCAL_MACHINE, `HARDWARE\ACPI\Firmware`, registry.QUERY_VALUE) if err != nil { return false } defer k.Close() vals, _ := k.ReadValueNames(0) for _, v := range vals { if strings.Contains(strings.ToLower(v), "vbox") || strings.Contains(strings.ToLower(v), "vmware") || strings.Contains(strings.ToLower(v), "qemu") { return true } } return false } func bootLogoCheck() bool { k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows\CurrentVersion\OEMInformation`, registry.QUERY_VALUE) if err != nil { return false } defer k.Close() logo, _, err := k.GetStringValue("Logo") if err != nil { return false } lower := strings.ToLower(logo) return strings.Contains(lower, "vbox") || strings.Contains(lower, "vmware") } func kernelObjectsCheck() bool { k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SYSTEM\CurrentControlSet\Control\Class\{4d36e968-e325-11ce-bfc1-08002be10318}`, registry.ENUMERATE_SUB_KEYS) if err != nil { return false } defer k.Close() subs, _ := k.ReadSubKeyNames(0) for _, sub := range subs { subKey, err := registry.OpenKey(registry.LOCAL_MACHINE, `SYSTEM\CurrentControlSet\Control\Class\{4d36e968-e325-11ce-bfc1-08002be10318}\`+sub, registry.QUERY_VALUE) if err != nil { continue } desc, _, err := subKey.GetStringValue("DriverDesc") subKey.Close() if err != nil { continue } lower := strings.ToLower(desc) if strings.Contains(lower, "vmware") || strings.Contains(lower, "vbox") || strings.Contains(lower, "virtual") || strings.Contains(lower, "qemu") { return true } } return false } func nvramCheck() bool { k, err := registry.OpenKey(registry.LOCAL_MACHINE, `HARDWARE\RESOURCEMAP`, registry.ENUMERATE_SUB_KEYS) if err != nil { return false } defer k.Close() subs, _ := k.ReadSubKeyNames(0) for _, sub := range subs { if strings.Contains(strings.ToLower(sub), "vbox") || strings.Contains(strings.ToLower(sub), "vmware") { return true } } return false } func edidCheck() bool { k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SYSTEM\CurrentControlSet\Enum\DISPLAY`, registry.ENUMERATE_SUB_KEYS) if err != nil { return false } defer k.Close() subs, _ := k.ReadSubKeyNames(0) for _, sub := range subs { lower := strings.ToLower(sub) if strings.Contains(lower, "vmware") || strings.Contains(lower, "vbox") || strings.Contains(lower, "qemu") { return true } } return false } func clockTiming() bool { ntdll := syscall.NewLazyDLL("ntdll.dll") ntQuery := ntdll.NewProc("NtQuerySystemInformation") if ntQuery.Find() != nil { return false } // SystemTimeAdjustmentInformation = 0x94 var buf [32]byte ret, _, _ := ntQuery.Call(0x94, uintptr(unsafe.Pointer(&buf[0])), uintptr(len(buf)), 0) return ret == 0 } // --- 95% --- func devicesPCICheck() bool { k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SYSTEM\CurrentControlSet\Enum\PCI`, registry.ENUMERATE_SUB_KEYS) if err != nil { return false } defer k.Close() subs, _ := k.ReadSubKeyNames(0) vmVendors := []string{"15ad", "80ee", "1af4"} for _, sub := range subs { parts := strings.SplitN(sub, "\\", 2) if len(parts) > 0 { vendor := strings.ToLower(parts[0]) for _, v := range vmVendors { if strings.HasPrefix(vendor, v) { return true } } } } return false } // --- 90% --- func virtualRegistryCheck() bool { k, err := registry.OpenKey(registry.CURRENT_USER, `Software\Sandboxie`, registry.QUERY_VALUE) if err == nil { k.Close() return true } k2, err := registry.OpenKey(registry.LOCAL_MACHINE, `SYSTEM\CurrentControlSet\Services\Sandboxie`, registry.QUERY_VALUE) if err == nil { k2.Close() return true } return false } func cpuHeuristicCheck() bool { kernel32 := syscall.NewLazyDLL("kernel32.dll") isIntel := kernel32.NewProc("IsProcessorFeaturePresent") if isIntel.Find() != nil { return false } // PF_XMMI64_INSTRUCTIONS_AVAILABLE = 10 // Check if SSE2 is properly reported ret, _, _ := isIntel.Call(10) return ret == 0 } // --- 75% --- func vpcInvalidCheck() bool { // Virtual PC check (32-bit only via CPUID) ntdll := syscall.NewLazyDLL("ntdll.dll") vpc := ntdll.NewProc("VpcGuest") return vpc.Find() == nil } // --- 45% --- func clockCheck() bool { kernel32 := syscall.NewLazyDLL("kernel32.dll") getTickCount := kernel32.NewProc("GetTickCount64") t1, _, _ := getTickCount.Call() t2, _, _ := getTickCount.Call() // If time doesn't advance normally, could be VM return t2-t1 > 100 } // --- 30% --- func cuckooDirCheck() bool { paths := []string{ "C:\\Cuckoo", "C:\\analysis", "C:\\Analyzer", os.Getenv("TEMP") + "\\cuckoa", } for _, p := range paths { if _, err := os.Stat(p); err == nil { return true } } return false } func cuckooPipeCheck() bool { // Check for Cuckoo pipe names pipes := []string{`\\.\pipe\cuckoo`, `\\.\pipe\analyzer`} for _, p := range pipes { if _, err := os.Stat(p); err == nil { return true } } return false } // --- 25% --- func displayCheck() bool { user32 := syscall.NewLazyDLL("user32.dll") getSystemMetrics := user32.NewProc("GetSystemMetrics") horz, _, _ := getSystemMetrics.Call(0) vert, _, _ := getSystemMetrics.Call(1) return (horz < 800 && vert < 600) || horz == 0 } func audioDevices() bool { winmm := syscall.NewLazyDLL("winmm.dll") out, _, _ := winmm.NewProc("waveOutGetNumDevs").Call() in, _, _ := winmm.NewProc("waveInGetNumDevs").Call() return out == 0 && in == 0 } func gpuCapabilities() bool { k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SYSTEM\CurrentControlSet\Control\Class\{4d36e968-e325-11ce-bfc1-08002be10318}\0000`, registry.QUERY_VALUE) if err != nil { return false } defer k.Close() desc, _, err := k.GetStringValue("DriverDesc") if err != nil { return false } lower := strings.ToLower(desc) for _, s := range []string{"virtual", "vmware", "vbox", "qemu", "hyper-v"} { if strings.Contains(lower, s) { return true } } return false } func deviceStringCheck() bool { k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SYSTEM\CurrentControlSet\Services\Disk\Enum`, registry.QUERY_VALUE) if err != nil { return false } defer k.Close() vals, _ := k.ReadValueNames(0) for _, v := range vals { val, _, err := k.GetStringValue(v) if err != nil { continue } lower := strings.ToLower(val) if strings.Contains(lower, "vbox") || strings.Contains(lower, "qemu") || strings.Contains(lower, "vmware") { return true } } return false } func powerCapabilitiesCheck() bool { powrprof := syscall.NewLazyDLL("powrprof.dll") callNtPowerInfo := powrprof.NewProc("CallNtPowerInformation") if callNtPowerInfo.Find() != nil { return false } // SystemPowerInformation = 12 var buf [32]byte ret, _, _ := callNtPowerInfo.Call(12, 0, 0, uintptr(unsafe.Pointer(&buf[0])), uintptr(len(buf))) return ret == 0 } // --- 10% --- func gamarueCheck() bool { k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion`, registry.QUERY_VALUE) if err != nil { return false } defer k.Close() productID, _, err := k.GetStringValue("ProductId") if err != nil { return false } // Gamarue VM detection: checks for specific product ID patterns return strings.HasPrefix(productID, "00330-") || strings.HasPrefix(productID, "00331-") } // --- 100% --- func wineDetection() bool { ntdll, err := syscall.LoadLibrary("ntdll.dll") if err != nil { return false } defer syscall.FreeLibrary(ntdll) _, err = syscall.GetProcAddress(ntdll, "wine_get_unix_file_name") return err == nil }