反調試——8——虛擬機檢測
其實虛擬機檢測也無外乎就是檢測一些虛擬機特有的特征,然后來判斷是否是在虛擬機里面,比如說這里(查看系統中運行的服務):
但是不能直接盲目的通過VMware這六個關鍵字母就判斷是在虛擬機里面了,因為你的電腦如果開了虛擬機,也會有一些VMware開頭的虛擬機服務:
所以我們必須要選取一些比較唯一的,比如說這里我們選這個VMware SVGA Helper Service這個把,大家可以自行選擇。然后需要做的就是遍歷系統中的服務,看看有沒有這個東西就行了。
遍歷系統中的服務:
這里會用到一個API:
BOOL EnumServicesStatusA(
SC_HANDLE hSCManager,
DWORD dwServiceType,
DWORD dwServiceState,
LPENUM_SERVICE_STATUSA lpServices,
DWORD cbBufSize,
LPDWORD pcbBytesNeeded,
LPDWORD lpServicesReturned,
LPDWORD lpResumeHandle
);
然后這個API的第一個參數需要用OpenSCManager這個API來使用:
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; } }
小結