Evasions: OS features
Contents
OS features detection methods
1. Checking debug privileges
2. Using unbalanced stack
3. Detect Wine
Countermeasures
Credits
OS features detection methods
Evasions in this group use peculiarities of how OS work.
1. Checking debug privileges
If the malware is running under debugger or in a sandbox like Cuckoo its process token will have a debug privilege in the enabled state. It happens because this privilege is enabled in the parent process and inherited by the malware process.
The malware tries to open crucial system processes like csrss.exe, smss.exe, lsass.exe with PROCESS_ALL_ACCESS access right and then tries to terminate them. This will fail in a normal case when the malware is executed from the explorer or command line because even an Administrator user can’t terminate those processes. But this will succeed if the process token has the debug privilege in the enabled state. Termination of crucial system process leads OS to crash into BSOD with an error 0x000000F4 so the emulation process will be aborted.
Functions to get snapshot of running processes:
- CreateToolhelp32Snapshot
- psapi.EnumProcesses (WinXP, Vista)
- kernel32.EnumProcesses (Win7+)
Function used to open the process:
- OpenProcess(PROCESS_ALL_ACCESS, ..., pid) // track for PIDs of 'csrss.exe', 'smss.exe', 'lsass.exe'
Code sample
Credits for this code sample: al-khaser project
Signature recommendations
If OpenProcess requests all the possible rights when opening one of the critical system processes — it’s a strong indicator of malware trying to apply this evasion technique.
2. Using unbalanced stack
This technique was presented at Virus Bulletin 2016 by Check Point Malware Reverse Engineering Team. It is described by this link.
To track process behaviour, the CuckooMon/Cuckoo Monitor module hooks relevant functions. In this type of architecture, the hook is called before the original function. A hooked function may use some space on the stack in addition to that used by the original function. Therefore, the total space on the stack used by the hooked function may be larger than the space used only by the original function.
Problem: The malware has information about how much space the called function uses on the stack. It can therefore move the stack pointer towards lower addresses at an offset that is sufficient to store the function arguments, local variables and return address to reserve space for them. The malware fills the space below the stack pointer with some relevant data. It then moves the stack pointer to the original location and calls the library function. If the function is not hooked, the malware fills in the reserved space before the relevant data (see Figure 1). If the function is hooked, the malware overlaps relevant data, because the space that was reserved for the original function’s local variables is smaller than the space occupied by the hook and the original function’s local variables combined. The relevant data is therefore corrupted (see Figure 2). If it stores pointers to some functions that are used later during the execution process, the malware jumps to arbitrary code, occasionally crashing the application.
Stack on non-hooked and on hooked function call.
Solution: To avoid this behaviour, the Cuckoo Monitor/CuckooMon module can use a two-stage hooking process. In the fi rst stage, instead of the hook’s code execution, it can move the stack pointer towards lower addresses of a specifi c size that will be enough for the malware’s relevant data. Then, the function’s arguments are copied under the new stack pointer. Only after these preparatory operations have been completed is the second stage hook (which performs the real hooking) called. Relevant data fi lled in by the malware resides on upper stack addresses, thus it is not affected in any way by the called function.
Code sample
Signature recommendations
Signature recommendations are not provided as it’s pretty tricky to track such a behavior on malware side.
3. Detect Wine
The MulDiv API is being called with specific arguments (MulDiv(1, 0x80000000, 0x80000000)
) which should logically return 1 - however, due to a bug with the ancient implementation on Windows, it returns 2.
There are more known evasion methods to detect Wine like the good old check of searching for the existence of one of Wine’s exclusive APIs such as kernel32.dll!wine_get_unix_file_name
or ntdll.dll!wine_get_host_version
) as also mentioned in Processes evasion techniques.
Code sample
Signature recommendations
Check if MulDiv(1, 0x80000000, 0x80000000)
is being called.
Countermeasures
- versus checking debug privileges: hook OpenProcess and track for critical system processes PIDs — then return an error.
- versus using unbalanced stack: 1) stack adjusting before function call; 2) kernel-mode hooking.
- versus Detect Wine: If Using Wine, hook MulDiv to return 2 or modify the implementation as it works in Windows.
Credits
Credits go to open-source project from where code samples were taken:
- al-khaser project on github
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.