Go back

Contents

Generic OS queries
1. Check if the username is specific
2. Check if the computer name is specific
3. Check if the host name is specific
4. Check if the total RAM is low
5. Check if the screen resolution is non-usual for host OS
6. Check if the number of processors is low
7. Check if the quantity of monitors is small
8. Check if the hard disk drive size and free space are small
9. Check if the system uptime is small
10. Check if the OS was boot from virtual hard disk (Win8+)
Countermeasures
Credits

Signature recommendations are general

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 user 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.


Detection via generic OS checks

Usual hosts have meaningful and non-standard usernames/computer names. Particular virtual environments assign some predefined names to default users as well as computer names. Other differences between host OS and VMs include RAM size, HDD size, quantity of monitors - and so on. While these may be not the most reliable ways to detect virtual environments, they are still commonly used in malware samples.


1. Check if the username is specific

Please note that checks are not case-sensitive.

Function used:

  • GetUserNameA/W

Code sample

bool is_user_name_match(const std::string &s) {
    auto out_length = MAX_PATH;
    std::vector<uint8_t> user_name(out_length, 0);
    ::GetUserNameA((LPSTR)user_name.data(), (LPDWORD)&out_length);

    return (!lstrcmpiA((LPCSTR)user_name.data(), s.c_str()));
}

Code sample is taken from InviZzzible tool


Countermeasures

Change user name to non-suspicious one.


Detections table

Check if username is one of the following:
Detect String
[general] admin
andy
honey
john
john doe
malnetvm
maltest
malware
roo
sandbox
snort
tequilaboomboom
test
virus
virusclone
wilbert
Nepenthes nepenthes
Norman currentuser
ThreatExpert username
Sandboxie user
VMware vmware


2. Check if the computer name is specific

Please note that checks are not case-sensitive.

Function used:

  • GetComputerNameA/W

Code sample

bool is_computer_name_match(const std::string &s) {
    auto out_length = MAX_PATH;
    std::vector<uint8_t> comp_name(out_length, 0);
    ::GetComputerNameA((LPSTR)comp_name.data(), (LPDWORD)&out_length);

    return (!lstrcmpiA((LPCSTR)comp_name.data(), s.c_str()));
}

Code sample is taken from InviZzzible tool


Countermeasures

Change computer name to non-suspicious one.


Detections table

Check if computer name is one of the following:
Detect String
[generic] klone_x64-pc
tequilaboomboom
Anubis TU-4NH09SMCG1HC
InsideTm


3. Check if the host name is specific

Please note that checks are not case-sensitive.

Function used:

  • GetComputerNameExA/W

Code sample

bool is_host_name_match(const std::string &s) {
    auto out_length = MAX_PATH;
    std::vector<uint8_t> dns_host_name(out_length, 0);
    ::GetComputerNameExA(ComputerNameDnsHostname, (LPSTR)dns_host_name.data(), (LPDWORD)&out_length);

    return (!lstrcmpiA((LPCSTR)dns_host_name.data(), s.c_str()));
}

Code sample is taken from InviZzzible tool


Countermeasures

Change host name to non-suspicious one.


Detections table

Check if host name is one of the following:
Detect String
[generic] SystemIT


4. Check if the total RAM is low

Functions used to get executable path:

  • GetMemoryStatusEx

Code sample

BOOL memory_space()
{
    DWORDLONG ullMinRam = (1024LL * (1024LL * (1024LL * 1LL))); // 1GB
    
    MEMORYSTATUSEX statex = {0};
    statex.dwLength = sizeof(statex);
    GlobalMemoryStatusEx(&statex); // calls NtQuerySystemInformation
    
    return (statex.ullTotalPhys < ullMinRam) ? TRUE : FALSE;
}

Credits for this code sample: al-khaser project


Countermeasures

Patch/hook NtQuerySystemInformation to return new number of PhysicalPages in SystemBasicInformation.

Tip: in this case its 1st argument is equal to 2 - SystemPerformanceInformation enum value.

Alternatively, patch NumberOfPhysicalPages in KUSER_SHARED_DATA.


5. Check if the screen resolution is non-usual for host OS

The following set of functions is used:

  • GetDesktopWindow
  • GetWindowRect

Alternatively:

  • GetSystemMetrics
  • SystemParametersInfo
  • GetMonitorInfo

Code sample

Take a look at this StackOverflow thread.


Countermeasures

Change screen resolution for it to match the resolution of usual host (1600x900, for example).


6. Check if the number of processors is low

Function used:

  • GetSystemInfo

Besides this function numbers of processors can be obtained from PEB, via either asm inline or intrinsic function, see code samples below.


Code sample (variant 1, al-khaser project)

BOOL NumberOfProcessors()
{
#if defined (ENV64BIT)
	PULONG ulNumberProcessors = (PULONG)(__readgsqword(0x30) + 0xB8);
#elif defined(ENV32BIT)
	PULONG ulNumberProcessors = (PULONG)(__readfsdword(0x30) + 0x64);
#endif

    if (*ulNumberProcessors < 2)
        return TRUE;
    else
        return FALSE;
}

Credits for this code sample: al-khaser project


Code sample (variant 2, al-khaser project, asm inline)

__declspec(naked)
DWORD get_number_of_processors() {
    __asm {
        ; get pointer to Process Environment Block (PEB)
        mov eax, fs:0x30

        ; read the field containing target number
        mov eax, [eax + 0x64]

        ; return from function
        retn
    }
}

