If we look on Ramnit’s history, it’s hard to exactly pin down which malware family it actually belongs to. One thing is certain, it’s not a new threat. It emerged in 2010, transferred by removable drives within infected executables and HTML files.
A year later, a more dangerous version was released. It contained a part of recently leaked Zeus source code, which allowed Ramnit to become a banking trojan.
These days, it has become much more sophisticated by utilizing a number of malicious activities including:
- Performing Man-in-the-Browser attacks
- Stealing FTP credentials and browser cookies
- Using DGA (Domain Generation Algorithm) to find the C&C (Command and Control) server
- Using privilege escalation
- Adding AV exceptions
- Uploading screenshots of sensitive information
- encrypt large (>4bytes) chunk data using RC4 with a key recovered from the XOR decryption
- create packed chunks from data parts
- concatenate all chunks together
- wrap the output in packet layer
Module Antivirus Trusted Module v2.0 (AVG, Avast, Nod32, Norton, Bitdefender)
Module Cookie Grabber v0.2 (no mask)
Despite Europol’s shut down of 300 C&C servers in 2015, it’s still going strong, recently being distributed by RIG EK via seamless gates.
The main binary is packed like a matryoshka – a custom packing method first and then UPX.
Despite being encrypted, extracting the binary from the packer is pretty straight-forward – all one needs to do is to set a breakpoint right after the binary decrypts the code and before it jumps into it.
And if we now navigate to the newly unpacked code section we’ll find the binary right after the loader assembly:
The unpacked binary (after UPX decompression) consists of 3 general functions:
If the current user is not already an admin and the process is not running with admin privileges it tries to perform privilege escalation.
Malware contains exploits for CVE-2013-3660 (patched in MS13-053) and CVE-2014-4113 (patched in MS14-058) vulnerabilities, however before it actually tries to run the payload, registry checks are performed to make sure that the host system is indeed vulnerable to said CVEs:
If the exploits succeed or the program is already running with high privileges, a “TRUE” value is stored in a hardcoded random-looking registry key: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\jfghdug_ooetvtgk, which is later used in the CheckBypassed function.
This function checks if previously mentioned registry key is set. If not and process has admin privileges, updates it. Assuming the exploit has worked, Ramnit then adds registry keys to evade Windows’ security systems detection (see Obfuscation/Evasion):
The routine coordinates ApplyExploit and CheckBypassed – if they both run successfully it creates two svchost.exe processes and writes rmnsoft.dll and modules.dll into them respectively.
Important detail: the binary executes CheckBypassed before ApplyExploit, so the binary has to be executed again in order to make any further progress. This trick outsmarts many single-run malware analysis systems, such as Cuckoo.
Ramnit encrypts its network communication using RC4 algorithm. Key for RC4 and botnet name are encrypted using xor with a hardcoded password.
XOR encryption is pretty standard, the only catch is that it skips key’s first char and then reverses the key.
XOR function calls:
Ciphertext lengths are almost always too long and we have to rely on null termination:
DGA config seems to be always declared at the beginning of the data section:
Program copies itself into C:\Users\User\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\.
Ramnit generates a list of domains by using a LCG algorithm with a hardcoded seed:
Generating a domain:
DGA recreated in Python:
Ramnit connects to C&C servers through port 443, but don’t let that fool you – it doesn’t use HTTPS, but its own protocol instead:
So if we’d like to send a packet containing some data, we would:
Some of available commands:
|Command||Byte Value||Short Description|
|COMMAND_OK||0x01||Server’s response that the command executed successfully|
|GET_DNSCHANGER||0x11||Get DNS-changer payload|
|UPLOAD_COOKIES||0x15||Upload stolen cookies (zip format)|
|GET_MODULE||0x21||Get a specific module|
|GET_MODULE_LIST||0x23||Get a list of downloadable modules|
|VERIFY_HOST||0x51||Check if the host is able to send a signed message|
|REGISTER_BOT||0xe2||Register bot (send two MD5s)|
|UPLOAD_INFO_GET_COMMANDS||0xe8||Upload detailed machine info|
When a bot wants to register itself it sends two encrypted md5 hashes, the data structure of which is following:
If C&C responds with a success packet (00ff0100000001), malware follows up with a empty 0x51 command. Signature from the response is verified using a hardcoded public RSA key. If there is a mismatch – the execution stops.
The program can request a list of modules and then download each one individually:
Antivirus Trusted Module v2.0
Adds exceptions to a fixed list of anti-virus software (AVG Anti-Virus, BitDefender, Avast, ESET NOD32 Antivirus, Norton AntiVirus)
Chrome reinstall module (x64-x86) v0.1
Uninstalls Google Chrome
and installs it again:
Cookie Grabber v0.2 (no mask)
Steals cookies from various hardcoded locations and sends a zip with results to the C&C through rmnsoft.dll.
Used for performing Man-in-the-Browser attacks and hooking HTTP functions.
Webinjects are a relatively new addition to Ramnit. They utilize a standard Zeus format:
Obfuscation / Evasion
Ramnit attempts to hide itself from Windows Defender by adding following registry values:
‘NOPs’ are inserted in random functions, which makes them difficult to find using e.g. Yara rule:
During writing of this article we’ve noticed a variation of Ramnit called clickbideu in an Italian spam campaign.
Its loader is completely different, but the communication module (rmnsoft.dll) has remained somewhat unchanged with only some minor differences:
DGA cycles between 3 hardcoded TLDs instead of just one:
Also new version seems to be using different port – 8001, although we’ve also seen usage of port 442.
Additionally, a different value (“fE4hNy1O”) is used for calculating the second md5.