一篇文章带你了解反虚拟机技术

VMware痕迹

  • 1.检测Mac地址,以00:05:69、00:0c:29和00:50:56开始的MAC地址与VMware相对应;以00:03:ff开始的MAC地址与virtualpc对应;以08:00:27开始的MAC地址与virtualbox对应。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    BOOL CheckVMWare()
    {
    string mac;
    get_3part_mac(mac); //res =ioctl(sock,SIOCGIFHWADDR,&ifr)获取Mac地址
    if (mac=="00-05-69" || mac=="00-0c-29" || mac=="00-50-56"||mac=="00-03-ff"||mac=="08-00-27)
    {
    return TRUE;
    }
    else
    {
    return FALSE;
    }
    }
  • 2.板序列号、主机型号、系统盘所在磁盘名称等其他硬件信息

  • 3.根据当前进程信息,通过进程快照读取当前进程信息,查找是否存在虚拟机中特有的进程,如VMware中的vmware.exe和VirtualBox中的VBoxService.exe

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    BOOL CheckVMWare()
    {
    DWORD ret = 0;
    PROCESSENTRY32 pe32;
    pe32.dwSize = sizeof(pe32);
    HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if(hProcessSnap == INVALID_HANDLE_VALUE)
    {
    return FALSE;
    }
    BOOL bMore = Process32First(hProcessSnap, &pe32);
    while(bMore)
    {
    if (!strcmp(pe32.szExeFile, "vmware.exe")||!strcmp(pe32.szExeFile, "VBoxService.exe"))
    {
    return TRUE;
    }
    bMore = Process32Next(hProcessSnap, &pe32);
    }
    CloseHandle(hProcessSnap);
    return FALSE;
    }
  • 4.根据特定的文件夹或文件信息,通过查找磁盘中是否存在特定的文件夹或文件,判断当前是否在虚拟机中。VMware虚拟机中通常会有路径C:\Program Files\VMware\VMware Tools\;VirtualBox虚拟机中通常会有路径C:\Program Files\Oracle\VirtualBox Guest Additions\。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    BOOL CheckVMware()
    {
    if (!PathIsDirectory("C:\\Program Files\\VMware\\VMware Tools\\")||!PathIsDirectory("C:\\Program Files\\Oracle\\VirtualBox Guest Additions\\") )
    {
    return FALSE;
    }
    else
    {
    return TRUE;
    }
    }
  • 5.根据特定注册表信息,通过读取主机具有虚拟机特性的注册表位置来判断是否处于虚拟机环境中。针对VMware可以判断注册表项HKEY_CLASSES_ROOT\Applications\VMwareHostOpen.exe;针对VirtualBox可以判断注册表项HKEY_LOCAL_MACHINE\SOFTWARE\Oracle\VirtualBox Guest Additions。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    BOOL CheckVMWare()
    {
    HKEY hkey;
    if (RegOpenKey(HKEY_CLASSES_ROOT, "\\Applications\\VMwareHostOpen.exe", &hkey) == ERROR_SUCCESS)
    {
    return TRUE;
    }
    else
    {
    return FALSE;
    }
    }
  • 6.根据特定服务名,通过获取主机当前具有VMware特性的服务信息,判断当前主机是否为虚拟机。在VMware中通常会存在VMware物理磁盘助手服务和VMware Tools服务等;在VirtualBox中通常会存在VirtualBox Guest Additions Service服务等。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    BOOL CheckVMWare()
    {
    int menu = 0;
    //打开系统服务控制器
    SC_HANDLE SCMan = OpenSCManager(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
    if(SCMan == NULL)
    {
    cout << GetLastError() << endl;
    printf("OpenSCManager Eorror/n");
    return -1;
    }
    //保存系统服务的结构
    LPENUM_SERVICE_STATUSA service_status;
    DWORD cbBytesNeeded = NULL;
    DWORD ServicesReturned = NULL;
    DWORD ResumeHandle = NULL;
    service_status = (LPENUM_SERVICE_STATUSA)LocalAlloc(LPTR, 1024 * 64);
    //获取系统服务的简单信息
    bool ESS = EnumServicesStatusA(SCMan, //系统服务句柄
    SERVICE_WIN32, //服务的类型
    SERVICE_STATE_ALL, //服务的状态
    (LPENUM_SERVICE_STATUSA)service_status, //输出参数,系统服务的结构
    1024 * 64, //结构的大小
    &cbBytesNeeded, //输出参数,接收返回所需的服务
    &ServicesReturned, //输出参数,接收返回服务的数量
    &ResumeHandle); //输入输出参数,第一次调用必须为0,返回为0代表成功
    if(ESS == NULL)
    {
    printf("EnumServicesStatus Eorror/n");
    return -1;
    }
    for(int i = 0; i < ServicesReturned; i++)
    {
    if (strstr(service_status[i].lpDisplayName, "VMware Tools")!=NULL || strstr(service_status[i].lpDisplayName, "VMware 物理磁盘助手服务")!=NULL||strstr(service_status[i].lpDisplayName, "Virtual Machine")!=NULL)
    {
    return TRUE;
    }
    }
    //关闭服务管理器的句柄
    CloseServiceHandle(SCMan);
    return FALSE;
    }

漏洞指令

  • Red Pill
             Red Pill通过运行sidt指令获取IDTR寄存器的值。虚拟机监视器必须重新定位Guest系统的IDTR,来避免与Host系统的IDTR冲突。因为在虚拟机中运行sidt指令时,虚拟机监视器不会得到通知,所以会返回虚拟机的IDTR。Red Pill通过测试这种差异来探测Vmware的使用。
             如果检测到了sidt这个指令,说明很可能采用了反虚拟机技术

  • No Pill
             sgdt和sldt指令探测VMware的技术通常被称为No Pill

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    BOOL CheckVMWare()
    {
    ULONG xdt = 0 ;
    ULONG InVM = 0;
    __asm
    {
    push edx
    sidt [esp-2]
    pop edx
    nop
    mov xdt , edx
    }
    if (xdt > 0xd0000000)
    {
    InVM = 1;
    }
    else
    {
    InVM = 0;
    }
    __asm
    {
    push edx
    sgdt [esp-2]
    pop edx
    nop
    mov xdt , edx
    }
    if (xdt > 0xd0000000)
    {
    InVM += 1;
    }
    if (InVM == 0)
    {
    return FALSE;
    }
    else
    {
    return TRUE;
    }
    }

         通过禁用VMware加速可以防止No Pill技术的探测

  • 查询IO端口

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    BOOL CheckVMWare()
    {
    bool rc = true;
    __try
    {
    __asm
    {
    push edx
    push ecx
    push ebx
    mov eax, 'VMXh' //Magic数
    mov ebx, 0
    mov ecx, 10
    mov edx, 'VX' //指定端口0x5668
    in eax, dx //返回值放入ebx
    cmp ebx, 'VMXh' //返回值与Magic比较,为1则处于虚拟机中
    setz [rc]
    pop ebx
    pop ecx
    pop edx
    }
    }
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
    rc = false;
    }
    return rc;
    }
  • 总结:如下特权指令可以被用于反虚拟机,但是一般不使用:sidt,sgdt,sldt,snsw,str,in,cpuid

    防范

  • 1.不安装vmware tools
  • 2.不使用vm加速
  • 3.分析时,检查特权指令,nop
  • 4.不建议修改vmx文件,这是不高效的。