Credits for this code sample: al-khaser project


Code sample (variant 3, pafish project)

int gensandbox_one_cpu_GetSystemInfo() {
    SYSTEM_INFO si;
    GetSystemInfo(&si);
    return si.dwNumberOfProcessors < 2 ? TRUE : FALSE;
}

Credits for this code sample: pafish project


Countermeasures

Assign two or more cores for Virtual Machine.

As an alternative solution, patch/hook NtCreateThread to assign specific core for each new thread.


7. Check if the quantity of monitors is small

Functions used:

  • EnumDisplayMonitors
  • GetSystemMetrics (SM_MONITOR)

Code sample

BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData)
{
    int *Count = (int*)dwData;
    (*Count)++;
    return TRUE;
}

int MonitorCount()
{
    int Count = 0;
    if (EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, (LPARAM)&Count))
        return Count;
    return -1; // signals an error
}

Credits for this code sample: StackOverflow forum


Countermeasures

Add at least one monitor to virtual environment.


8. Check if the hard disk drive size and free space are small

Functions used:

  • DeviceIoControl(..., IOCTL_DISK_GET_LENGTH_INFO, ...)
  • GetDiskFreeSpaceExA/W

Code sample (checking drive total size)

int gensandbox_drive_size() {
    GET_LENGTH_INFORMATION size;
    DWORD lpBytesReturned;

    HANDLE drive = CreateFile("\\\\.\\PhysicalDrive0", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
    if (drive == INVALID_HANDLE_VALUE) {
        // Someone is playing tricks. Or not enough privileges.
        CloseHandle(drive);
        return FALSE;
    }
    BOOL result = DeviceIoControl(drive, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, &size, sizeof(GET_LENGTH_INFORMATION), &lpBytesReturned, NULL);
    CloseHandle(drive);

    if (result != 0) {
        if (size.Length.QuadPart / 1073741824 <= 60) /* <= 60 GB */
        return TRUE;
    }

    return FALSE;
}

Credits for this code sample: al-khaser project


Code sample (checking drive free space)

int gensandbox_drive_size2() {
    ULARGE_INTEGER total_bytes;

    if (GetDiskFreeSpaceExA("C:\\", NULL, &total_bytes, NULL))
    {
        if (total_bytes.QuadPart / 1073741824 <= 60) /* <= 60 GB */
        return TRUE;
    }

    return FALSE;
}

Credits for this code sample: al-khaser project


Countermeasures

Against checking disk size: filter IRP device control requests to \\Device\\HarddiskN with specific CTL-codes:

  • DRIVE_GEOMETRY_EX
  • DRIVE_LAYOUT_EX
  • PARTITION_INFO_EX

Against checking free space: patch/hook NtQueryVolumeInformationFile to process these classes:

  • FileFsSizeInformation
  • FileFsFullSizeInformation

in case if handle points to \\Device\\HarddiskVolumeN.


9. Check if the system uptime is small

Function used:

  • GetTickCount
  • GetTickCount64
  • NtQuerySystemInformation

Code sample

bool Generic::CheckSystemUptime() const {
    const DWORD uptime = 1000 * 60 * 12; // 12 minutes
    return GetTickCount() < uptime;
}

Code sample is taken from InviZzzible tool

Code sample

#define MIN_UPTIME_MINUTES 12
BOOL uptime_check()
{
    ULONGLONG uptime_minutes = GetTickCount64() / (60 * 1000);
    return uptime_minutes < MIN_UPTIME_MINUTES;
}


Code sample

BOOL uptime_check2()
{
    SYSTEM_TIME_OF_DAY_INFORMATION  SysTimeInfo;
    ULONGLONG uptime_minutes;
    NtQuerySystemInformation(SystemTimeOfDayInformation, &SysTimeInfo, sizeof(SysTimeInfo), 0);
    uptime_minutes = (SysTimeInfo.CurrentTime.QuadPart - SysTimeInfo.BootTime.QuadPart) / (60 * 1000 * 10000);
    return uptime_minutes < MIN_UPTIME_MINUTES;
}

Countermeasures

  • Adjust KeBootTime value
  • Adjust SharedUserData->TickCount, SharedUserData->TickCoundLowDeprecated values


10. Check if the OS was boot from virtual hard disk (Win8+)

Function used:

  • IsNativeVhdBoot // false on host OS, true within VM

Code sample (excerpt from malware)

Take a look at the excerpt from malware here.


Code sample (pafish project)

int gensandbox_IsNativeVhdBoot() {
    BOOL isnative = FALSE;

    IsNativeVhdBoot fnnative = (IsNativeVhdBoot) GetProcAddress(
        GetModuleHandleA("kernel32"), "IsNativeVhdBoot");

    /* IsNativeVhdBoot always returns 1 on query success */
    if (fnnative)
        fnnative(&isnative);
		
    return (isnative) ? TRUE : FALSE;
}

Credits for this code sample: pafish project


Countermeasures

Hook IsNativeVhdBoot and change its result to the one required.


Countermeasures

Countermeasures are present in appropriate sub-sections, see above.


Credits

Credits go to open-source projects from where code samples were taken:

Though Check Point tool InviZzzible has them all implemented, due to modular structure of the code it would require more space to show a code sample from this tool for the same purposes. That’s why we’ve decided to use other great open-source projects for examples throughout the encyclopedia.


Go back