In my previous blog post on L0rdix RAT, I took a look at its panel and builder components that have been circulating through underground forums recently. As part of that analysis, I identified a key (“3sc3RLrpd17”) which was embedded in one of the PHP pages in L0rdix’s panel. A SHA-256 hash is calculated of this key, which is used as the AES key to encrypt and decrypt L0rdix’s command and control (C2) communications. When a sample is generated using L0rdix’s builder, the operator is able to decide this key.
In this post, I examine L0rdix’s C2 encryption and decryption functions in more detail and discuss how to automate the task of identifying, decrypting and extracting L0rdix C2 traffic from a PCAP using Python.
L0rdix’s configuration structure
L0rdix’s configuration contains 10 fields, which are encrypted and sent as URL query strings in a HTTP POST request to the connect.php page of the panel. The configuration settings of deployed bots are updated by sending similar POST requests to the bots from the panel.
|Query String||Configuration Field|
|p=||Privileges of current user|
|f=||L0rdix profile in use|
L0rdix C2 encryption and decryption steps
L0rdix encrypts its C2 communications using the following steps:
- Encrypts the plaintext using AES in Cipher Block Chaining (CBC) mode with a 256-bit key and 16-byte initialisation vector (IV).
- Base64 encodes the ciphertext.
- Replaces plus (+) characters with tildes (~).
- URL encodes the ciphertext.
Figure 1 – L0rdix RAT’s C# encryption function.
For example, the ciphertext of “Windows 7 Enterprise” looks like this:
We can decrypt the ciphertext by performing the encryption actions in reverse:
- buNpZksa9PSEshjHiM9XNI84ku2X6Zy2Syr7zdzvxMM= (After URL decoding)
- 6ee369664b1af4f484b218c788cf57348f3892ed97e99cb64b2afbcddcefc4c3 (Hex representation after Base64 decoding)
- Windows 7 Enterprise (After AES decryption)
Default key or single operator
After analysing more L0rdix samples in the wild, it became clear that many of them use the key found in the leaked panel to encrypt their C2 channels. There are two realistic possibilities for the re-occurrence of this key:
- “3sc3RLrpd17” is the default key that the RAT panel is supplied with from its author and several buyers have not changed it.
- The L0rdix samples that use this key are bots controlled by a single operator. Based on the implementation of the encryption and decryption functions, each L0rdix panel operator must use the same key for every bot they control.
There is stronger evidence to indicate that the first possibility is true. For instance, the key is referenced in a coding tutorial on how to encrypt and decrypt data using AES in C# and PHP. L0rdix’s server side encryption and decryption functions closely resemble those in the tutorial, sharing the method (AES-CBC 256), IV (16 null bytes), key (“3sc3RLrpd17”) and programming languages used (C# and PHP). L0rdix’s author may have copied the tutorial’s encryption implementation and decided not to change the key.
Figure 2 – L0rdix panel’s PHP decryption function, including the suspected default operator key.
Figure 3 – Coding tutorial on AES-256 encryption and decryption in PHP.
Automating L0rdix C2 decryption with decrypt_l0rdix_c2.py
Since L0rdix uses symmetric key encryption it was possible to write a Python script (decrypt_l0rdix_c2.py) to parse a PCAP containing L0rdix C2 traffic and decrypt it. The script first identifies L0rdix traffic based on its expected structure by parsing a PCAP using the Pyshark library. For example, since L0rdix has 10 fields in its configuration, there should be at least 10 query strings in a L0rdix C2 URL. The query strings are identified and decoded into a ciphertext before being run through an AES decryption function using the Pycryptodome library.
The script also extracts screenshots that L0rdix RAT periodically takes of infected systems. The traffic is decrypted using the suspected default operator key (“3sc3RLrpd17”), or a user supplied key using the optional -k argument. You can extract the operator key from a L0rdix bot using static analysis. If a L0rdix operator has not changed the operator key from the default one, any captured C2 traffic between their bots and the admin panel can be decrypted using decrypt_l0rdix_c2.py. The script is available to download from GitHub.
Figures 4 and 5 show the output from running the script against L0rdix C2 traffic:
- decrypt_l0rdix_c2.py -p l0rdix_c2.pcap
Figure 4 – Output from decrypt_l0rdix_c2.py showing identified L0rdix traffic.
Figure 5 – Output from decrypt_l0rdix_c2.py showing extracted screenshots and decrypted traffic. You can see the decrypted values of L0rdix’s configuration.