反調試——8——虛擬機檢測


反調試——8——虛擬機檢測

其實虛擬機檢測也無外乎就是檢測一些虛擬機特有的特征,然后來判斷是否是在虛擬機里面,比如說這里(查看系統中運行的服務):

 

 

但是不能直接盲目的通過VMware這六個關鍵字母就判斷是在虛擬機里面了,因為你的電腦如果開了虛擬機,也會有一些VMware開頭的虛擬機服務:

 

 

所以我們必須要選取一些比較唯一的,比如說這里我們選這個VMware SVGA Helper Service這個把,大家可以自行選擇。然后需要做的就是遍歷系統中的服務,看看有沒有這個東西就行了。

遍歷系統中的服務:

這里會用到一個API:

EnumServicesStatusA function (winsvc.h) - Win32 apps | Microsoft Docs

BOOL EnumServicesStatusA(
 SC_HANDLE              hSCManager,
 DWORD                  dwServiceType,
 DWORD                  dwServiceState,
 LPENUM_SERVICE_STATUSA lpServices,
 DWORD                  cbBufSize,
 LPDWORD                pcbBytesNeeded,
 LPDWORD                lpServicesReturned,
 LPDWORD                lpResumeHandle
);

然后這個API的第一個參數需要用OpenSCManager這個API來使用:OpenSCManagerA function (winsvc.h) - Win32 apps | Microsoft Docs

 

SC_HANDLE OpenSCManagerA(
 LPCSTR lpMachineName,//如果值為0表示本機
 LPCSTR lpDatabaseName,
 DWORD  dwDesiredAccess
);

然后這個服務數據庫的句柄必須調用一個API來關閉:

CloseServiceHandle()

 

void TestVirtual()
{
    auto hSCM = OpenSCManagerA(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
    /*
    第一個為NULL表示是本機,
    第二個參數是指定值,
    第三個參數表示權限,如果要調用枚舉服務API就需要是這個權限。
    */
    if (hSCM == NULL)
    {
        cout << "打開系統服務數據庫錯誤" << endl;
        return;
    }
    LPENUM_SERVICE_STATUSA lpServiceStatus = NULL;
    lpServiceStatus = (LPENUM_SERVICE_STATUSA)malloc(0x8000);
    DWORD servieceSize = 0;
    DWORD needSize = 0;
    DWORD resumeHandle = 0;
    auto ret = EnumServicesStatusA(hSCM, SERVICE_WIN32, SERVICE_STATE_ALL, lpServiceStatus, 0x8000, &needSize, &servieceSize, &resumeHandle);
    /*
    第一個參數:是服務數據庫的句柄
    第二個參數:是要的服務的類型,這里不直到怎么查看我就全部加上了
    第三個參數:服務的狀態,是否啟動
    第四個參數:服務結構體的緩沖區
    第五個參數:緩沖區大小
    第六個參數:如果緩沖區大小不夠,需要的剩下的大小是多少
    第七個參數:得到的服務的數量
    第八個參數:緩沖區不夠的時候下一個服務的結構體指針
    */
    if(needSize>0x8000)
    {
        cout << "緩沖區過小" << endl;
        return;
    }
​
    for (int i = 0; i < servieceSize; i++)
    {
        if (strcmp(lpServiceStatus->lpDisplayName, "VMware SVGA Helper Service")==0)
        {
            cout<<"檢測到了虛擬機"<<endl;
            return ;
        }
        lpServiceStatus++;
    }
    cout << "沒有檢測到虛擬機" << endl;
    CloseServiceHandle(hSCM);
}

 


 

 

還有很多方式,大家可以入手,只要是可以唯一標識虛擬機就好。

特殊的辦法

這個辦法我也不知道為什么。不是虛擬機的環境運行下面的代碼會崩潰。是虛擬機則安然無恙。

            push   edx
            push   ecx
            push   ebx
            mov    eax, 'VMXh'
            mov    ebx, 0
            mov    ecx, 10 
            mov    edx, 'VX' 
            in     eax, dx 
            cmp    ebx, 'VMXh'
            pop    ebx
            pop    ecx
            pop edx

 

//代碼實現:
void testAssemer()
{
    int FLAG = FALSE;
    __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'
            pop    ebx
            pop    ecx
            pop edx
        }
    }
    __except(1)
    {
        FLAG = TRUE;
    }
    if (FLAG == FALSE)
    {
        cout << "檢測到了虛擬機" << endl;
    }
    else
    {
        cout << "未檢測到虛擬機" << endl;
    }
}

 

 

 

小結

虛擬機和本機肯定是有一些不同的,抓住這些驗證不同的辦法就可以來檢測是否是在虛擬機里了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM