362 lines
6.9 KiB
C++
362 lines
6.9 KiB
C++
#include "check_vmware.h"
|
||
#include "utils.h"
|
||
|
||
#include <initguid.h>
|
||
#include <devguid.h>
|
||
#include <SetupAPI.h>
|
||
#include <initguid.h>
|
||
#include <dxgi.h>
|
||
#include <intrin.h>
|
||
|
||
|
||
#pragma comment(lib, "dxgi.lib")
|
||
#pragma comment(lib, "Setupapi.lib")
|
||
|
||
|
||
CONST WCHAR* processList[] =
|
||
{
|
||
L"vmtoolsd.exe",
|
||
L"vm3dservice.exe",
|
||
L"VGAuthService.exe",
|
||
};
|
||
|
||
CONST CHAR* filePathName[] =
|
||
{
|
||
"C:\\Program Files\\VMware",
|
||
|
||
"C:\\Windows\\System32\\drivers\\vmmouse.sys",
|
||
"C:\\Windows\\System32\\drivers\\vmusbmouse.sys",
|
||
|
||
"C:\\Windows\\System32\\drivers\\vm3dmp.sys",
|
||
"C:\\Windows\\System32\\drivers\\vm3dmp_loader.sys",
|
||
"C:\\Windows\\System32\\drivers\\vm3dmp-debug.sys",
|
||
"C:\\Windows\\System32\\drivers\\vm3dmp-stats.sys",
|
||
};
|
||
|
||
namespace check_vmware
|
||
{
|
||
bool registry()
|
||
{
|
||
char szBuf[256]{ 0 };
|
||
if (utils::RegReadString(HKEY_LOCAL_MACHINE,
|
||
"HARDWARE\\DESCRIPTION\\System\\BIOS",
|
||
"SystemManufacturer",
|
||
szBuf, sizeof(szBuf)))
|
||
{
|
||
if (strstr(szBuf, "VMware"))
|
||
return true;
|
||
}
|
||
|
||
if (utils::RegReadString(HKEY_LOCAL_MACHINE,
|
||
"HARDWARE\\DESCRIPTION\\System\\BIOS",
|
||
"SystemProductName",
|
||
szBuf, sizeof(szBuf)))
|
||
{
|
||
if (strstr(szBuf, "VMware"))
|
||
return true;
|
||
}
|
||
|
||
|
||
return false;
|
||
}
|
||
|
||
bool process()
|
||
{
|
||
auto Snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
|
||
if (Snapshot == INVALID_HANDLE_VALUE)
|
||
return false;
|
||
|
||
PROCESSENTRY32 pe32{ 0 };
|
||
pe32.dwSize = sizeof(pe32);
|
||
|
||
|
||
if (Process32First(Snapshot, &pe32))
|
||
{
|
||
do {
|
||
for (size_t i = 0; i < sizeof(processList) / sizeof(processList[0]); i++)
|
||
{
|
||
if (!wcscmp(processList[i], pe32.szExeFile))
|
||
{
|
||
CloseHandle(Snapshot);
|
||
return true;
|
||
}
|
||
}
|
||
} while (Process32Next(Snapshot, &pe32));
|
||
}
|
||
|
||
CloseHandle(Snapshot);
|
||
|
||
return false;
|
||
}
|
||
|
||
bool cpuid()
|
||
{
|
||
int info[4]{ 0 };
|
||
CHAR szHypervisorVendor[256];
|
||
|
||
__cpuid(info, 0x40000000);
|
||
SecureZeroMemory(szHypervisorVendor, sizeof(szHypervisorVendor));
|
||
memcpy(szHypervisorVendor, info + 1, 12);
|
||
|
||
if (!_strcmpi(szHypervisorVendor, "VMwareVMware"))
|
||
return true;
|
||
|
||
return false;
|
||
}
|
||
|
||
bool cpuid2()
|
||
{
|
||
int info[4]{ 0 };
|
||
|
||
__cpuid(info, 1);
|
||
|
||
if ((info[2] >> 31) & 1)
|
||
return true;
|
||
|
||
return false;
|
||
}
|
||
|
||
bool diskname()
|
||
{
|
||
HDEVINFO hDevInfo = SetupDiGetClassDevsW(&GUID_DEVCLASS_DISKDRIVE, NULL, NULL, DIGCF_PRESENT);
|
||
if (hDevInfo == INVALID_HANDLE_VALUE)
|
||
return false;
|
||
|
||
SP_DEVINFO_DATA devInfo = { 0 };
|
||
devInfo.cbSize = sizeof(SP_DEVINFO_DATA);
|
||
|
||
DWORD dwIndex = 0;
|
||
// 循环枚举全部磁盘设备
|
||
while (SetupDiEnumDeviceInfo(hDevInfo, dwIndex, &devInfo))
|
||
{
|
||
WCHAR szBuffer[1024] = { 0 };
|
||
DWORD dwDataType = 0;
|
||
DWORD dwBufSize = sizeof(szBuffer);
|
||
|
||
// 读取设备友好名称 SPDRP_FRIENDLYNAME
|
||
if (SetupDiGetDeviceRegistryPropertyW(
|
||
hDevInfo,
|
||
&devInfo,
|
||
SPDRP_FRIENDLYNAME,
|
||
&dwDataType,
|
||
(PBYTE)szBuffer,
|
||
dwBufSize,
|
||
&dwBufSize))
|
||
{
|
||
if (utils::StrContainsI(szBuffer, L"VBOX") ||
|
||
utils::StrContainsI(szBuffer, L"QEMU") ||
|
||
utils::StrContainsI(szBuffer, L"VMWARE") ||
|
||
utils::StrContainsI(szBuffer, L"VIRTUAL HD"))
|
||
{
|
||
SetupDiDestroyDeviceInfoList(hDevInfo);
|
||
return true;
|
||
}
|
||
}
|
||
dwIndex++;
|
||
}
|
||
SetupDiDestroyDeviceInfoList(hDevInfo);
|
||
return false;
|
||
}
|
||
|
||
bool mousename()
|
||
{
|
||
HDEVINFO hDevInfo = SetupDiGetClassDevs(
|
||
&GUID_DEVCLASS_MOUSE,
|
||
NULL,
|
||
NULL,
|
||
DIGCF_PRESENT);
|
||
|
||
if (hDevInfo == INVALID_HANDLE_VALUE)
|
||
return false;
|
||
|
||
SP_DEVINFO_DATA DeviceInfoData;
|
||
DeviceInfoData.cbSize = sizeof(DeviceInfoData);
|
||
|
||
bool bVirtual = false;
|
||
|
||
for (DWORD i = 0;
|
||
SetupDiEnumDeviceInfo(hDevInfo, i, &DeviceInfoData);
|
||
i++)
|
||
{
|
||
WCHAR Name[512] = { 0 };
|
||
|
||
// FriendlyName
|
||
if (!SetupDiGetDeviceRegistryPropertyW(
|
||
hDevInfo,
|
||
&DeviceInfoData,
|
||
SPDRP_FRIENDLYNAME,
|
||
NULL,
|
||
(PBYTE)Name,
|
||
sizeof(Name),
|
||
NULL))
|
||
{
|
||
// 有些设备没有 FriendlyName
|
||
SetupDiGetDeviceRegistryPropertyW(
|
||
hDevInfo,
|
||
&DeviceInfoData,
|
||
SPDRP_DEVICEDESC,
|
||
NULL,
|
||
(PBYTE)Name,
|
||
sizeof(Name),
|
||
NULL);
|
||
}
|
||
|
||
std::wstring str = Name;
|
||
|
||
if (str.find(L"VMware") != std::wstring::npos ||
|
||
str.find(L"VirtualBox") != std::wstring::npos ||
|
||
str.find(L"Hyper-V") != std::wstring::npos ||
|
||
str.find(L"Virtual") != std::wstring::npos ||
|
||
str.find(L"QEMU") != std::wstring::npos ||
|
||
str.find(L"Xen") != std::wstring::npos ||
|
||
str.find(L"Parallels") != std::wstring::npos)
|
||
{
|
||
bVirtual = true;
|
||
}
|
||
}
|
||
|
||
SetupDiDestroyDeviceInfoList(hDevInfo);
|
||
return bVirtual;
|
||
}
|
||
|
||
|
||
bool dxgiGpuName()
|
||
{
|
||
HRESULT hr;
|
||
IDXGIFactory1* pFactory = nullptr;
|
||
|
||
hr = CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)&pFactory);
|
||
if (FAILED(hr) || !pFactory)
|
||
return false;
|
||
|
||
UINT adapterIndex = 0;
|
||
IDXGIAdapter1* pAdapter = nullptr;
|
||
|
||
// 遍历所有显卡适配器
|
||
while (pFactory->EnumAdapters1(adapterIndex, &pAdapter) != DXGI_ERROR_NOT_FOUND)
|
||
{
|
||
DXGI_ADAPTER_DESC1 desc;
|
||
hr = pAdapter->GetDesc1(&desc);
|
||
if (SUCCEEDED(hr))
|
||
{
|
||
// 虚拟机显卡特征关键词
|
||
if (wcsstr(desc.Description, L"VMware") != nullptr
|
||
|| wcsstr(desc.Description, L"VBox") != nullptr
|
||
|| wcsstr(desc.Description, L"VirtualBox") != nullptr
|
||
|| wcsstr(desc.Description, L"Basic Display Adapter") != nullptr)
|
||
{
|
||
pAdapter->Release();
|
||
pFactory->Release();
|
||
return true;
|
||
}
|
||
}
|
||
pAdapter->Release();
|
||
adapterIndex++;
|
||
}
|
||
|
||
pFactory->Release();
|
||
return false;
|
||
}
|
||
|
||
bool In()
|
||
{
|
||
#if _WIN64
|
||
__try
|
||
{
|
||
Asm_CheckVmWare();
|
||
return true;
|
||
}
|
||
__except (1)
|
||
{
|
||
return false;
|
||
}
|
||
#else
|
||
__try
|
||
{
|
||
__asm
|
||
{
|
||
mov eax, 0x564D5868; //魔法值 'VMXh',VMware端口通信固定标识
|
||
mov ebx, 0xFFFFFFFF; //EBX初始值,用于接收Hypervisor返回标识
|
||
mov ecx, 10; //命令号 10 = CMD_GetVersion(获取VMware版本)
|
||
mov edx, 0x5658; //VMware专属I / O端口号 0x5658
|
||
in eax, dx; //向VMware端口发起通信请求
|
||
cmp ebx, 0x564D5868; //判断EBX是否被改写为'VMXh'魔法值
|
||
je vm_found; //相等 = 检测到VMware,跳转
|
||
xor al, al; //未找到,AL置0(FALSE)
|
||
jmp vm_end; //跳转到结尾
|
||
vm_found:
|
||
mov al, 1; //找到VMware,AL置1(TRUE)
|
||
vm_end:
|
||
}
|
||
}
|
||
__except (GetExceptionCode() == EXCEPTION_PRIV_INSTRUCTION)
|
||
{
|
||
return FALSE;
|
||
}
|
||
#endif
|
||
}
|
||
|
||
bool file()
|
||
{
|
||
for (size_t i = 0; i < sizeof(filePathName) / sizeof(filePathName[0]); i++)
|
||
{
|
||
if (GetFileAttributesA(filePathName[i]) != INVALID_FILE_ATTRIBUTES)
|
||
{
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
unsigned long long rdtsc_exit()
|
||
{
|
||
int info[4]{ 0 };
|
||
DWORD64 tsc1, tsc2;
|
||
DWORD64 sum = 0;
|
||
|
||
for (size_t i = 0; i < 200; i++)
|
||
{
|
||
tsc1 = __rdtsc();
|
||
__cpuid(info, 0);
|
||
tsc2 = __rdtsc();
|
||
sum += (tsc2 - tsc1);
|
||
}
|
||
|
||
return sum;
|
||
}
|
||
|
||
bool virutal_check_vmcall()
|
||
{
|
||
#if _WIN64
|
||
|
||
__try
|
||
{
|
||
Asm_VMCall();
|
||
return true;
|
||
}
|
||
__except (1)
|
||
{
|
||
return false;
|
||
}
|
||
#else
|
||
|
||
__try
|
||
{
|
||
_asm
|
||
{
|
||
_emit 0x0F
|
||
_emit 0x01
|
||
_emit 0xC1
|
||
|
||
mov eax, 1
|
||
}
|
||
}
|
||
__except (1)
|
||
{
|
||
return false;
|
||
}
|
||
#endif
|
||
}
|
||
|
||
|
||
} |