我正在尝试开发一个应用程序来检测程序是否在虚拟机内运行。
对于32位Windows,已经有方法在以下链接中解释:http://www.codeproject.com/Articles/9823/Detect-if-your-program-is-running-inside-a-Virtual 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
我在 cpp 文件中将此部分称为:
__try
{
returnValue = IsInsideVM();
}
__except(1)
{
returnValue = false;
}
提前致谢。
The old red pill from Joanna http://en.wikipedia.org/wiki/Joanna_Rutkowska可能有效:invalidthings.org 博客的随机备份页面 http://www.ouah.org/Red_%20Pill.html:
吞下红色药丸或多或少相当于以下代码(在矩阵中返回非零):
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;
}
这段代码的核心实际上是 SIDT 指令(编码为 0F010D[addr]),它将中断描述符表寄存器(IDTR)的内容存储在目标操作数中,目标操作数实际上是一个内存位置。 SIDT指令的特殊和有趣之处在于,它可以在非特权模式(ring3)下执行,但它返回敏感寄存器的内容,由操作系统内部使用。
由于只有一个 IDTR 寄存器,但至少有两个操作系统同时运行(即主机和客户操作系统),因此 VMM 需要将客户的 IDTR 重新定位到安全的地方,以免与主机的 IDTR 发生冲突。不幸的是,VMM 无法知道来宾操作系统中运行的进程是否(以及何时)执行 SIDT 指令,因为它没有特权(并且不会生成异常)。这样进程就得到了IDT表的重定位地址。据观察,在 VMWare 上,IDT 的重定位地址位于地址 0xffXXXXXX,而在 Virtual PC 上则为 0xe8XXXXXX。这是在 VMWare Workstation 4 和 Virtual PC 2004 上进行测试的,两者都运行在 Windows XP 主机操作系统上。
注意:我自己还没有测试过它,但看起来它使用了非特权方法。如果它一开始不适用于 x64,一些调整可能会有所帮助。
另外,刚刚发现一个问题,内容可能对您有帮助:在 Linux 上检测 VMM https://stackoverflow.com/q/3668804/1000282
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)