检测虚拟机环境
今天在写程序时,不想让这个程序在虚拟机上运行
于是尝试了一下代码:
注册表和硬件检测
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| #include <stdio.h> #include <windows.h>
BOOL CheckRegistry(); BOOL CheckHardware();
int main() { if (CheckRegistry() || CheckHardware()) { printf("可能运行在虚拟机中。\n"); } else { printf("未检测到虚拟机。\n"); } return 0; }
BOOL CheckRegistry() { HKEY hKey; LONG lResult; DWORD dwType, dwSize; char szBuffer[256];
lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\VMware, Inc.\\VMware Tools", 0, KEY_READ, &hKey); if (lResult == ERROR_SUCCESS) { RegCloseKey(hKey); return TRUE; }
lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Oracle\\VirtualBox Guest Additions", 0, KEY_READ, &hKey); if (lResult == ERROR_SUCCESS) { RegCloseKey(hKey); return TRUE; }
return FALSE; }
BOOL CheckHardware() { SYSTEM_INFO sysInfo; GetSystemInfo(&sysInfo);
if (sysInfo.dwNumberOfProcessors <= 1) { return TRUE; }
MEMORYSTATUSEX memInfo; memInfo.dwLength = sizeof(memInfo); GlobalMemoryStatusEx(&memInfo); if (memInfo.ullTotalPhys < 1024 * 1024 * 1024) { return TRUE; }
return FALSE; }
|
CheckRegistry函数:检查系统注册表中是否存在与虚拟机相关的注册表项。例如,VMware和VirtualBox在安装时会在注册表中添加特定的项。
CheckHardware函数:检查系统的硬件信息,如处理器数量和物理内存大小。虚拟机通常具有较少的处理器和较小的内存。
缺陷
虚拟机可能会隐藏特征来避免被检测,在实际操作中,检测注册表确实没法判断成功程序所在环境为虚拟机,仍然能运行成功。
GPU检测
突然想到了在打开任务管理器时,主机会显示GPU,而虚拟机不会显示GPU
主机:
虚拟机Win11:
虚拟机Win10:
检测GPU信息
但是在使用程序检测GPU时,仍然在虚拟机中检测出:
但是,这里发现GPU有很明显的特征,适配器名称有VMware字段
所以,获取到GPU信息后,匹配一下适配器名称中有没有VMware或者VirtualBox字段
代码实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| int containsSubstring(const char* str, const char* substr) { char lowerStr[128]; char lowerSubstr[128]; int i;
for (i = 0; str[i] && i < 127; i++) { lowerStr[i] = tolower((unsigned char)str[i]); } lowerStr[i] = '\0';
for (i = 0; substr[i] && i < 127; i++) { lowerSubstr[i] = tolower((unsigned char)substr[i]); } lowerSubstr[i] = '\0';
return strstr(lowerStr, lowerSubstr) != NULL; }
DWORD WINAPI GPUProcDetect(LPVOID lpParameter) { IDirect3D9* pD3D = Direct3DCreate9(D3D_SDK_VERSION); if (pD3D == NULL) { printf("Direct3D 初始化失败\n"); return 1; }
D3DADAPTER_IDENTIFIER9 adapterIdentifier; HRESULT hr = pD3D->GetAdapterIdentifier(D3DADAPTER_DEFAULT, 0, &adapterIdentifier); if (FAILED(hr)) { printf("获取适配器信息失败\n"); pD3D->Release(); exit(1); }
if (containsSubstring(adapterIdentifier.Description, "vmware") || containsSubstring(adapterIdentifier.Description, "virtualbox")) { printf("检测到虚拟机环境,程序将退出。\n"); pD3D->Release(); Sleep(3000); exit(1); }
pD3D->Release();
return 0; }
|

这也只是一种现在比较可行的简单的检测方法,不保证可能厂商以后把这个特征也抹除