Hardware  H  FileSystem  Registry  Generic OS Queries  Global OS object  UI artifacts  OS Features  Processes  Network  CPU  Hardware  Firmware tables  Hooks  Timing  WMI  Human-like behavior  macOS


Hardware info detection methods

Virtual environments emulate hardware devices and leave specific traces in their descriptions - which may be queried and the conclusion about non-host OS made.


 

1. Check if HDD has specific name

Functions used:

Code sample

 

hDevs = SetupDiGetClassDevs(
&guid,  // GUID_DEVCLASS(DEVINTERFACE)_DISKDRIVE
NULL,
NULL,
DIGCF_PRESENT);

SetupDiEnumDeviceInfo(
hDevsInfo,
0,
&devinfo);  // PSP_DEVINFO_DATA

SetupDiGetDeviceRegistryProperty(
hDevs,
&devinfo,
SPDRP_FRIENDLYNAME,
&dword_1,
szFriendlyName,  // HDD name will be here
dFriendlyNameSize,
&dword_2);

Detections table

Check if hard disk drive has one of the following names:
DetectName
QEMUQEMU
VirtualBoxVBOX
VirtualPCVIRTUAL HD
VMWareVMWare


 

2. Check if HDD Vendor ID has specific value

The following function is used:

Code sample

 

bool GetHDDVendorId(std::string& outVendorId) {
HANDLE hDevice = CreateFileA(_T("\\\\.\\PhysicalDrive0"), 
0, 
FILE_SHARE_READ | FILE_SHARE_WRITE, 
0, 
OPEN_EXISTING, 
0, 
0);
if (hDevice == INVALID_HANDLE_VALUE)
return false;
    
STORAGE_PROPERTY_QUERY storage_property_query = {};
storage_property_query.PropertyId = StorageDeviceProperty;
storage_property_query.QueryType = PropertyStandardQuery;
STORAGE_DESCRIPTOR_HEADER storage_descriptor_header = {};
DWORD BytesReturned = 0;
  
if (!DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY, 
&storage_property_query, sizeof(storage_property_query), 
&storage_descriptor_header, sizeof(storage_descriptor_header), 
&BytesReturned, )) {
printf("DeviceIoControl() for size query failed\n");
CloseHandle(hDevice);
return false;
}
if (!BytesReturned) {
CloseHandle(hDevice);
return false;
}
  
std::vector<char> buff(storage_descriptor_header.Size); //_STORAGE_DEVICE_DESCRIPTOR
if (!DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY, 
&storage_property_query, sizeof(storage_property_query), 
buff.data(), buff.size(), 0)) {
CloseHandle(hDevice);
return false;
}
  
CloseHandle(hDevice);
  
if (BytesReturned) {
STORAGE_DEVICE_DESCRIPTOR* device_descriptor = (STORAGE_DEVICE_DESCRIPTOR*)buff.data();
if (device_descriptor->VendorIdOffset)
outVendorId = &buff[device_descriptor->VendorIdOffset];
  
return true;
}
    
return false;
}

Detections table

Check if HDD Vendor ID is one of the following:
DetectName
VirtualBoxVBOX
VMWarevmware


 

3. Check if audio device is absent

This technique was extracted from TeslaCrypt malware sample and was described in this Joe Security blog post.

Code sample

 

void AudioEvasion() {
PCWSTR wszfilterName = L"audio_device_random_name";

if (FAILED(CoInitialize(NULL)))
return;

IGraphBuilder *pGraph = nullptr;
if (FAILED(CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**)&pGraph)))
return;

if (E_POINTER != pGraph->AddFilter(NULL, wszfilterName))
ExitProcess(-1);

IBaseFilter *pBaseFilter = nullptr;
CoCreateInstance(CLSID_AudioRender, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pBaseFilter);
  
pGraph->AddFilter(pBaseFilter, wszfilterName);

