我有两个应用程序,每个程序都运行在各自独立的MS Windows 7虚拟机(VM)上。我不能为主机编写软件作为解决方案的一部分。我用C++编写Qt代码。 这可能是不可能的,但我希望能够检测VM窗口何时具有焦点(不是应用程序窗口,而是VM)。这两个应用程序都是全屏应用程序(至少在VM中是全屏),它们始终具有应用程序窗口焦点,但我希望能够在用户按键之前检测到用户的键盘输入将要转到哪个VM。 有什么想法吗
bool IsVMWare()
{
bool res = true;
__try
{
__asm
{
push edx
push ecx
push ebx
mov eax, 'VMXh'
mov ebx, 0
mov ecx, 10 // get VMWare version
mov edx, 'VX' // port number
in eax, dx // read port
// on return EAX returns the VERSION
cmp ebx, 'VMXh' // compare with target
setz [res] // set return value
pop ebx
pop ecx
pop edx
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
res = false;
}
return res;
}
另一种方法是测试CPUID管理程序(HV)存在位和HV供应商的名称:
bool IsVM()
{
int cpuInfo[4] = {};
//
// Upon execution, code should check bit 31 of register ECX
// (the “hypervisor present bit”). If this bit is set, a hypervisor is present.
// In a non-virtualized environment, the bit will be clear.
//
__cpuid(cpuInfo, 1);
if (!(cpuInfo[2] & (1 << 31)))
return false;
//
// A hypervisor is running on the machine. Query the vendor id.
//
const auto queryVendorIdMagic = 0x40000000;
__cpuid(cpuInfo, queryVendorIdMagic);
const int vendorIdLength = 13;
using VendorIdStr = char[vendorIdLength];
VendorIdStr hyperVendorId = {};
memcpy(hyperVendorId + 0, &cpuInfo[1], 4);
memcpy(hyperVendorId + 4, &cpuInfo[2], 4);
memcpy(hyperVendorId + 8, &cpuInfo[3], 4);
hyperVendorId[12] = '\0';
static const VendorIdStr vendors[]{
"KVMKVMKVM\0\0\0", // KVM
"Microsoft Hv", // Microsoft Hyper-V or Windows Virtual PC */
"VMwareVMware", // VMware
"XenVMMXenVMM", // Xen
"prl hyperv ", // Parallels
"VBoxVBoxVBox" // VirtualBox
};
for (const auto& vendor : vendors)
{
if (!memcmp(vendor, hyperVendorId, vendorIdLength))
return true;
}
return false;
}
2条答案
按热度按时间4ioopgfo1#
没有100%的方法来识别VM。但有一些“指标”:
所有这些方法都不可靠,但被广泛使用。
VMware提供了正式记录的VM检测方法is here, (with code snippets)。有一种方法是基于使用虚拟机管理程序端口0x5658(“VX”)和虚拟机管理程序魔术DWORD 0x564D5868,它代表“VMXh”
另一种方法是测试CPUID管理程序(HV)存在位和HV供应商的名称:
实现的一些硬件检测方法依赖于VM如何模拟CPU行为的事实。例如,使用缓存指令,如 wbinvd 和 invd,但它们是特权的。
一些链接阅读更多:
这里有一篇有趣的文章about VM & Sandbox detection,里面有一些代码示例。
我发现了一个repository,其中一些方法是用C实现的。其中一些只能在Windows上使用,但也有一些跨平台的
zengzsys2#
这段代码应该可以完成这项工作