收集整理一下虚拟机检测相关的文章,过段时间用。

方法一

方法一:

使用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

特别感谢以下资料出处: