我是虚拟机世界中的初学者,并且有一个小问题。如果软件在VM上运行(例如VMware Player),它如何知道它是在VM上安装的?软件是从操作系统中获取信息吗?还是软件和硬件(VMware Player)之间的直接通信?预先感谢
不幸的是没有唯一的答案。每台虚拟机都有一种可以使用的桥梁,但是您必须为要检测到的每个VM编写特定的检查(示例是VC 特定的,但您可以轻松地将其调整为编译器)。请注意,在理论中,您应该无法确定是否在VM下运行。
VMware
VMware使用IN
指令来处理来宾进行托管通信。通常,此说明在用户模式中不可用,并且会引发异常,但VM处理它。如果我们捕获异常,那么我们知道我们不是在VMware下运行的(或者我们有权执行IN
指令)。第二个测试以确定我们是否具有特权或在WMware下运行的第二个测试几乎没有用,但这是 standard 检测代码,我在此处写入它(我们只检查了预期的 string VMXh
在EBX
寄存器中,请注意,我们必须初始化一些具有所需值的寄存器。)
bool IsRunningInsideVmWare()
{
bool flag = true;
__try
{
__asm
{
push edx
push ecx
push ebx
mov eax, 'VMXh'
mov ebx, 0
mov ecx, 10
mov edx, 'VX'
in eax, dx
cmp ebx, 'VMXh'
setz [flag]
pop ebx
pop ecx
pop edx
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
flag = false;
}
return flag;
}
虚拟PC
访客可以使用不存在的指令0f3f070b
与主机进行通信,您可以做的是发出此类指令,VM可以正确解释它,但是物理CPU会引发异常(您可以捕获并跳过有问题的指令)。在此示例中,我们将EBX
设置为异常处理程序中的已知值,然后我们可以检测到此情况。
DWORD __forceinline VpcExceptionFilter(LPEXCEPTION_POINTERS ep)
{
ep->ContextRecord->ctx->Ebx = -1;
ep->ContextRecord->ctx->Eip += 4;
return EXCEPTION_CONTINUE_EXECUTION;
}
bool IsRunningInsideVpc()
{
bool flag = false;
__try
{
_asm
{
push ebx
mov eax, 1
mov ebx, 0
__emit 0Fh
__emit 3Fh
__emit 07h
__emit 0Bh
test ebx, ebx
setz [flag]
pop ebx
}
}
__except(VpcExceptionFilter(GetExceptionInformation()))
{
}
return flag;
}
虚拟盒
要检测VirtualBox非常简单,您只需要检查伪设备\.VBoxMiniRdrDN
是否存在:
bool IsRunningInsideVirtualBox()
{
HANDLE handle = CreateFile("\\.\VBoxMiniRdrDN", GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (handle != INVALID_HANDLE_VALUE)
{
CloseHandle(handle);
return true;
}
return false;
}
使用WMI和以下查询可以完成一些更通用的事情(假设:您正在Windows上运行):
- 在
Win32_BaseBoard
中与(?i)(Hyper-V|Virtual Machine|Microsoft|VMware|VirtualBox|Parallels Virtual)
匹配Name
。 - 在
Win32_ComputerSystem
中匹配Model
和Manufacturer
与(?i)(Hyper-V|Virtual Machine|VMware|VirtualBox)
。 - 在
Win32_VideoController
中匹配Name
与(?i)Hyper-V
。
CPUID
指令也可以帮助您(当支持这些值时)。
使用EAX
设置为0(获取供应商ID ),您可以进入EBX
,EDX
和ECX
带有CPU供应商名称的ASCII字符串(请参阅list Wikipedia)。当然,VM可以返回错误的名称,也可能是未知的VM。
将ECX
( Hypervisor )的EAX
设置为1(处理器信息和功能位)位,如果您在VM下运行,则将设置为1。同样,VM可能会返回一个错误的结果(有些VM不荣幸)。
当我不得不使用此问题时,我也尝试检查VM中不支持的硬件技巧/功能(例如,对USB传统支持),但我发现它不够可靠用于生产。
在评论中,您说您正在使用Android。这是一个完全不同的故事,但是 common 技术类似于我对WMI(或上述组合)所说的。一种常见的方法是检查设备名称字符串中的众所周知的仿真器,从Android 7中有一个特定的标志ro.kernel.qemu
。
您可以伪造那些值吗?是的,例如,看到有没有办法将ro.kernel.qemu设置为模拟器中的0?请注意,任何旨在阻止您在仿真下使用它的体面应用程序也将使用多个检测技术(另请参见Android:以编程方式获取硬件信息)。
我认为只要它正常运行,它对于该软件的运行都不重要。
如果您真的想检查是否正在运行(或您的自写代码)在VM上运行。在Windows情况下,可以检查设备管理器(Windows Case)中的硬件,因为VM应用程序创建了一些虚拟硬件。例如,VMWare
将创建一些名为VMware ...设备的硬件。