Unlocking Lockton Ransomware

Be careful where you leave your keys

Yes… I’ve reused/reworded parts of my last post for this one because who doesn’t like to be “efficient”

A couple of days ago, I spotted this post by @MalGamy12 about another new Linux ransomware sample on the block, dubbed Lockton Ransomware. The post by @MalGamy12 is believed to be the first ‘In The Wild’ (ITW)’ sample available for analysis, uploaded to VirusTotal just last week.

I was curious to see if this sample would prove to be more challenging than my previous competitor.

What Are We Working With

The sample can be found on VirusTotal here.

File Description SHA256
Lockton ELF 64-bit cf37b3caea9b8f6bf3297f2d9c562703ad0eb4f6a27df9b105bd7c9aa9ca95ee

Technical Analysis

For this sample, I decided to start with some static analysis.

Static Analysis

I kicked things off by loading the file into Ghidra and letting the analyser run. This was to try and ascertain what the file was written in (given most things I’ve seen lately are Go or Rust). As it turns out, this binary is likely written in C++, based on the decompiled instructions and detected ELF Source Files:

c_refs

It was also noted that this file required some specific Shared Objects (also called shared libraries)

  • libcrypto++.so.8
  • libfltk.so.1.3
  • libstdc++.so.6
  • libgcc_s.so.1
  • libc.so.6

As I was to discover during my dynamic analysis, the libraries in bold are not necessarily installed by default on a lot Linux distros. for instance, the libfltk library is used as part of the Flat ToolKit which is an open source GUI toolkit. Therefore, some would be victims may be safe by default as these libraries are required for the binary to run as there seems to be no fallback to allow the binary to run.

Moving on, I performed a basic strings search which provided some noteworthy results:

encryptedfiles.txt
Unable to open encryptedfiles.txt for writing.
Unable to open encryptedfiles.txt for reading.
File listed in encryptedfiles.txt does not exist: 
Lockton Ransomware
Instructions
Your files have been encrypted. To recover them, please follow the instructions below. DO NOT CLOSE THIS WINDOW OR POWER OFF YOUR DEVICE!
IF YOU DO SO YOU WILL BE UNABLE TO RECOVER YOUR FILES!
1. Download the official Monero wallet from getmonero.org.
2. Purchase [INSERT AMOUNT OF USD] worth of Monero and send it to the following Monero address:
   [INSERT MONERO ADDRESS]
3. After sending the payment, download Dino XMPP and send the ransom payment transaction ID to the following XMPP.
   [INSERT XMPP]
4. After we verify you have paid your ransom, we will respond to your message with the decryption key.
5. Use the decryption key to recover your encrypted files below.
Decryption Key:
Decrypt Files
/home
Files have been decrypted successfully.
Decryption key is incorrect. Please try again.
gtk+
1BD0B3CFB4FCB84DEA46826619880D255037BFB6996E3EAF44FA49D831D7B33D

Based on the strings, it looks like this binary has the capabilities to:

  • Encrypt files
  • Log files that have been encrypted
  • Decrypt files
  • Potential hardcoded file path and key

main

By looking at the binary in Ghidra, we can establish that there is very likely a hardcoded key based on recovered naming. Within main there is a reference to hardcoded_key. Pulling on this thread (by finding the XREF of the key looking hex string above), establishes a function _GLOBAL__sub_I_log_encrypted_file which initialises prior to main starting. This function calls __static_initialization_and_destruction_0 which shows the value being assigned:

hard_key

Back to main and we can confirm that a GUI is utilised with the aptly named “RansomwareWindow” naming used. A look at into the associated function validates a GUI based on the FLTK library calls to build the GUI and provide content, which just so happens to contain the ransom note (albeit without the key data like contact and payment info populated). At this stage, what I found interesting was the inclusion of the decrypt widgets:

ransom_win_build

Finally, prior to the call for showing the GUI, we have a call to process_directory. From code analysis we can presume the arguments passed will include:

proc_dir_call

process_directory

By default, a true value is passed to the function, meaning that it will process files and directories recursively to encrypt files. If a false value is passed i.e. when the Decrypt Files button in the GUI is pushed, it will go down the decryption route of reading encryptedfiles.txt and calling the decrypt function.

As one would expect given the nature of the binary, the encrypt_file and decrypt_file functions take a filename (pointer), and the key value as input to do the necessary processing.

encrypt_file

Moving into this function, we see that the binary is utilising Crypto++ library to setup the encryption algorithm to use. The general flow is as follows:

  • Open & read file, storing contents in a basic_string
  • Decode the hardcoded_key from hex using HexDecoder
  • Generate 16 bytes of random data for an IV
  • Set up the cipher using CryptoPP
  • Encrypt the data stored from earlier
  • Write IV to the output file
  • Write encrypted data to the output file
  • Checks file length to verify encryption and calls log_encrypted_file

So, what we see is quite a common ransomware flow that includes adding the IV to each file in order to aid decryption (of course the correct key is also required).

Cipher Identification