IBaseFilter *pBaseFilter2 = nullptr;
pGraph->FindFilterByName(wszfilterName, &pBaseFilter2);
if (nullptr == pBaseFilter2)
ExitProcess(1);

FILTER_INFO info = { 0 };
pBaseFilter2->QueryFilterInfo(&info);
if (0 != wcscmp(info.achName, wszfilterName))
return;

IReferenceClock *pClock = nullptr;
if (0 != pBaseFilter2->GetSyncSource(&pClock))
return;
if (0 != pClock)
return;

CLSID clsID = { 0 };
pBaseFilter2->GetClassID(&clsID);
if (clsID.Data1 == 0)
ExitProcess(1);

if (nullptr == pBaseFilter2)
ExitProcess(-1);

IEnumPins *pEnum = nullptr;
if (0 != pBaseFilter2->EnumPins(&pEnum))
ExitProcess(-1);

if (0 == pBaseFilter2->AddRef())
ExitProcess(-1);
}


 

4. Check if CPU temperature information is available

This technique was extracted from GravityRAT malware and is described by this link.

Code sample (Windows cmd command)

 

wmic /namespace:\\root\WMI path MSAcpi_ThermalZoneTemperature get CurrentTemperature


 

5. Check physical display adapter for IDirect3D9 interface

This method checks physical display adapters present in the system when the IDirect3D9 interface was instantiated. It works on all Windows versions starting from Windows XP.

Functions used:

Code sample

 

#include <d3d9.h>

// https://github.com/qt/qtbase/blob/dev/src/plugins/platforms/windows/qwindowsopengltester.cpp#L124

void detect() {
typedef IDirect3D9* (WINAPI* PtrDirect3DCreate9)(UINT);

HMODULE d3d9lib = ::LoadLibraryA("d3d9");
if (!d3d9lib)
return;

PtrDirect3DCreate9 direct3DCreate9 = (PtrDirect3DCreate9)GetProcAddress(d3d9lib, "Direct3DCreate9");
if (!direct3DCreate9)
return;

IDirect3D9* direct3D9 = direct3DCreate9(D3D_SDK_VERSION);
if (!direct3D9)
return;

D3DADAPTER_IDENTIFIER9 adapterIdentifier;
const HRESULT hr = direct3D9->GetAdapterIdentifier(0, 0, &adapterIdentifier);
direct3D9->Release();

if (SUCCEEDED(hr)) {
printf("VendorId:    0x%x\n", adapterIdentifier.VendorId);
printf("DeviceId:    0x%x\n", adapterIdentifier.DeviceId);
printf("Driver:      %s\n", adapterIdentifier.Driver);
printf("Description: %s\n", adapterIdentifier.Description);
}
}

Credits for this code sample go to elsamuko who pointed it out.

Example of output on a usual host machine is provided below:

VendorId:    0x10de
DeviceId:    0x103c
Driver:      nvldumdx.dll
Description: NVIDIA Quadro K5200

And here is an example of output on a virtual machine (VMware):

VendorId:    0x15ad
DeviceId:    0x405
Driver:      vm3dum64_loader.dll
Description: VMware SVGA 3D

Examined fields are named after the corresponding fields of D3DADAPTER_IDENTIFIER9 structure. Malware can compare values in these fields to the ones which are known to be present inside the virtual machine and if match is found, then it draws the conclusion that it’s run under virtual machine.

Detections table

Check if the following values are present in the fields of D3DADAPTER_IDENTIFIER9 structure:
DetectStructure fieldValueComment
VMwareVendorId0x15AD 
DeviceId0x405Only when used in combination with VendorId related to VMware (0x15AD)
Drivervm3dum.dll 
Drivervm3dum64_loader.dll 
DescriptionVMware SVGA 3D 


 

Signature recommendations

Signature recommendations are general for each technique: hook the function used and track if it is called. It’s pretty hard to tell why application wants to get HDD name, for example. It doesn’t necessarily mean applying evasion technique. So the best what can be done in this situation is intercepting target functions and tracking their calls.


 

Countermeasures