64位Windows VMware检测

bug*_*gra 9 vmware 64-bit assembly detection visual-c++

我正在尝试开发一个应用程序,它检测程序是否在虚拟机内运行.

对于32位Windows,已经有方法下面的链接解释说: http://www.codeproject.com/Articles/9823/Detect-if-your-program-is-running-inside-a-Virtual

我正在尝试在64位Windows操作系统中调整有关Virtual PC和VMware检测的代码.对于VMware,代码可以在Windows XP 64位操作系统中成功检测到.但是当我在本机系统(Windows 7 64位操作系统)中运行程序时程序崩溃了.

我将代码放在.asm文件中,并使用ml64.exe文件定义自定义生成步骤.64位Windows的asm代码是:

IsInsideVM proc

      push   rdx
      push   rcx
      push   rbx

      mov    rax, 'VMXh'
      mov    rbx, 0     ; any value but not the MAGIC VALUE
      mov    rcx, 10    ; get VMWare version
      mov    rdx, 'VX'  ; port number

      in     rax, dx    ; read port
                        ; on return EAX returns the VERSION
      cmp    rbx, 'VMXh'; is it a reply from VMWare?
      setz   al         ; set return value
      movzx rax,al

      pop    rbx
      pop    rcx
      pop    rdx

      ret
IsInsideVM endp
Run Code Online (Sandbox Code Playgroud)

我将这部分称为cpp文件,如:

__try
{
returnValue = IsInsideVM();
}
__except(1)
{
    returnValue = false;
}
Run Code Online (Sandbox Code Playgroud)

提前致谢.

pep*_*ico 4

乔安娜的旧红色药丸可能有效:invisiblethings.org 博客的随机备份页面

吞下红色药丸或多或少相当于以下代码(在矩阵中返回非零):

 int swallow_redpill () {
   unsigned char m[2+4], rpill[] = "\x0f\x01\x0d\x00\x00\x00\x00\xc3";
   *((unsigned*)&rpill[3]) = (unsigned)m;
   ((void(*)())&rpill)();
   return (m[5]>0xd0) ? 1 : 0;
 }
Run Code Online (Sandbox Code Playgroud)

这段代码的核心实际上是SIDT指令(编码为0F010D[addr]),它将中断描述符表寄存器(ID​​TR)的内容存储在目标操作数中,目标操作数实际上是一个内存位置。SIDT指令的特殊和有趣之处在于,它可以在非特权模式(ring3)下执行,但它返回敏感寄存器的内容,由操作系统内部使用。

由于只有一个IDTR寄存器,但至少有两个操作系统同时运行(即主机和客户操作系统),因此VMM需要将客户的IDTR重新定位到安全的地方,以免与主机的IDTR发生冲突。不幸的是,VMM 无法知道来宾操作系统中运行的进程是否(以及何时)执行 SIDT 指令,因为它没有特权(并且不会生成异常)。这样进程就得到了IDT表的重定位地址。据观察,在 VMWare 上,IDT 的重定位地址位于地址 0xffXXXXXX,而在 Virtual PC 上则为 0xe8XXXXXX。这是在 VMWare Workstation 4 和 Virtual PC 2004 上进行测试的,两者都运行在 Windows XP 主机操作系统上。

注意:我自己还没有测试过它,但看起来它使用了非特权方法。如果它一开始不适用于 x64,一些调整可能会有所帮助。

另外,刚刚发现一个问题,其内容可能对您有帮助:Detecting VMM on linux