虛擬機運行環境檢測


虛擬機運行環境檢測

虛擬機運行環境檢測,指的是軟件能夠判斷當前是不是在虛擬機中運行,根據判斷結果,做對應的處理。從惡意軟件的視角,它可以在虛擬機中改變自身行為,加大分析難度。從軟件自身安全出發,用於防止被逆向調試以及某些場景下的非正常使用。

檢測思路

要實現這個功能,可有如下幾個入手點:

  • 硬件檢測
    • 虛擬機會創建具有特定標示符的硬件設備以及驅動。例如vmware會虛擬出兩個網卡設備VMnet1(Host Only方式)和VMnet8(NAT方式),vbox會創建VirtualBox Host-Only Network
  • 運行環境檢測
    • vmware虛擬機會默認開啟幾個硬件端口與宿主機通訊。
    • 利用特權指令在虛擬機和真實機器上執行結果不一致來區分。目前在網上找到的方法大部分是用來檢測Vmware,不適用於VirtualBox以及VirtuaPC。
  • 應用程序檢測
    • 虛擬機會安裝一些特定軟件以及服務,比如vmtoolsd.exevboxserivce.exe等。
    • 在特定路徑下,存在特殊標識,例如注冊表、系統驅動文件等。

分享一個網上各虛擬機的硬件區別,原文點此進入

02d06e6691bc2f5087e6a056042c129e.jpg

安裝虛擬機以及測試的注意事項

通過VirtualBox安裝虛擬機時,有時會出現如下錯誤:

使用VirtualBox安裝系統出錯.jpg

通過查閱網上相關資料,發現是因為權限問題,重新以管理員權限打開VirtualBox,就可以繼續安裝。

本次測試發現Virtaul BoxVirtual PC兩款虛擬機會相互沖突,就是說,當Virtaul box啟動時,再啟動Virtual PCVirtaul box會彈出如下提示:

virtualbox和virtualpc相互沖突.jpg

可能這兩種虛擬機不兼容,讀者在自行測試時,需要注意這一點。

安裝VirtualBox的增強功能時,需要安裝多個驅動,有時候安裝界面會把驅動安裝確認界面給蓋住,此時安裝界面會出現類似卡死的情況,因此,建議把安裝界面移到一邊,這樣當驅動確認界面出現時,可確認並繼續安裝。

為了便於在不同虛擬機下測試,選擇原版XP系統。在構建測試軟件時,注意,要使用兼容XP模式的平台工具集來編譯,否則測試軟件無法在xp上運行。同時,將程序運行需要的運行庫放在同一個共享目錄中,各個虛擬機都訪問該共享目錄。

通過VirtualPC安裝虛擬機時,安裝集成組件后,無法查看共享目錄。網上解答連接在此,需要設置登陸用戶名和密碼,然后重新啟動,在打開VirtualPC虛擬機之前,輸入用戶名和密碼,方可看到共享目錄。

實踐

以下給出三種實例來檢測虛擬機是否存在,分布是基於進程名、基於注冊表鍵以及基於硬盤驅動器檢測,更多檢測方案,參考文末實例代碼鏈接。

基於進程名檢測

通過檢測檢測指定進程名是否存在,來判斷是否運行在虛擬機。


bool IsExist(const wchar_t* pName)
{
	if (nullptr == pName)
		return false;
	
	const wchar_t* list[] = {
		//Vmware
		L"vmtoolsd.exe",
		L"vmacthlp.exe",
		L"vmwaretray.exe",
		L"vmwareuser.exe",
		
		//virtuablBox
		L"vboxserivce.exe",
		L"vboxtray.exe",

		//virtualPC
		L"vmsrvc.exe",
		L"vmusrvc.exe",
		L"vpcmap.exe",
	};

	std::wstring strProcessName(pName);
	std::transform(strProcessName.begin(), strProcessName.end(), strProcessName.begin(), ::tolower);
	for (int i = 0; i < sizeof(list)/sizeof(list[0]); i++)
	{
		if (0 == strProcessName.compare(list[i]))
			return true;
	}

	return false;
}

BOOL CheckVMByProcessName()
{
	HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
	if (INVALID_HANDLE_VALUE == hProcessSnap)
		return false;
	
	PROCESSENTRY32 pe32;
	pe32.dwSize = sizeof(PROCESSENTRY32);
	BOOL bMore = Process32First(hProcessSnap, &pe32);
	while (bMore)
	{
		char szName[MAX_PATH] = { 0 };
		
		if (IsExist(pe32.szExeFile))
		{
			_tprintf(L"進程名: %s 進程PID: %d", pe32.szExeFile, pe32.th32ProcessID);
			break;
		}
			
		bMore = Process32Next(hProcessSnap, &pe32);		
	}

	CloseHandle(hProcessSnap);
	return bMore;
}

基於注冊表鍵檢測

利用注冊表鍵值是否存在來檢測,具體如下:


LONG registerOpenKey(char *value)
{
	HKEY HK = 0;
	return RegOpenKeyExA(HKEY_LOCAL_MACHINE, value, 0, KEY_READ, &HK);
}

bool CheckVMByReg()
{
	std::string stringVmRegKeys[] =
	{
		//VMWare
		"SOFTWARE\\Clients\\StartMenuInternet\\VMWAREHOSTOPEN.EXE",
		"SOFTWARE\\VMware, Inc.\\VMware Tools",
		"SYSTEM\\CurrentControlSet\\Enum\\SCSI\\Disk&Ven_VMware_&Prod_VMware_Virtual_S",
		
		// Virtual PC or VirtualBox
		"SYSTEM\\CurrentControlSet\\Control\\VirtualDeviceDrivers",
	};
	
	bool bCheckflag = false;
	for (size_t i = 0; i < sizeof(stringVmRegKeys) / sizeof(stringVmRegKeys[0]); i++)
	{
		if (ERROR_SUCCESS == registerOpenKey((char *)stringVmRegKeys[i].c_str()))
		{
			bCheckflag = true;
			printf("Analysis environment detected (%s)\n", stringVmRegKeys[i].c_str());
		}
	}

	return bCheckflag;
}

基於硬盤驅動器名稱檢測

基於特定硬盤驅動器標題名稱來檢測。


BOOL CheckVMByDiskName()
{
	std::vector<std::wstring> vtBlockHardDisc({ L"vmware", L"vbox", L"virtual"});

	std::vector<std::wstring> vtDrivers;
	CWmiDataHelper querier;
	if (querier.ExecComQuery(L"select * from Win32_DiskDrive", L"Caption", vtDrivers) && vtDrivers.size())
	{
		std::transform(vtDrivers[0].begin(), vtDrivers[0].end(), vtDrivers[0].begin(), tolower);
		
		for (unsigned int i = 0; i < vtBlockHardDisc.size(); i++)
		{
			if (wcsstr(vtDrivers[0].c_str(), vtBlockHardDisc[i].c_str()))
			{				
				_tprintf(L"local disk name: %s. find key word:%s \n", vtDrivers[0].c_str(), vtBlockHardDisc[i].c_str());
				return TRUE;
			}
		}
	}

	return FALSE;
}

測試結果

測試環境:

  • VMware 10.0.1
  • Virtual Box 6.1.18
  • Virtual PC 6.1.7601

在沒有進行任何反檢測措施的情況下,下表為檢測結果匯總。

檢測方法 Vmware Virtual Box Virtual PC 反檢測手段
特定進程名檢測 可以 可以 可以 刪除特定進程
硬盤名稱檢測 可以 可以 可以 修改驅動或者配置文件vmx
MAC地址檢測 可以 可以 可以 修改MAC地址
CPUId檢測 可以 不行 可以 未找到
特定服務檢測 可以 可以 可以 卸載對應服務程序
特定文件檢測 可以 可以 可以 修改特定文件
注冊表檢測 可以 可以 可以 修改特定注冊表選項
IN特權指令 可以 不可以 不可以 未找到
IDT基址 不可以 不可以 不可以 未找到
LDT基址 不可以 不可以 不可以 未找到
GDT基址 不可以 不可以 不可以 未找到
STR 不可以 不可以 不可以 未找到

通過上表可以知道,三種虛擬機環境都可以檢測的方法有

  • 特定進程名
  • 硬盤名
  • MAC地址
  • 注冊表檢測
  • 特定文件
  • 特定服務

特定進程名、硬盤名以及MAC地址這三種很容易反檢測,不建議使用。注冊表選項也很容易繞過,不建議。

最后剩下特定文件以及特定服務,經過實際測試發現,即使禁用掉特定服務,只要沒有卸載掉服務程序,還是可以檢測到的。一般來說,虛擬機提供的服務是為了方便與宿主機通訊的,共享文件的,卸載后會很麻煩。

最終結論,優先使用特定文件檢測,具體檢測文件可根據實際虛擬機環境來設定,其次使用特定服務檢測。

上述每一種方法,均不能百分百保證檢測正確,各位讀者可根據具體情況來使用。

總結

本文搜集網上現有總結,並介紹基於進程、注冊表鍵以及硬盤驅動器名稱等多種檢測虛擬機運行環境的方法,給出優先使用特定文件檢測,其次檢測特定后台服務的方案。

參考資料:

本文工程代碼鏈接在此
軟件如何判斷自己運行在虛擬機中?
反虛擬機和沙箱檢測的一些小技巧
sems
修改虛擬機中的硬盤ID等信息
[原創]虛擬機檢測技術剖析
VMware | ESXi 等虛擬軟件的反虛擬機檢測技術方法探討
VIrtual Machine Detection Techniques


免責聲明!

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



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