0x2 虚拟机检测
- 虚拟机检测的针对性很强,时效性也很强,这里只是简单的介绍一个作为例子
虚拟机检测核心无外乎以下几点:
- 设备
- 驱动
- 硬件
- 虚拟指令
TRUE
:表示检测到调试
0x2.1 mac检测
- 虚拟机的mac地址一般都有特殊的标志头
- 这个标志头是全球mac联盟分配的,一般不会变
- 这里列举vb的mac检测方式
- vb的mac地址是以
08:00:27
开头
//获取并且比对mac地址
BOOL check_mac_addr(const TCHAR* szMac)
{
BOOL bResult = FALSE;
PIP_ADAPTER_INFO pAdapterInfo, pAdapterInfoPtr;
ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO);
pAdapterInfo = (PIP_ADAPTER_INFO)MALLOC(sizeof(IP_ADAPTER_INFO));
if (pAdapterInfo == NULL)
{
_tprintf(_T("Error allocating memory needed to call GetAdaptersinfo.\n"));
return -1;
}
DWORD dwResult = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen);
// 获取 ulOutBufLen 需要的长度
if (dwResult == ERROR_BUFFER_OVERFLOW)
{
FREE(pAdapterInfo);
pAdapterInfo = (PIP_ADAPTER_INFO)MALLOC(ulOutBufLen);
if (pAdapterInfo == NULL) {
printf("Error allocating memory needed to call GetAdaptersinfo\n");
return 1;
}
// 获取网卡信息
dwResult = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen);
}
if (dwResult == ERROR_SUCCESS)
{
// 将mac转换成字符串比较
CHAR szMacMultiBytes[4];
for (int i = 0; i < 4; i++) {
szMacMultiBytes[i] = (CHAR)szMac[i];
}
pAdapterInfoPtr = pAdapterInfo;
while (pAdapterInfoPtr)
{
if (pAdapterInfoPtr->AddressLength == 6 && !memcmp(szMacMultiBytes, pAdapterInfoPtr->Address, 3))
{
bResult = TRUE;
break;
}
pAdapterInfoPtr = pAdapterInfoPtr->Next;
}
}
FREE(pAdapterInfo);
return bResult;
}
BOOL vbox_check_mac()
{
// VirtualBox 的mac 地址 由 PCS Systemtechnik CmbH 公司提供
return check_mac_addr(_T("\x08\x00\x27"));
}
0x2.2 窗口检测
虚拟机内一般会运行固定的软件:
- 调试器
- vmtools
- vbtools
- 检测这些特殊的窗口也可在以为标志
BOOL vbox_window_class()
{
//检测特殊的窗口
HWND hClass = FindWindow(_T("VBoxTrayToolWndClass"), NULL);
HWND hWindow = FindWindow(NULL, _T("VBoxTrayToolWnd"));
//只要有一个就算是虚拟机
if (hClass || hWindow)
return TRUE;
else
return FALSE;
}
0x2.3 硬盘检测
- 虚拟磁盘需要windows加载专属的驱动才能识别
- 驱动中内置了硬盘的类别
- 通过字符串比较 硬盘类别可以判断是否存在虚拟磁盘
- 本质上检测是否挂载了虚拟磁盘
// 本质上是检测注册表:HKLM\System\CurrentControlSet\Services\Disk\Enum
BOOL registry_services_disk_enum()
{
HKEY hkResult = NULL;
const TCHAR* diskEnumKey = _T("System\\CurrentControlSet\\Services\\Disk\\Enum");
DWORD diskCount = 0;
DWORD cbData = sizeof(diskCount);
const TCHAR* szChecks[] = {
/*
关键字
* https://research.checkpoint.com/2019-resurgence-of-smokeloader
*/
_T("qemu"),
_T("virtio"),
_T("vmware"),
_T("vbox"),
_T("xen"),
/*
关键字
https://cofense.com/kutaki-malware-bypasses-gateways-steal-users-credentials/
*/
_T("VMW"),
_T("Virtual"),
};
WORD dwChecksLength = sizeof(szChecks) / sizeof(szChecks[0]);
BOOL bFound = FALSE;
//没有记录就退出
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, diskEnumKey, NULL, KEY_READ, &hkResult) == ERROR_SUCCESS)
{
if (RegQueryValueEx(hkResult, _T("Count"), NULL, NULL, (LPBYTE)&diskCount, &cbData) != ERROR_SUCCESS)
{
RegCloseKey(hkResult);
return bFound;
}
RegCloseKey(hkResult);
}
for (unsigned int i = 0; i < diskCount; i++) {
TCHAR subkey[11];
_stprintf_s(subkey, sizeof(subkey) / sizeof(subkey[0]), _T("%d"), i);
//检测是否存在关键字
for (unsigned int j = 0; j < dwChecksLength; j++) {
if (Is_RegKeyValueExists(HKEY_LOCAL_MACHINE, diskEnumKey, subkey, szChecks[j])) {
bFound = TRUE;
break;
}
}
if (bFound) {
break;
}
}
return bFound;
}
0x2.4 设备检查
- 虚拟机一般会虚拟出一些专用的硬件设备用于通信
//vb的一些特殊设备
VOID vbox_devices()
{
const TCHAR *devices[] = {
_T("\\\\.\\VBoxMiniRdrDN"),
_T("\\\\.\\VBoxGuest"),
_T("\\\\.\\pipe\\VBoxMiniRdDN"),
_T("\\\\.\\VBoxTrayIPC"),
_T("\\\\.\\pipe\\VBoxTrayIPC")
};
WORD iLength = sizeof(devices) / sizeof(devices[0]);
for (int i = 0; i < iLength; i++)
{
HANDLE hFile = CreateFile(devices[i], GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
TCHAR msg[256] = _T("");
_stprintf_s(msg, sizeof(msg) / sizeof(TCHAR), _T("Checking device %s "), devices[i]);
if (hFile != INVALID_HANDLE_VALUE) {
CloseHandle(hFile);
print_results(TRUE, msg);
}
else
print_results(FALSE, msg);
}
}
//vmware的设备
VOID vmware_devices()
{
const TCHAR *devices[] = {
_T("\\\\.\\HGFS"),
_T("\\\\.\\vmci"),
};
WORD iLength = sizeof(devices) / sizeof(devices[0]);
for (int i = 0; i < iLength; i++)
{
HANDLE hFile = CreateFile(devices[i], GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
TCHAR msg[256] = _T("");
_stprintf_s(msg, sizeof(msg) / sizeof(TCHAR), _T("Checking device %s "), devices[i]);
if (hFile != INVALID_HANDLE_VALUE) {
CloseHandle(hFile);
print_results(TRUE, msg);
}
else
print_results(FALSE, msg);
}
}
0x2.5 进程检测
- 虚拟机中可能在后台运行一些特殊的驱动程序
//xen检测
VOID xen_process()
{
//这是一个数组
const TCHAR *szProcesses[] = {
_T("xenservice.exe"),
};
WORD iLength = sizeof(szProcesses) / sizeof(szProcesses[0]);
for (int i = 0; i < iLength; i++)
{
TCHAR msg[256] = _T("");
_stprintf_s(msg, sizeof(msg) / sizeof(TCHAR), _T("Checking Citrix Xen process %s"), szProcesses[i]);
if (GetProcessIdFromName(szProcesses[i]))
print_results(TRUE, msg);
else
print_results(FALSE, msg);
}
}