Don’t get Caught by Raspberry Robin: Dissecting the evasion methods
Recently, the SonicWall Capture Labs Research team analyzed a Raspberry Robin, which is known for its endless anti-evasion’s techniques and multiple layers of packing. The layers have several anti-debugger, anti-sandbox, anti-VM and anti-emulator checks. The malware keeps evolving over the time and intensified itself to become more robust by adding various evasions and tactics.
Overview:
Raspberry Robin is packed with 14 layers, each one is heavily obfuscated and performing a particular goal. From the structure of each layer, we can understand that initially it began as PE files but were changed into unique encrypted structures without PE headers that could only be retrieved and decrypted by the preceding layers.
Once Raspberry Robin identified the execution is happening in a controlled environment then it mislead the execution flow in a variety of ways:
- Terminate execution of the malware.
- Executes in a infinite loop.
- Generate a exception and terminates.
- Execution of fake payload instead of real payload.
Obfuscation:
Malware does an extensive use of obfuscation. This makes it exceedingly difficult to statically analyze anti-analysis tactics and figure out how to get malware to unpack itself by passing all the checks. Malware uses API hashing to retrieve API addresses. Malware only uses VirtualAlloc and VirtualProtect API’s to unpack next layer.
Series of Layers:
Start:
Malware directly starts decryption of layer 1, which is stored in .data section, using simple XOR and jump to it:
Layer 1:
This layer decrypts the next layer and starts its execution.
Layer 2:
It is a DLL file with no import and exports directory:
It has one unique check , where it initially set cx = 2. After performing some instruction it checks if cx is still equal to 2. Since cx value should remain the same. The gs selector’s value would be reset by a single step event and a new value would be placed into cx at the end of the procedure.
This layer decrypts the next layer and starts its execution.
Layer 3:
This layer decrypts the next layer and starts its execution.
Layer 4:
This layer decrypts the next layer and starts its execution:
Layer 5:
Here, malware allocates large memory buffer with PAGE_WRITECOMBINE flag, where it first writes and then reads from it, evaluating read/write performance. Malware loops this check 32 times and compares that write performance is at least 6th times more than read performance.
This check focuses on the execution in the emulator, if it is unsuccessful, malware will choose an incorrect RC4 key and leads to crash.
Function responsible for write-read performance check:
Malware performs above operation 32 times:
After successfully bypassing above check, it decrypts the next layer and starts its execution.
Layer 6:
It performs simple task of decryption by using very complex calls. Check the below call graph of this layer.
This layer decrypts the next layer and starts its execution.
Layer 7:
Every time malware has to call any API, it search for the required module in PEB->InLoadOrderModuleList. If the module found, it retrieves the address of required API from exports:
This layer decrypts the next layer and starts its execution.
Layer 8:
In this layer malware creates a new thread , which executes below mentioned checks as a separate function one by one:
1:
- Malware checks NtMinorVerion and NtMajorVerionfields of KUSER_SHARED_DATA structure to get operating system version. At least windows 7 required to continue its execution:
- Malware check KdDebuggerEnabled field of KUSER_SHARED_DATA structure to detect presence of kernel debugger:
- Malware checks BeingDebugged and NtGlobalFlag fields of PEB structure to detect user mode debugger:
2:
- Malware iterates through USERNAME and COMPUTERNAME environment variables to check for blacklisted user names and computer names:
3:
- Malware uses CPUID instruction with multiple values of EAX to get various information about system processor. It sets EAX=0x01 to check whether it is running in Hypervisor or not. It sets EAX = 0x0 to get processor family name such as GenuineIntel is defined for intel processors. It set EAX =0x1c but this is invalid as per intel’s developer documentation. It sets EAX = 0x40000000 to check vendor ID string:
4:
- Malware uses NumberOfPhysicalPages field of KUSER_SHARED_DATA structure to get ram size. It does to compare with minimum threshold to continue its execution:
5:
- Malware gets Hash of absolute process path then check it against blacklisted paths which are generally used by sandbox:
6:
- Malware implements an anti emulation method based on FileMapping. It creates a section of approx. 57MB size then it maps created section 9 times into malware’s memory address space. After mapping , it write’s dummy instructions and jump instruction at the end of each section:
7:
- Malware get MAC address of machine using GetAdaptersAddresses API and check it against default adapter addresses of virtual machines:
8:
- Malware check ProductId of HardDisk and compares it against blacklisted names. It uses DeviceIOControl API to get information about HardDisk:
9:
- Malware check for display device name of system and compares it against blacklisted names. It uses EnumDisplayDevicesW API to get list of display devices:
10:
- Malware checks for hashes of running process names against process names related to virtual environment and analysis tools. To fetch running processes names malware use NtQuerySystemInformation API with SystemProcessInformation class as parameter:
- Also malware uses PEB->InLoadOrderModuleList to list all DLL modules, hashing each of module’s name and compare against hardcoded list of blacklisted modules. Function for checking DLL modules name:
- Name Hashing Algorithm:
11:
- Malware checks for sandbox related files in C: folder:
12:
- Malware uses NtQuerySystemInformation API with SystemVhdBootInformation = 0x70 class to get virtual hard disk boot information. It also uses NtQuerySystemInformation API with SystemFirmwareTableInformation = 0x4C class to get firmware table information:
13:
- Malware check whether default execution of VBA macro’s is enabled or not. For this it queries registry key using SHGetValueW API:
Malware has a variety of anti-analysis checks in this Layer. If malware is successful in detecting an analysis environment in at least one check, It will unpack and run the fake payload rather than the real payload
LAYER 9:
On physical machine MulDiv API returns value 2 but on WineHQ’s MulDiv’s API implementation it returns value 1. So malware makes use of this opportunity and detects its execution under wine successfully:
Runtime call to allocated region:
It decrypts the next layer and starts its execution.
Layer 10:
Strings from the fake loader:
LAYER 11:
Malware drops fake payload into %TEMP% directory and execute it.
Fake Payload:
LAYER 12:
It decrypts the next layer and starts its execution.
LAYER 13:
It decrypts the next layer and starts its execution.
LAYER 14:
Raspberry Robin’s Main payload is unpacked.
SonicWall Capture Labs provides protection against this threat via the following signature:
- GAV: Roshtyak.A (Trojan)
This threat is also detected by SonicWall Capture ATP w/RTDMI and the Capture Client endpoint solutions.