基於軟體特徵檢測虛擬機

在調試時,有可能會放在虛擬機里調試,所以反調試就需要檢測是否在VM中,這裡提供的方法有以下三種:

  方式1:搜索服務   – 包含WMware Tools / WMware 物理磁碟助手服務
  方式2:找文件路徑  – C:\Program Files\VMware\VMware Tools
  方式3:尋找進程   – vmtoolsd.exe

 

程式碼:

#include <stdio.h>
#include <Windows.h>
#include <process.h>
#include <TlHelp32.h>
#include "Psapi.h"

#include <Shlwapi.h>
#pragma comment(lib,"Shlwapi.lib")


/**********************************************************************************/

// 通過VMware Tools路徑檢測虛擬機
BOOL CheckVmByPath()
{
    // PathIsDirectory需要包含Shlwapi的頭文件和庫
    if (PathIsDirectory("C:\\Program Files\\VMware\\VMware Tools") == 0 )
    {
        return FALSE;
    }
    else
    {
        return TRUE;
    }
}
DWORD WINAPI ThreadFuncCallBack(LPVOID lp)
{
    while (true)
    {
        if (CheckVmByPath())
        {
            MessageBox(0, "VM存在", "提示",MB_OK);
            break;
        }
    }
    return 0;
}

/**********************************************************************************/

// 搜索服務 -- 包含WMware Tools / WMware 物理磁碟助手服務
BOOL CheckVmByServe()
{
    SC_HANDLE SCMan = OpenSCManager(NULL,NULL, SC_MANAGER_CONNECT| SC_MANAGER_ENUMERATE_SERVICE);    // 打開本地的服務控制管理器資料庫,得到句柄
    if (SCMan == NULL)
    {
        return FALSE;
    }
    else
    {
        LPENUM_SERVICE_STATUSA service_status;
        DWORD dwByteNeed = NULL;    // 需要的服務
        DWORD dwServiceReturned = NULL;    // 返回服務的數量
        DWORD dwResumeHandle = NULL;
        service_status = (LPENUM_SERVICE_STATUSA)LocalAlloc(LPTR, 1024*64);

        bool bEss = EnumServicesStatusA(SCMan, SERVICE_WIN32, SERVICE_STATE_ALL, 
            service_status, 1024 * 64, &dwByteNeed,&dwServiceReturned,&dwResumeHandle);

        if (bEss == NULL)
        {
            DWORD Error = GetLastError();
            printf("%d", Error);
            return FALSE;
        }
        for (size_t i = 0; i < dwServiceReturned; i++)
        {
            if (strstr(service_status[i].lpDisplayName, "VMware Tools") != NULL || strstr(service_status[i].lpDisplayName, "WMware 物理磁碟助手服務") != NULL)
            {
                return TRUE;
            }
        }
        CloseServiceHandle(SCMan);
        return FALSE;
    }
}

/**********************************************************************************/

BOOL FindProcess(TCHAR *pName)
{
    HANDLE SnapshotHandle;                //定義一個快照
    PROCESSENTRY32 ProcessEntry32;        //照片結構體

    SnapshotHandle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);    //照第一張相
    if (SnapshotHandle != INVALID_HANDLE_VALUE)
    {
        ProcessEntry32.dwSize = sizeof(PROCESSENTRY32);

        if (Process32First(SnapshotHandle, &ProcessEntry32))            //照的第一張放到ProcessEntry32裡面
        {
            do
            {
                if (!strcmp(ProcessEntry32.szExeFile, pName))
                {
                    return TRUE;
                }

            } while (Process32Next(SnapshotHandle, &ProcessEntry32));

            return FALSE;
        }
    }
}

// 尋找調試器進程
DWORD WINAPI ThreadFuncCallBack2(LPVOID lp)
{
    while (TRUE)
    {
        CHAR NeedFindPName[20] = "vmtoolsd.exe";
        if (FindProcess(NeedFindPName))
        {
            MessageBox(0, "存在VM","提示", MB_OK);
            break;
        }
    }
    return 0;
}



int main()
{
    // 方式1:搜索服務 -- 包含WMware Tools / WMware 物理磁碟助手服務
    // CreateThread(NULL, NULL, ThreadFuncCallBack, NULL, NULL, NULL);    
    

    // 方式2:找文件路徑 -- C:\Program Files\VMware\VMware Tools
    /*
    if (CheckVmByServe())
    {
        MessageBox(0, "VM存在", "提示", MB_OK);
        return 0;
    }
    */


    // 方式3:尋找進程 -- vmtoolsd.exe
    CreateThread(NULL, NULL, ThreadFuncCallBack2, NULL, NULL, NULL);


    while (true)
    {
        printf("RUN\n");
    }
    
    system("pause");
    return 0;
}

 

在虛擬機中運行exe文件: