Init commit

This commit is contained in:
My Name
2026-11-03 20:45:39 -08:00
commit 26642f28a2
57 changed files with 15683 additions and 0 deletions
+487
View File
@@ -0,0 +1,487 @@
#include "Common.h"
#include "VmDetect.h"
#include <intrin.h>
#include <iphlpapi.h>
#include <string>
#pragma comment(lib, "iphlpapi.lib")
static std::string ToLowerAscii(const std::string& in)
{
std::string out = in;
for (auto& c : out)
{
if (c >= 'A' && c <= 'Z')
c = (char)(c + 32);
}
return out;
}
static std::string NarrowAscii(const wchar_t* w)
{
std::string out;
if (!w)
return out;
for (; *w; ++w)
{
if (*w < 128)
out.push_back((char)*w);
}
return out;
}
static bool ContainsAny(const std::string& haystackLower, std::initializer_list<const char*> needles)
{
for (const char* n : needles)
{
if (haystackLower.find(n) != std::string::npos)
return true;
}
return false;
}
// ---------------------------------------------------------------- CPUID
struct CpuidResult
{
bool hypervisorPresent = false;
std::string vendor; // raw 12-byte hypervisor vendor
std::string brand;
};
static CpuidResult QueryCpuid()
{
CpuidResult r;
int regs[4]{};
__cpuid(regs, 0);
int maxLeaf = regs[0];
__cpuid(regs, 1);
r.hypervisorPresent = (regs[2] & (1 << 31)) != 0;
if (maxLeaf >= 0x40000000)
{
int hv[4]{};
__cpuid(hv, 0x40000000);
char vendor[13]{};
memcpy(vendor + 0, &hv[1], 4);
memcpy(vendor + 4, &hv[2], 4);
memcpy(vendor + 8, &hv[3], 4);
r.vendor = vendor;
if (maxLeaf >= 0x40000001)
{
int b[4]{};
__cpuid(b, 0x40000001);
char brand[13]{};
memcpy(brand + 0, &b[0], 4);
memcpy(brand + 4, &b[1], 4);
memcpy(brand + 8, &b[2], 4);
r.brand = brand;
}
}
return r;
}
// ---------------------------------------------------------------- SMBIOS
static std::string ReadSmbiosStrings()
{
std::string collected;
DWORD size = GetSystemFirmwareTable('RSMB', 0, nullptr, 0);
if (size < 8 || size > 1024 * 1024)
return collected;
std::vector<BYTE> buf(size);
DWORD got = GetSystemFirmwareTable('RSMB', 0, buf.data(), size);
if (got < 8)
return collected;
const BYTE* data = buf.data();
DWORD length = got;
// Raw SMBIOS table: 8-byte header, then structure table.
DWORD tableLen = *(const DWORD*)(data + 4);
if (tableLen == 0 || tableLen > length - 8)
tableLen = length - 8;
const BYTE* p = data + 8;
const BYTE* end = data + 8 + tableLen;
while (p + 4 <= end)
{
BYTE structLen = p[1];
if (structLen < 4 || p + structLen > end)
break;
const BYTE* strings = p + structLen;
// Strings: NUL-terminated ASCII, double NUL ends the list.
while (strings + 1 < end && !(strings[0] == 0 && strings[1] == 0))
{
const char* s = (const char*)strings;
size_t len = strlen(s);
collected += s;
collected += ' ';
strings += len + 1;
}
p = strings + 2;
}
return collected;
}
// ---------------------------------------------------------------- registry
static bool RegKeyExists(HKEY root, const wchar_t* subKey)
{
HKEY h = nullptr;
if (RegOpenKeyExW(root, subKey, 0, KEY_READ, &h) != ERROR_SUCCESS)
return false;
RegCloseKey(h);
return true;
}
static std::string ReadDiskEnumValue()
{
std::string out;
HKEY h = nullptr;
if (RegOpenKeyExW(
HKEY_LOCAL_MACHINE,
L"SYSTEM\\CurrentControlSet\\Services\\Disk\\Enum",
0,
KEY_READ,
&h) != ERROR_SUCCESS)
{
return out;
}
wchar_t buf[1024]{};
DWORD size = sizeof(buf);
DWORD type = 0;
if (RegQueryValueExW(h, L"0", nullptr, &type, (LPBYTE)buf, &size) == ERROR_SUCCESS &&
(type == REG_SZ || type == REG_EXPAND_SZ))
{
out = NarrowAscii(buf);
}
RegCloseKey(h);
return out;
}
// ---------------------------------------------------------------- network
static bool HasVirtualMac()
{
// Vendor OUIs that only appear on virtual adapters.
static const BYTE oui[][3] =
{
{ 0x00, 0x0C, 0x29 }, // VMware
{ 0x00, 0x50, 0x56 }, // VMware
{ 0x00, 0x05, 0x69 }, // VMware
{ 0x00, 0x1C, 0x14 }, // VMware
{ 0x08, 0x00, 0x27 }, // VirtualBox
{ 0x52, 0x54, 0x00 }, // QEMU / KVM
{ 0x00, 0x16, 0x3E }, // Xen
{ 0x00, 0x15, 0x5D }, // Hyper-V
{ 0x00, 0x03, 0xFF }, // Microsoft virtual
{ 0x00, 0x1C, 0x42 }, // Parallels
};
ULONG size = 16 * 1024;
std::vector<BYTE> buf(size);
ULONG ret = GetAdaptersInfo((PIP_ADAPTER_INFO)buf.data(), &size);
if (ret == ERROR_BUFFER_OVERFLOW)
{
buf.resize(size);
ret = GetAdaptersInfo((PIP_ADAPTER_INFO)buf.data(), &size);
}
if (ret != ERROR_SUCCESS)
return false;
for (PIP_ADAPTER_INFO a = (PIP_ADAPTER_INFO)buf.data(); a; a = a->Next)
{
for (const auto& prefix : oui)
{
if (a->AddressLength >= 3 &&
a->Address[0] == prefix[0] &&
a->Address[1] == prefix[1] &&
a->Address[2] == prefix[2])
{
return true;
}
}
}
return false;
}
// ---------------------------------------------------------------- artifacts
static bool HasVmServices()
{
static const wchar_t* services[] =
{
L"SYSTEM\\CurrentControlSet\\Services\\VBoxService",
L"SYSTEM\\CurrentControlSet\\Services\\VBoxGuest",
L"SYSTEM\\CurrentControlSet\\Services\\VBoxMouse",
L"SYSTEM\\CurrentControlSet\\Services\\VBoxSF",
L"SYSTEM\\CurrentControlSet\\Services\\VBoxWddm",
L"SYSTEM\\CurrentControlSet\\Services\\vmci",
L"SYSTEM\\CurrentControlSet\\Services\\vmhgfs",
L"SYSTEM\\CurrentControlSet\\Services\\VMTools",
L"SYSTEM\\CurrentControlSet\\Services\\vmrawdsk",
L"SYSTEM\\CurrentControlSet\\Services\\vmusbmouse",
L"SYSTEM\\CurrentControlSet\\Services\\vm3dservice",
L"SYSTEM\\CurrentControlSet\\Services\\vmmouse",
L"SYSTEM\\CurrentControlSet\\Services\\xenvdb",
L"SYSTEM\\CurrentControlSet\\Services\\xenbus",
};
for (const wchar_t* s : services)
{
if (RegKeyExists(HKEY_LOCAL_MACHINE, s))
return true;
}
return false;
}
static bool HasVmDriversOnDisk()
{
static const wchar_t* files[] =
{
L"C:\\Windows\\System32\\drivers\\VBoxGuest.sys",
L"C:\\Windows\\System32\\drivers\\VBoxMouse.sys",
L"C:\\Windows\\System32\\drivers\\VBoxSF.sys",
L"C:\\Windows\\System32\\drivers\\vmmouse.sys",
L"C:\\Windows\\System32\\drivers\\vmhgfs.sys",
L"C:\\Windows\\System32\\drivers\\vmrawdsk.sys",
L"C:\\Windows\\System32\\drivers\\vmusbmouse.sys",
L"C:\\Windows\\System32\\VBoxService.exe",
L"C:\\Windows\\System32\\VBoxTray.exe",
};
for (const wchar_t* f : files)
{
DWORD attr = GetFileAttributesW(f);
if (attr != INVALID_FILE_ATTRIBUTES && !(attr & FILE_ATTRIBUTE_DIRECTORY))
return true;
}
return false;
}
static bool HasVmProcesses()
{
static const wchar_t* names[] =
{
L"VBoxService.exe",
L"VBoxTray.exe",
L"vmtoolsd.exe",
L"vmwaretray.exe",
L"vmwareuser.exe",
L"VGAuthService.exe",
L"qemu-ga.exe",
L"xenservice.exe",
};
HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (snap == INVALID_HANDLE_VALUE)
return false;
PROCESSENTRY32W pe{};
pe.dwSize = sizeof(pe);
bool found = false;
if (Process32First(snap, &pe))
{
do
{
for (const wchar_t* n : names)
{
if (_wcsicmp(pe.szExeFile, n) == 0)
{
found = true;
break;
}
}
if (found)
break;
} while (Process32Next(snap, &pe));
}
CloseHandle(snap);
return found;
}
// ---------------------------------------------------------------- public
bool IsVirtualMachine(std::wstring* reason)
{
auto setReason = [reason](const wchar_t* text)
{
if (reason)
*reason = text;
};
if (reason)
reason->clear();
CpuidResult cpu = QueryCpuid();
// A hypervisor bit alone is not proof: VBS / Credential Guard / Hyper-V
// on bare metal sets it too. Strong vendors are decisive.
if (cpu.hypervisorPresent)
{
const std::string vendor = cpu.vendor;
if (vendor == "VMwareVMware") { setReason(L"cpuid: VMware"); return true; }
if (vendor == "VBoxVBoxVBox") { setReason(L"cpuid: VirtualBox"); return true; }
if (vendor == "KVMKVMKVM") { setReason(L"cpuid: KVM"); return true; }
if (vendor == "XenVMMXenVMM") { setReason(L"cpuid: Xen"); return true; }
if (vendor.rfind("TCGTCGTCG", 0) == 0) { setReason(L"cpuid: QEMU TCG"); return true; }
if (vendor == "bhyve bhyve") { setReason(L"cpuid: bhyve"); return true; }
if (vendor == "VServerVServer") { setReason(L"cpuid: Virtual Server"); return true; }
}
const std::string smbios = ToLowerAscii(ReadSmbiosStrings());
if (ContainsAny(smbios, { "virtualbox", "vmware", "qemu", "kvm", "bochs", "parallels", "xen", "virtual machine", "hyper-v" }))
{
setReason(L"smbios: virtual vendor string");
return true;
}
if (cpu.hypervisorPresent && cpu.vendor == "Microsoft Hv")
{
// Hyper-V guest: confirmed by SMBIOS containing "virtual machine"
// (handled above) or by Hyper-V integration services.
if (RegKeyExists(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\vmicheartbeat"))
{
setReason(L"hyperv: integration services");
return true;
}
if (HasVirtualMac())
{
setReason(L"hyperv: virtual MAC");
return true;
}
}
std::string diskEnum = ToLowerAscii(ReadDiskEnumValue());
if (ContainsAny(diskEnum, { "vbox", "vmware", "qemu", "xen", "virtio" }))
{
setReason(L"disk enum: virtual controller");
return true;
}
if (HasVmServices())
{
setReason(L"registry: guest service installed");
return true;
}
if (HasVmDriversOnDisk())
{
setReason(L"driver: guest driver present");
return true;
}
if (HasVmProcesses())
{
setReason(L"process: guest helper running");
return true;
}
if (HasVirtualMac())
{
setReason(L"network: virtual MAC OUI");
return true;
}
return false;
}
#ifndef ARDRV_ALLOW_VM_DEFAULT
#define ARDRV_ALLOW_VM_DEFAULT 0
#endif
bool VmOverrideRequested(int argc, wchar_t** argv)
{
#if ARDRV_ALLOW_VM_DEFAULT
// Built for lab/testing images that are themselves virtual machines.
(void)argc;
(void)argv;
return true;
#endif
for (int i = 1; i < argc; ++i)
{
if (argv[i] && (_wcsicmp(argv[i], L"--allow-vm") == 0 ||
_wcsicmp(argv[i], L"-allow-vm") == 0))
{
return true;
}
}
wchar_t env[64]{};
DWORD n = GetEnvironmentVariableW(L"ARDRV_ALLOW_VM", env, _countof(env));
if (n > 0 && n < _countof(env) && (env[0] == L'1' || env[0] == L'y' || env[0] == L'Y'))
return true;
HKEY h = nullptr;
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\ArDrvLoader", 0, KEY_READ, &h) == ERROR_SUCCESS)
{
DWORD value = 0;
DWORD size = sizeof(value);
DWORD type = 0;
bool enabled =
RegQueryValueExW(h, L"AllowVm", nullptr, &type, (LPBYTE)&value, &size) == ERROR_SUCCESS &&
type == REG_DWORD &&
value != 0;
RegCloseKey(h);
if (enabled)
return true;
}
return false;
}