Report an incident
Report an incident

Ramnit – in-depth analysis
29 September 2017 | Michał Praszmo | #analysis, #malware, #ramnit

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

    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.

    Executable’s analysis

    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. breakpoint1.png

    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:

    • ApplyExploit
    • CheckBypassed
    • start


    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):

    start routine

    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.


    Static config

    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: datasection.png


    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:

    Packet’s structure:

    Chunks’ structures:

    So if we’d like to send a packet containing some data, we would:

    • 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

    Traffic example:


    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
    GET_INJECTS 0x13 Get webinjects
    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

    Bot registration

    When a bot wants to register itself it sends two encrypted md5 hashes, the data structure of which is following:

    Python code:

    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:


    New variant

    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:

    Python implementation:

    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.

    Additional links


    Yara rules:

    Samples analyzed:

    • Main PE

      • 92460d8ac1d1e9f155ef2ca6dd7abb417df8900a17e95157d4372a2c846e829f
    • rmnsoft.dll

      • be2044fe6f0220dde12c51677f2ef4c45d9dea669073bd052695584e573629e0
    • modules.fll

      • 96a10e07d092f6f429672ce2ca66528aae19de872bda39249135a82477d27a83
    • Module Antivirus Trusted Module v2.0 (AVG, Avast, Nod32, Norton, Bitdefender)

      • 975ed0f933d4a22ca631c5ab77c765cd46c48511d43326b066b4505c6dc911de
    • Module Cookie Grabber v0.2 (no mask)

      • bc977a0f455fc747a7868a7940aa98af10c91c4aae7598310de8b78132436bee
    • Module Hooker

      • a88151b3bf825e26ded28f94addeada095d2cd13791b2153a9594b26d9cfb85e


    Loader sha256:

    • d290225dde1b18bf68c4c42e06638a61fb336c91a2c4e6dd007bcbe7327fcbae
    • c2cae7d9ef91dfcc1ae8f542e0ac64ce66c526d5a4154241855020612d358ee8
    • 1f3fbca46a599b4f221ead7785606451365db45bbbc537ee0c4d019e8984d106
    • 9d723bb1dc375834ebb907271b83dffab44e98b82fa73da6267037f019e4bc83
    • f3567e2b5fc521987f0dd79aff6f3b1328db8e03fa825c3c030080a8b5819564
    • 7689465ba010537b0c29cf18d32a25962bd1605b717733f5953eb1b1eb0a68c9
    • f98ca50b7d07682ac359b97dd68eb924c4cbd825db72c1a132458e9bb765fa1e
    • 4b00b0ece480267af051e7907458381d8a9e8506c7da67b8a8e1d74d45773d68
    • 6ac47d82134385fa73386ff3cd7b2eb7008da2205b3f5af7b41fab45c63f9046
    • 6a1fc689d2ef32ee6288498f8a875c6dc880d7494f46c05d25d0e1f627984e8e
    • 522e935b91307b8c01e0ea8a724985f5b4e01227a761aeccb63b00f0d964f7e9
    • b3e67b5ee899c53f90c9da772592a4709372192542e1297bbce4929a8e1d5c69
    • 71d92cc6dc9273d162a969960b1021e5f18cf39b2c48043e5c5e49db5a58d955
    • da15c2a89334496910b6d966bf91fa25a1c9526c53796e06d166416abe7cf2f4
    • e4353bda9692581ea9743165dfd843238c23bb92e24b778983de80e90ac650a3

    DGA domains for analyzed configs: