This blog post was authored by Hasherezade and Jérôme Segura
On November 23, we received an alert from a partner about a resurgence of Gootkit infections in Germany. Gootkit is a very capable banking Trojan that has been around since 2014 and possesses a number of functionalities such as keystroke or video recording designed to steal financially-related information.
In this latest campaign, threat actors are relying on compromised websites to socially engineer users by using a decoy forum template instructing them to download a malicious file.
While analyzing the complex malware loader we made a surprising discovery. Victims receive Gootkit itself or, in some cases, the REvil (Sodinokibi) ransomware. The decision to serve one or the other payload happens after a check with the criminal infrastructure.
Gootkit attacks observed in Germany
Security researcher TheAnalyst was the first to publicly identify an active campaign in November using a sophisticated loader that was eventually attributed to Gootkit, a banking Trojan not observed in the wild for some time. Germany’s Computer Emergency Response Team DFN-CERT later confirmed that German users were being targeted via compromised websites.
Around the same time, we started receiving reports from some of our partners and their ISPs about Gootkit-related traffic. We were able to confirm Gootkit detections within our telemetry that were all located in Germany.
After a couple of days, we remediated over 600 unique machines that had been compromised.
Fake forum template on hacked websites
The initial loader is spread via hacked websites using an interesting search engine optimization (SEO) technique to customize a fake template that tries to trick users to download a file.
The template mimics a forum thread where a user asks in German for help about a specific topic and receives an answer which appears to be exactly what they were looking for. It’s worth noting that the hacked sites hosting this template are not German (only the template is); they simply happen to be vulnerable and are used as part of the threat actor’s infrastructure.
This fake forum posting is conditionally and dynamically created if the correct victim browses the compromised website. A script removes the legitimate webpage content from the DOM and adds its own content (the template showing a link to a file to download).
There is a server-side check prior to each visit to the page to determine if the user has already been served the fake template or not, in which case the webserver will return legitimate content instead.
Fileless execution and module installation
The infection process starts once the victim executes a malicious script inside the zip archive they just downloaded.
This script is the first of several stages that leads to the execution of the final payload. The following diagram shows a high level overview:
The first stage (a version with cleaned formatting available here) decodes the next element:
Block 1 is responsible for reading/writing registry keys under “HKEY_CURRENT_USER\SOFTWARE\<script-specific name>”. It also deobfuscates and runs another block of code:
This fragment of code is responsible for connecting to the C2. It fetches the domains from the list, and tries them one by one. If it gets a response, it runs it further.
The expected response from the server is a decimal string, containing a pseudorandom marker used for validation. It needs to be removed before further processing. The marker consists of “@[request argument]@”.
The downloaded code chunk is responsible for installing the persistent elements. It also runs a Powershell script that reads the storage, decodes it and runs it further.
Stage 3 – The stored payload and the decoding Powershell
The authors diversified the method of encoding and storing the payload. During our tests we observed two ways of encoding. In one of them, the PE is stored as a Base64 encoded string, and in the other as a hexadecimal string, obfuscated by having certain numbers substituted by a pattern.
The payload is usually stored as a list of registry keys, yet we also observed a variant in which similar content was written into a TXT file.
Example of the payload stored in a file:
The content of the file is an obfuscated Powershell script that runs another Base64 obfuscated layer that finally decodes the .NET payload.
Example of the Powershell script that runs to deobfuscate the file:
"C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe" -ExecutionPolicy Bypass -windowstyle hidden -Command "IEX (([System.IO.File]::ReadAllText('C:\Users\[username]\bkquwxd.txt')).Replace('~',''));"
Below we will study two examples of the loader: One that leads to execution of the REvil ransomware, and another that leads to the execution of Gootkit.
Example 1—Loading REvil ransomware
The example below shows the variant in which a PE file was encoded as an obfuscated hexadecimal string. In the analyzed case, the whole flow led to execution of REvil ransomware. The sandbox analysis presenting this case is available here.
Decoded content of the script:
It reads the content from the registry keys and deobfuscates it by substituting patterns. In the given example, the pattern “!@#” in the hexadecimal string was substituted by “1000”, then the PE was decoded and loaded with the help of .NET Reflection.
The next stage PE file (.NET):
The .NET loader comes with a hardcoded string that is the next stage PE: the final malicious payload. The Setup function called by the PowerShell script is responsible for decoding and running the next PE:
The loader runs to the next stage with the help of Process Hollowing – one of the classic methods of PE injection.
Example 2 – Loading Gootkit
In an other common variant, the payload is saved as Base64. The registry keys compose a PowerShell script in the following format:
$Command =[System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String("[content]")); Invoke-Expression $Command;Start-Sleep -s 22222;
After decoding the base64-encoded content, we get another PowerShell script:
It comes with yet another Base64-encoded piece that is further decompressed and loaded with the help of Reflection Assembly. It is the .NET binary, similar to the previous one.
The script calls a function “Install1” from the .NET module. This function loads another PE, that is embedded inside as a base64 encoded buffer:
This time the loader uses another method of PE injection, manual loading into the parent process.
The revealed payload is a Gootkit first stage binary: 60aef1b657e6c701f88fc1af6f56f93727a8f4af2d1001ddfa23e016258e333f. This PE is written in Delphi. In its resources we can find another PE (327916a876fa7541f8a1aad3c2270c2aec913bc8898273d545dc37a85ef7307f ), obfuscated by XOR with a single byte. It is further loaded by the first one.
Loader like matryoshka dolls with a side of REvil
The threat actors behind this campaign are using a very clever loader that performs a number of steps to evade detection. Given that the payload is stored within the registry under a randomly-named key, many security products will not be able to detect and remove it.
However, the biggest surprise here is to see this loader serve REvil ransomware in some instances. We were able to reproduce this flow in our lab once, but most of the time we saw Gootkit.
The REvil group has very strict rules for new members who must pass the test and verify as Russian. One thing we noticed in the REvil sample we collected is that the ransom note still points to decryptor.top instead of decryptor.cc, indicating that this could be an older sample.
Banking Trojans represent a vastly different business model than ransomware. The latter has really flourished during the past few years and has earned criminals millions of dollars in part thanks to large ransom payments from high profile victims. We’ve seen banking malware (i.e. Emotet) turn into loaders for ransomware where different threat actors can specialize in what they do best. Time will tell what this return of Gootkit really means and how it might evolve.
Detection and protection
Malwarebytes prevents, detects and removes Gootkit and REvil via our different protection layers. As we collect indicators of compromise we are able to block the distribution sites so that users do not download the initial loader.
If a system is already infected with Gootkit, Malwarebytes can remediate the infection by cleaning up the registry entries where Gootkit hides:
Finally, we also detect and stop the REvil (Sodinokibi) ransomware:
Indicators of Compromise
Variant 1 (Gootkit):
- NET loader [973d0318f9d9aec575db054ac9a99d96ff34121473165b10dfba60552a8beed4]
- Delphi PE [60aef1b657e6c701f88fc1af6f56f93727a8f4af2d1001ddfa23e016258e333f]
- PE stored in resources [327916a876fa7541f8a1aad3c2270c2aec913bc8898273d545dc37a85ef7307f]
Variant 2 (REvil):
- NET loader [0e451125eaebac5760c2f3f24cc8112345013597fb6d1b7b1c167001b17d3f9f]
- Delphi PE [d0e075a9346acbeca7095df2fc5e7c28909961184078e251f737f09b8ef892b6] – the ransomware
- PE stored in resources [a7e363887e9a7cc7f8de630b12005813cb83d6e3fc3980f735df35dccf5a1341] – a helper component