Tricks used by malware authors to protect their malicious code from detection

In our last two posts we’ve shown how vendors like Symantec and Microsoft (among others) miss detecting threats due to the nature of how their engines operate.

So how do malware authors know if an environment is safe for them to attack or not?

There are plenty of indicators about a system that they check to determine if there’s a security system like a sandbox which automatically tests malware or a virtual machine (VM) used in some sandbox environments and by security researchers to analyze and debug malware.

So how many processor cores do you have?

Well, most computers and even smartphones nowadays have at least 2 if not more, so if a malware sees only 1, it’s a strong indicator that the machine is used in a VM or sandbox to test the malware.

Let’s see some code examples for Windows OS…

Example #1: The “Straightforward” way

The straightforward way is to ask via the GetSystemInfo and GetNativeSystemInfo WinAPI calls (on x86 OS with x64 processor the latter returns accurate system information, otherwise they’re the same)

SYSTEM_INFO si;
GetNativeSystemInfo(&si); //or GetSystemInfo(&si);
if (si.dwNumberOfProcessors == 1)
   ExitProcess(0);

Example #2:  The “Cross-platform” way

The C++ standard has a call that informs about the number of processors (internally in Windows, it calls GetSystemInfo function)

if (std::thread::hardware_concurrency() == 1)
    exit(0);

Example #3: The “Native” way

WinAPI calls like GetSystemInfo above usually invoke a lower level call (or calls) to ntdll.dll functionality. In this case, the function NtQuerySystemInformation returns the number of cores (and Microsoft even suggests using GetSystemInfo to retrieve this information)

...
SYSTEM_BASIC_INFORMATION sbi;
NtQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi), nullptr);
if (sbi.NumberOfProcessors == 1)
    ExitProcess(0);

Example #4: The “Trickster” way:

When an application runs, it can use any of the existing cores to execute code and Windows allows getting information on which ones are used with a call to GetProcessAffinityMask.

The trick used here is to utilize the last parameter which indicates the system’s affinity (whereas a value of 1 indicates the system was configured to use a single core)

DWORD_PTR dwProcessAffinity, dwSystemAffinity;
GetProcessAffinityMask(GetCurrentProcess(), &dwProcessAffinity, &dwSystemAffinity);
if (dwSystemAffinity == 1)
    ExitProcess(0);

Example #5 : More WinAPI functions

GetActiveProcessorCount

GetCurrentProcessorNumber

GetCurrentProcessorNumberEx

GetLogcalProcessorInformation

GetLogicalProcessorInformationEx

some are not deterministic but can still assist in determining that there’s more than a single core.

Example #6: More Native functions

NtGetCurrentProcessorNumber & NtGetCurrentProcessorNumberEx

RtlGetCurrentProcessorNumber & RtlGetCurrentProcessorNumberEx

RtlGetNativeSystemInformation is undocumented but is similar to NtQuerySystemInformation

Example #7: The “WMI” way

WMI is a system component for querying the OS for its information, including by scripting languages like VBScript & PowerShell, which is why it’s widely used by Fileless malware and malicious scripts to read OS’ data, in our case the query is very simple

SELECT NumberOfCores FROM Win32_Processor

Example #8: Using Environment variables

Some information about the system is exposed by environment variables, and it can be easily read by calling WinAPI’s GetEnvironmentVariable or even C-Runtime’s getenv:

TCHAR buffer[10];
GetEnvironmentVariable(TEXT("Number_of_Processors"), buffer, 10);
if (_ttoi(buffer) == 1)
   exit(0);

BONUS – Example #9: The “Registry” way

This trick is not really used by malware but it’s a nice one as it gives the number in a not-so-intuitive manner by reading the hardware information from the registry (since 0 indicates the first processor, if key 1 exists, the machine has more than 1 core)

HKEY hKey;

if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Hardware\\Description\\System\\CentralProcessor\\1"), 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
    ExitProcess(0);

One can also check the processor’s floating-point entry to get the same indicator by reading

HKLM\Hardware\Description\System\FloatingPointProcessor\1

Conclusion

As you figured it out, malware authors have many ways just to check one simple indicator about a system to determine if it’s safe for them to attack.

Our Deception technology identifies when malware asks the system such questions, it falsifies the information to deter it from executing, protecting the endpoint from attacks without knowing the threat beforehand and without relying on specific, limited indicators about the threats, as oppose to signatures and heuristics.