C++ 如何检测您的应用程序正在运行的虚拟机是焦点

use*_*612 6 c++ focus virtual-machine detect

我有 2 个应用程序,每个应用程序都在各自独立的 MS Windows 7 虚拟机 (VM) 上运行。我无法为主机编写软件作为解决方案的一部分。我正在使用 Qt 使用 C++ 进行编码。

这可能不可能,但我希望能够检测虚拟机窗口何时具有焦点(不是应用程序窗口,而是虚拟机)。这两个应用程序都是全屏应用程序(至少在虚拟机内全屏),始终具有应用程序窗口焦点,但我希望能够在用户的键盘输入敲击键盘之前检测到他们将进入哪个虚拟机。钥匙。

有任何想法吗?

小智 7

没有 100% 的方法来识别 VM 与否。但有一些“指标”:

\n
    \n
  • 特定的“设备”、驱动程序、服务(vmmouse.sys、vmci、VBoxService.exe 等)
  • \n
  • 特定注册表项、Windows 产品 ID、MAC 地址
  • \n
\n

所有这些方法都不可靠,但被广泛使用。

\n

VMware 提供了官方记录的虚拟机检测方法(带有代码片段)。\n有一种方法基于使用虚拟机管理程序端口 0x5658(“VX”)和虚拟机管理程序魔术 DWORD 0x564D5868(代表“VMXh”)

\n
bool IsVMWare()\n{\n  bool res = true;\n\n  __try\n  {\n    __asm\n    {\n      push   edx\n      push   ecx\n      push   ebx\n\n      mov    eax, \'VMXh\'\n      mov    ebx, 0 \n      mov    ecx, 10 // get VMWare version\n      mov    edx, \'VX\' // port number\n\n      in     eax, dx // read port\n                     // on return EAX returns the VERSION\n                     \n      cmp    ebx, \'VMXh\' // compare with target\n      setz   [res] // set return value\n\n      pop    ebx\n      pop    ecx\n      pop    edx\n    }\n  }\n  __except(EXCEPTION_EXECUTE_HANDLER)\n  {\n    res = false;\n  }\n\n  return res;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

另一种方法是测试 CPUID 管理程序 (HV) 存在位和 HV 供应商的名称:

\n
bool IsVM()\n{\n    int cpuInfo[4] = {};\n\n    //\n    // Upon execution, code should check bit 31 of register ECX\n    // (the \xe2\x80\x9chypervisor present bit\xe2\x80\x9d). If this bit is set, a hypervisor is present.\n    // In a non-virtualized environment, the bit will be clear.\n    //\n    __cpuid(cpuInfo, 1);\n    \n\n    if (!(cpuInfo[2] & (1 << 31)))\n        return false;\n    \n    //\n    // A hypervisor is running on the machine. Query the vendor id.\n    //\n    const auto queryVendorIdMagic = 0x40000000;\n    __cpuid(cpuInfo, queryVendorIdMagic);\n\n    const int vendorIdLength = 13;\n    using VendorIdStr = char[vendorIdLength];\n\n    VendorIdStr hyperVendorId = {};\n    \n    memcpy(hyperVendorId + 0, &cpuInfo[1], 4);\n    memcpy(hyperVendorId + 4, &cpuInfo[2], 4);\n    memcpy(hyperVendorId + 8, &cpuInfo[3], 4);\n    hyperVendorId[12] = \'\\0\';\n\n    static const VendorIdStr vendors[]{\n    "KVMKVMKVM\\0\\0\\0", // KVM \n    "Microsoft Hv",    // Microsoft Hyper-V or Windows Virtual PC */\n    "VMwareVMware",    // VMware \n    "XenVMMXenVMM",    // Xen \n    "prl hyperv  ",    // Parallels\n    "VBoxVBoxVBox"     // VirtualBox \n    };\n\n    for (const auto& vendor : vendors)\n    {\n        if (!memcmp(vendor, hyperVendorId, vendorIdLength))\n            return true;\n    }\n\n    return false;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

一些硬件检测方法的实现依赖于VM如何模拟CPU行为。例如,使用缓存指令,如wbinvdinvd,但它们是特权的。

\n

一些阅读更多内容的链接:

\n

有一篇关于虚拟机和沙箱检测的有趣文章有趣文章以及一些代码示例。

\n

我找到了一个存储库,其中包含一些用 C 实现的方法。其中一些只能在 Windows 上使用,但也有一些跨平台的方法

\n


Mic*_*ati 1

那段代码应该可以完成工作

BOOL IsVMRunning()
{
#if _WIN64
    UINT64 time1 = __rdtsc();
    UINT64 time2 = __rdtsc();
    return ((time2 - time1) > 500);
#else
    unsigned int time1 = 0;
    unsigned int time2 = 0;
    __asm
    {
        RDTSC
        MOV time1, EAX
        RDTSC
        MOV time2, EAX
    }
    return ((time2 - time1) > 500);
#endif
}
Run Code Online (Sandbox Code Playgroud)