So far, we’ve identified an IV is required for encryption and the library it utilises. Now we can establish the crypto algorithm used in this sample from either the encrypt or decrypt functions by checking out the call to CipherModeFinalTemplate_CipherHolder. The Crypto++ library is template-based. This means the template defines the encryption algorithm and its behaviour. In this case, the ransomware leverages AES-256 in OFB mode. While the template itself might not explicitly state the key length, we can determine it by analysing the size of the hardcoded key within the binary.

crypto_used

decrypt_file

We’ve established a good amount of detail about the encryption used by this binary so far. With this knowledge, and a review of the code we can outline the general decryption flow as follows:

  • Decode the hardcoded_key from hex using HexDecoder
  • Set up the cipher using CryptoPP
  • Open the encrypted file
  • Read the first 16 bytes (IV)
  • Finalise cipher setup with the IV
  • Read the encrypted data
  • Decrypt and write the data back into a new file with the same name

This sample has been quite enjoyable to look at and learn from up to this point. One item to note is that given this is ransomware, there is often a list of file types or extensions to target which I have not seen within this sample. Let’s move onto some dynamic analysis and confirm some of our findings.

Dynamic Analysis

As I’ve done with other Linux samples lately, I’ve mapped the memory from gdb for the binary to those in Ghidra for easier setting of breakpoints. Having done this, I was able to establish the following args being passed to the functions of interest - I’ve put generic variable names in for encrypt/decrypt:

555678f9 - CALL to process_directory
Guessed arguments:
arg[0]: 0x7fffffffdd40 --> 0x7fffffffdd50 --> 0x656d6f682f ('/home')
arg[1]: 0x7fffffffdd20 --> 0x55555558c270 ("1BD0B3CFB4FCB84DEA46826619880D255037BFB6996E3EAF44FA49D831D7B33D")
arg[2]: 0x1 

5556762e - CALL to encrypt_file 
Guessed arguments:
arg[0]: 0x7fffffffdac0 --> 0x5555555b9c20 ("/home/file_to_enc")
arg[1]: 0x7fffffffdd20 --> 0x55555558c270 ("1BD0B3CFB4FCB84DEA46826619880D255037BFB6996E3EAF44FA49D831D7B33D")

As expected from static analysis findings, the binary defaults to the recursive encryption of files within /home. Once all the files have been encrypted, you are presented with the GUI window:

ransom_window

It is worth coming back to a point I made earlier in that there is no file filter for this ransomware, instead it just targets any file within /home.

Anyway, now our files are encrypted (Oh no!) which can be validated by trying to open or cat any to terminal. Let’s pass a random incorrect key to the decrypt input box and see what happens… Decryption key is incorrect. Please try again..

As expected I guess. However, doing this confirmed the control flow of the binary and the args passed to the decrypt function:

55567743 - CALL to decrypt file 
Guessed arguments:
arg[0]: 0x5555556373b0 --> 0x5555555e0000 ("encrypted_file_path")
arg[1]: 0x7fffffffd490 --> 0x5555555e09c0 ("decryption_key")

Next, we try providing the hardcoded key: 1BD0B3CFB4FCB84DEA46826619880D255037BFB6996E3EAF44FA49D831D7B33D which returns: Files have been decrypted successfully.

Successful decryption was confirmed by reviewing what was the previously encrypted files.

Note - if run or testing from a terminal window, profile files in use such as .zshrc will not be recovered by the decrypt_file function.

We can also manually test decryption based on the findings from static analysis using CyberChef. To do this, I took a hexdump of an encrypted file (.zshrc) and converted it into hex so I could extract the IV easily. Using the IV and hardcoded key against the remaining data, and with OFB mode selected, successfully recovers the file data.

Conclusion

In contrast to my recent analysis of AkitaCrypt, this ransomware sample demonstrates a higher level of sophistication in its code structure and encryption methods, which align closely with techniques commonly employed by Windows ransomware. However, the presence of a hardcoded encryption key and placeholder text in the ransom note strongly suggests that this could be a test version or an early-stage development sample.

Interestingly, during my research, I discovered another sample on VirusTotal that shares the same hardcoded key (hash provided in the IoC section). This further supports the theory that this ransomware is still in its developmental phase, with potential for more refined versions to emerge in the future.


IoCs

Hardcoded Encryption Key:
1BD0B3CFB4FCB84DEA46826619880D255037BFB6996E3EAF44FA49D831D7B33D

SHA256:
cf37b3caea9b8f6bf3297f2d9c562703ad0eb4f6a27df9b105bd7c9aa9ca95ee
1a1fb87d76abf41ca90a476ff1aa6d6883db0a8848eba839b6b3826d19523a77


Detection and Decryption

Based on the IoCs from this sample, I’ve crafted a Yara rule to help detect this ransomware in the wild. If newer or updated samples are discovered then the rule can always be adapted from here.

Additionally, I’ve made a decryption script for this ransomware here. This script enables victims to decrypt their files (knowing the key) without needing to execute the ransomware binary (which may have been contained by antivirus software or an incident response team).

Share: X Facebook LinkedIn