收集整理一下虚拟机检测相关的文章,过段时间用。
方法一
方法一:
使用RDTSC指令来判断虚拟机类型(通过指令执行的时钟周期来判断):
int Ret = 0;
__asm
{
rdtsc
xchg ecx, eax
rdtsc
sub eax, ecx
cmp eax, 0xFF
jnb DETECT
sub edx, edx
mov DWORD PTR [Ret], 0
jmp RETURN
DETECT:
sub eax, ecx
mov DWORD PTR [Ret], 1
RETURN:
}
RDTSC指令将计算机启动以来的CPU运行周期数放到EDX:EAX里面,EDX是高位,EAX是低位。 RDTSC指令还可以antidebug,实现微秒级计时器。
方法二
方法二:VMware“后门”
mov ecx, 0Ah ; CX=function# (0Ah=get_version)
mov eax, 'VMXh' ; EAX=magic
mov dx, 'VX' ; DX=magic
in eax, dx ; specially processed io cmd
; output: EAX/EBX/ECX = data
cmp ebx, 'VMXh' ; also eax/ecx modified (maybe vmw/os ver?)
je under_VMware
VMware后门开在IO端口0x5658。
利用这个后门时,必需: EAX = 0x564D5868 (“VMXh”) EBX 为参数,一般不用。 ECX 低 16 位为功能号。其实是一个函数数组的索引。 Vmware 调用对应的函数处理后门请求。 这个函数数组共有36 个元素,但某些没有定义。 ECX 的高 16 位为功能参数。 EDX = 0x5658 (“VX”),为 IO 端口号。
bool IsVMWare()
{
unsigned long _EBX;
__try
{
__asm
{
// Run the magic code sequence
push ebx
mov eax, 0x564D5868
mov ebx, 0x8685D465 // Ensure EBX doesnt contain 0x564D5868 :)
mov ecx, 10 // The command for obtaining VMWare version information
mov dx, 0x5658
in eax, dx
mov _EBX, ebx
pop ebx
};
}
__except(1)
{
// An exception occured, we aint in VMWare
return false;
}
// The code was executed successfuly, check for the magic value
return _EBX == 0x564D5868;
}
bool IsInsideVMWare()
{
bool rc = true;
__try
{
__asm
{
push edx
push ecx
push ebx
mov eax, 'VMXh'
mov ebx, 0 // any value but not the MAGIC VALUE
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' // is it a reply from VMWare?
setz [rc] // set return value
pop ebx
pop ecx
pop edx
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
rc = false;
}
return rc;
}
bool IsInsideVPC()
{
bool rc = false;
__try
{
_asm push ebx
_asm mov ebx, 0 // Flag
_asm mov eax, 1 // VPC function number
// call VPC
_asm __emit 0Fh
_asm __emit 3Fh
_asm __emit 07h
_asm __emit 0Bh
_asm test ebx, ebx
_asm setz [rc]
_asm pop ebx
}
// The except block shouldn't get triggered if VPC is running!!
__except(IsInsideVPC_exceptionFilter(GetExceptionInformation()))
{
}
return rc;
}
```asm
```c++
int DCVM ()
{
unsigned char m[2 + 4], rpill[] = "/x0f/x01/x0d/x00/x00/x00/x00/xc3";
*((unsigned *)&rpill[3]) = (unsigned)m;
((void( *)())&rpill)();
printf ("idt base: %#x/n", *((unsigned *)&m[2]));
if (m[5] > 0xd0) printf ("虚拟机/r/n", m[5]);
else printf ("真实机器/r/n");
return 0;
}
#include <stdio.h>
int LdtCheck()
{
unsigned char m[2];
__asm sldt m; //L,not i
printf("LDTR: %2.2x %2.2x/n", m[0], m[1]);
return (m[0] != 0x00 && m[1] != 0x00) ? 1 : 0;
}
int main(int argc, char *argv[])
{
if (LdtCheck())
printf("Virtual Machine detected./n");
else
printf("Native machine detected./n");
return 0;
}
#include <stdio.h>inline int idtCheck ()
{
unsigned char m[2];
__asm sidt m;
printf("IDTR: %2.2x %2.2x/n", m[0], m[1]);
return (m[1] > 0xd0) ? 1 : 0;
}
int gdtCheck()
{
unsigned char m[2];
__asm sgdt m;
printf("GDTR: %2.2x %2.2x/n", m[0], m[1]);
return (m[1] > 0xd0) ? 1 : 0;
}
int ldtCheck()
{
unsigned char m[2];
__asm sldt m;
printf("LDTR: %2.2x %2.2x/n", m[0], m[1]);
return (m[0] != 0x00 && m[1] != 0x00) ? 1 : 0;
}
int main(int argc, char *argv[])
{
idtCheck();
gdtCheck();
if (ldtCheck())
printf("Virtual Machine detected./n");
else
printf("Native machine detected./n");
return 0;
}</stdio.h> </stdio.h>
方法三:环境内进程检测
//是否包含某进程
BOOL IsContainsProcess(CString strProName)
{
PROCESSENTRY32 pe32; //定义结构体变量来保存进程的信息
pe32.dwSize = sizeof(pe32); //填充大小
HANDLE hProcessSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); //创建快照
if (hProcessSnap == INVALID_HANDLE_VALUE)
{
//MessageBox("进程快照失败","提示",MB_OK);
exit(1);
}
//遍历所有快照
BOOL bMore = ::Process32First(hProcessSnap, &pe32);
while(bMore)
{
if (strProName == pe32.szExeFile)
{
return TRUE; //如果存在该进程,则返回TRUE
bMore = FALSE; //停止循环
}
else
{
bMore =::Process32Next(hProcessSnap, &pe32);
}
}
//扫尾
CloseHandle(hProcessSnap);
return FALSE;
}
//程序启动时刻
if (
(IsContainsProcess("VBoxTray.exe")) ||
(IsContainsProcess("VBoxService.exe")) ||
(IsContainsProcess("VMwareUser.exe")) ||
(IsContainsProcess("VMwareTray.exe")) ||
(IsContainsProcess("VMUpgradeHelper.exe")) ||
(IsContainsProcess("vmtoolsd.exe")) ||
(IsContainsProcess("vmacthlp.exe"))
)
{
AfxMessageBox("请不要在虚拟机中运行该程序");
exit(0);
}
方法四
方法四:windows主机检查注册表键值 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet等键值是否包含常见虚拟机的键值
方法五
方法五:检查CPUID/硬盘型号/主板型号 参考代码如下,适用没有做过硬件名称修改的虚拟机: 如果使用的是 VMware/Xen HVM/KVM 这样的全虚拟就更难判断一些,最准确的办法是读取 CPUID 来判断,Xen 源代码下面有一段检测是否是 Xen 的 C 语言代码 tools/misc/xen-detect.c,这段代码提供了一个很好的例子,重写了代码,用宏替代了函数,增加了对 VMware 和 KVM 的识别,用 gcc 编译后就可以运行:
/*
* check if a linux system running on a virtual machine (vmware/xen hvm/kvm)
*/
#include stdio.h
#include string.h
#define HYPERVISOR_INFO 0×40000000
#define CPUID(idx, eax, ebx, ecx, edx)
asm volatile (
"test % 1, % 1 ; jz 1f ; ud2a ; .ascii "xen" ; 1: cpuid"
: " = b" (*ebx), " = a" (*eax), " = c" (*ecx), " = d" (*edx)
: "0″ (idx) );
int main(void)
{
unsigned int eax, ebx, ecx, edx;
char string[13];
CPUID(HYPERVISOR_INFO, &eax, &ebx, &ecx, &edx);
*(unsigned int *)(string + 0) = ebx;
*(unsigned int *)(string + 4) = ecx;
*(unsigned int *)(string + 8) = edx;
string[12] = 0;
if (strncmp(string, "XenVMMXenVMM", 12) == 0)
{
printf("xen hvmn");
}
else if (strncmp(string, "VMwareVMware", 12) == 0)
{
printf("vmwaren");
}
else if (strncmp(string, "KVMKVMKVM", 12) == 0)
{
printf("kvmn");
}
else
printf("bare hardwaren");
return 0;
使用wmi检查硬盘型号是否包含VMWARE字符串
Dim $VFlag = True
Dim $obj = ObjGet("winmgmts:\\localhost\root\CIMV2")
Dim $objItem = $obj.ExecQuery("SELECT * FROM Win32_DiskDrive", "WQL", 0x10 + 0x20)
If IsObj($objItem) Then
For $Item In $objItem
If StringInStr($Item.Model, "VMWARE") Then
$VFlag = False
ExitLoop
EndIf
Next
If $VFlag Then
MsgBox(0, "", "NOT VMWARE")
Else
MsgBox(0, "", "IS VMWARE")
EndIf
Else
MsgBox(0, "error", "NO obj")
EndIf
组合起来的方法
$a = _CheckVM()
If $a = "" Then
MsgBox(0, "我不在虚拟机里", "我不在虚拟机里!")
Else
MsgBox(0, "我在虚拟机里!", "我在虚拟机里,我的理由是" & @CRLF & @CRLF & $a)
EndIf
;检查是否运行于虚拟机环境。返回空值说明运行于真实环境,返回一个字符串,说明运行于虚拟机环境并给出解释。
;方法:检查虚拟机服务/进程,硬盘,BIOS 主板/芯片组
;发现2个以上即确定为虚拟机环境
Func _CheckVM()
$strComputer = '.'
$objWMIService = ObjGet('winmgmts:\\' & $strComputer & '\root\cimv2')
$vmhit_count = 0
$vmhit_details = ""
; 检查虚拟机管理程序
If ProcessExists("VBoxService.exe") Or ProcessExists("VBoxTray.exe") Or ProcessExists("VMwareTray.exe") Or ProcessExists("VMwareUser.exe") Then _AddVMHit($vmhit_count, $vmhit_details, "RUNNING SOFTWARE", "Found a Vbox or VMware guest OS service or tray process")
; 检查虚拟机设备
If Not IsObj($objWMIService) Then
MsgBox(0, "", "? WTF?")
Return ""
EndIf
; 检查虚拟机硬盘
$colItems = $objWMIService.ExecQuery('SELECT * FROM Win32_DiskDrive', 'WQL', 0x10 + 0x20)
If IsObj($colItems) Then
For $objItem In $colItems
$vReturn = $objItem.Model
Select
Case StringInStr($vReturn, "VBOX HARDDISK")
_AddVMHit($vmhit_count, $vmhit_details, "DISKS", "Found device ""VBOX HARDDISK""")
Case StringInStr($vReturn, "QEMU HARDDISK")
_AddVMHit($vmhit_count, $vmhit_details, "DISKS", "Found device ""QEMU HARDDISK""")
Case StringInStr($vReturn, "VMWARE VIRTUAL IDE HARD DRIVE")
_AddVMHit($vmhit_count, $vmhit_details, "DISKS", "Found device ""VMWARE VIRTUAL IDE HARD DRIVE""")
Case StringInStr($vReturn, "VMWARE Virtual S SCSI Disk Device")
_AddVMHit($vmhit_count, $vmhit_details, "DISKS", "Found device ""VMWARE Virtual S SCSI Disk Device""")
EndSelect
Next
EndIf
; 检查虚拟机BIOS
$colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_BIOS", "WQL", 0x10 + 0x20)
If IsObj($colItems) Then
For $objItem In $colItems
Select
Case StringInStr($objItem.BIOSVersion(0), "Vbox")
_AddVMHit($vmhit_count, $vmhit_details, "BIOS", "Found Vbox BIOS version")
Case StringInStr($objItem.SMBIOSBIOSVersion, "virt")
_AddVMHit($vmhit_count, $vmhit_details, "BIOS", "Found Vbox BIOS version")
EndSelect
Next
EndIf
; 检查虚拟机主板/芯片组
$colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_Baseboard", "WQL", 0x10 + 0x20)
If IsObj($colItems) Then
For $objItem In $colItems
Select
Case StringInStr($objItem.Name, "Base Board") And StringInStr($objItem.Product, "440BX Desktop Reference Platform")
_AddVMHit($vmhit_count, $vmhit_details, "MOTHERBOARD", "Found VMware-style motherboard, ""440BX Desktop Reference Platform"" / Name=""Base Board""")
EndSelect
Next
EndIf
If $vmhit_count >= 2 Then
Return $vmhit_details & @CRLF & @CRLF & "Hits in " & $vmhit_count & " of 4 hardware categories - probably a virtual machine."
Else
Return ""
EndIf
EndFunc ;==>_CheckVM
Func _AddVMHit(ByRef $vmhit_count, ByRef $vmhit_details, $this_hit_category, $this_hit_text)
If StringInStr($vmhit_details, "In CATEGORY:" & $this_hit_category & ":") Then
$vmhit_details &= " and " & $this_hit_text
Else
If $vmhit_details > "" Then $vmhit_details &= @CRLF
$vmhit_details &= "In CATEGORY:" & $this_hit_category & ": " & $this_hit_text
$vmhit_count += 1
EndIf
EndFunc ;==>_AddVMHit
Opt("MustDeclareVars", 1)
If _VCheck() Then
MsgBox(0, "", "True")
Else
MsgBox(0, "", "False")
EndIf
Func _VCheck()
Local $strComputer = ".", $sMake, $sModel, $sBIOSVersion, $bIsVM, $sVMPlatform
Local $objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\CIMV2")
Local $colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_ComputerSystem")
If IsObj($colItems) Then
For $objItem In $colItems
;MsgBox(0,"","Name: " & $objItem.Name)
$sMake = $objItem.Manufacturer
$sModel = $objItem.Model
Next
EndIf
$colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_BIOS", "WQL", 0x10 + 0x20)
If IsObj($colItems) Then
For $objItem In $colItems
;MsgBox(0,"",$objItem.BIOSVersion(0))
$sBIOSVersion = $objItem.SMBIOSBIOSVersion
Next
EndIf
$bIsVM = False
$sVMPlatform = ""
MsgBox(0, "", "Manufacturer=" & $sMake)
MsgBox(0, "", "Model=" & $sModel)
MsgBox(0, "", "BIOSVersion=" & $sBIOSVersion)
If $sModel = "Virtual Machine" Then
; Microsoft virtualization technology detected, assign defaults
$sVMPlatform = "Hyper-V"
$bIsVM = True
; Try to determine more specific values
Switch $sBIOSVersion
Case "VRTUAL - 1000831"
$bIsVM = True
$sVMPlatform = "Hyper-V 2008 Beta or RC0"
Case "VRTUAL - 5000805", "BIOS Date: 05/05/08 20:35:56 Ver: 08.00.02"
$bIsVM = True
$sVMPlatform = "Hyper-V 2008 RTM"
Case "VRTUAL - 3000919"
$bIsVM = True
$sVMPlatform = "Hyper-V 2008 R2"
Case "A M I - 2000622"
$bIsVM = True
$sVMPlatform = "VS2005R2SP1 or VPC2007"
Case "A M I - 9000520"
$bIsVM = True
$sVMPlatform = "VS2005R2"
Case "A M I - 9000816", "A M I - 6000901"
$bIsVM = True
$sVMPlatform = "Windows Virtual PC"
Case "A M I - 8000314"
$bIsVM = True
$sVMPlatform = "VS2005 or VPC2004"
EndSwitch
ElseIf $sModel = "VMware Virtual Platform" Then
; VMware detected
$sVMPlatform = "VMware"
$bIsVM = True
ElseIf $sModel = "VirtualBox" Then
; VirtualBox detected
$bIsVM = True
$sVMPlatform = "VirtualBox"
Else
EndIf
If $bIsVM Then
MsgBox(0, "", "IsVirtualMachine=True")
MsgBox(0, "", "VirtualMachinePlatform=" & $sVMPlatform)
Else
MsgBox(0, "", "IsVirtualMachine=False")
EndIf
Return $bIsVM
EndFunc ;==>_VCheck
特别感谢以下资料出处: