HTB - Lockpick

jonatan shinkind
8 min read6 days ago

In today’s write-up, we’ll be diving deep into the Lockpick challenge from Hack The Box. This challenge involves dealing with a piece of ransomware.

Our goal is to figure out what this ransomware does and how to unlock the files it has encrypted.

The provided file contains three items: a folder named ‘forela-criticaldata’, a zip file called ‘bescrypt.zip’, and a text file named ‘DANGER.txt’, all of which have been extracted.

The `DANGER.txt` file contains the password needed to unzip `bescrypt.zip`.

The extracted file is an .elf executable, likely the software responsible for encrypting the files.

The files encrypted by the ransomware are found inside the ‘forela-criticaldata’ directory. It appears that the original files were encrypted and removed, and two new files were created with the original names but different extensions:

  • .24bes — Encrypted file
  • .24bes_note.txt — Ransom note

To decrypt the files, we need to determine the encryption type and locate the encryption key.

First, let’s extract the strings from ‘bescrypt3.2’. We might find some useful information.

fread, closedir, fopen, strlen, strstr, malloc, remove, ftell, readdir
fclose, opendir, fwrite, fseek, .txt, .sql, .pdf, .docx, .xlsx, .csv, .json
.xml, /forela-criticaldata/, encrypt_file , process_directory
  • Functions related to file operations like fopen, fread, fwrite, fseek, fclose, remove, and directory operations like opendir, readdir, closedir suggest the malware scans and modifies files.
  • Specific file types mentioned (.txt, .sql, .pdf, .docx, .xlsx, .csv, .json, .xml) are common targets for ransomware to encrypt.
  • The string encrypt_file was found, which could be the function we’re looking for.

Let’s use our reverse engineering skills to gain a deeper understanding of its functions and behavior.

I used Cutter to disassemble the file. From examining the functions, it is apparent that there is a main function. This main function seems to be the entry point that orchestrates the ransomware’s operations.

functions

Let’s examine the main function.

main function

As we can see, there is a function call named process_directory that takes two arguments, which are pointed to by registers rsi and rdi.

Following the instructions, we observe that the address of the string “bhUIIshutrea98liOp” is stored in rsi, and the address of the string “forela_criticaldata” is stored in rdi.

In an abstract form, the main function looks like this:

process_directoey("bhUIIshutrea98liOp","forela_criticaldata")

Let’s move on to the ‘process_directory’ function and analyze each block of instructions, while ignoring error handling for clarity.

original __________________________________________renamed

At the first block of the function, we can see that the arguments provided to the function (“bhUIIshutrea98liOp” and “forela_criticaldata”) are stored in ‘var_418h’ and ‘var_420h’. Let’s rename these variables to make the analysis much clearer.

The function call ‘opendir’ takes one argument stored in the rax register, which is “forela_criticaldata”. The result of this call is stored in ‘var_8’ (a pointer to the directory). We can rename ‘var_8’ to ‘dirp’ for clarity.

original __________________________________________renamed

The pointer (dirp) to the directory “forela_criticaldata” provided as an argument to the `readdir` function, the results are stored in `var_10h` (representing the first entry of the directory). Let’s rename `var_10h` to `file_info`.

original _______________________________________renamed

This block constructs the full file path by combining the directory path forela_criticaldata with the file name from ‘file_info’, storing the result in ‘var_410h’ using snprintf.

Let’s rename ‘var_410h’ as ‘file_path’.

jump table

Next, there is a check for file extensions (.sql, .txt, .json, etc.). If a match is found, the code jumps directly to the next block that contains a call to the `encrypt_file` function, as shown below.

The encrypt_file function takes two arguments: file_path and the address of the string “bhUIIshutrea98liOp”. It is now clear that this string is used as the encryption key (answer to task 1).

encrypt_file(file_path,'bhUIIshutrea98liOp')

Let’s dive into the encrypt_file function to identify the encryption mechanism.

original __________________________________________renamed

At the beginning of the function, the arguments `file_path` and `encryption_key` are stored in `var_848h` and `var_850h` respectively. Let’s rename these variables to `file_path` and `encryption_key` for clarity.

The `fopen` function uses two arguments: the file path and a mode specifier. By examining address `0x0002008`, we determine it stores the string “rb”, indicating “read binary” mode. The return value of `fopen` is stored in `var_20h`. This return value is a file pointer, which tracks the current position within the file, allowing you to know the exact byte or character being read or written.

original ____________________________renamed
  • By using fseek (2 = SEEK_END), the file pointer is moved to the end of the file(pointing the last byte).
  • ftell function gets the current position of the file pointer, indicates the file size, and this value is stored in ‘var_28h’. (‘var_28h’ renamed as ‘file_size’)
  • rewind function resets the file pointer to the beginning of the file.
  • malloc function allocates memory equal to the file size, and the pointer to this memory location is stored in ‘var_30h’.(‘var_30h’ renamed as ‘buffer’)
  • fread function reads the entire file into the allocated memory buffer.
  • fclose function closes the file.
  • var_18h’ is set to 0 and will be used as a counter.(‘var_18h’ renamed as ‘counter’)

Finaly the function that encrypting the files,

The function performs XOR encryption on a buffer. It uses a counter to track the position within the buffer.

For each byte in the buffer, it calculates the corresponding byte in the encryption key by taking the counter modulo and the key length, ensuring the key is reused cyclically.

The buffer byte is then XORed with the key byte and stored back in the buffer.

This process continues until all bytes in the buffer are encrypted. The loop breaks when counter equals ‘file_size’.

Short explanation about XOR cipher:

In an XOR cipher, each bit of the plaintext (A) is XORed with the corresponding bit of the key (H). The result is the ciphertext (A XOR H). The same key is used for both encryption and decryption. Reapplying the XOR operation with the same key returns the original plaintext.

Now that we understand how the XOR cipher works, we can create a python script to decrypt the files using XOR with the same key.

import os
# list all files in the given directory
def read_dir(path):
file_list = []
for file in os.listdir(path):
file_list.append(file)
return file_list

# read the data from an encrypted file
def file_data(file_path):
with open(file_path, 'rb') as data:
encrypted_data = bytearray(data.read())
return encrypted_data

# decrypt the data using XOR operation
def xor_data(key, encrypted_data):
decrypted_data = bytearray(len(encrypted_data))
key_length = len(key)
for i in range(len(encrypted_data)):
decrypted_data[i] = encrypted_data[i] ^ ord(key[i % key_length])
return decrypted_data

# write the decrypted data to a new file
def write_to_file(file, decrypted_data, path):
filename = os.path.basename(file)[:-6]
file_path = os.path.join(path, filename)
with open(file_path, 'wb') as new_file:
new_file.write(decrypted_data)

# path to the directory containing the encrypted files
path = r"C:\Users\husky\Desktop\lockpick\forela-criticaldata"

# decryption key
key = 'bhUlIshutrea98liOp'
file_list = read_dir(path)

# Loop through each file in the list
for file in file_list:
if file.endswith(".24bes"):
file_path = os.path.join(path, file)
encrypted_data = file_data(file_path)
decrypted_data = xor_data(key, encrypted_data)
write_to_file(file, decrypted_data, path)
os.remove(file_path)
print(f'[+] successful : {file}')
elif file.endswith("note.txt"):
file_path = os.path.join(path, file)
os.remove(file_path)
print("[+] Operation complete.")

After running the script, all files were decrypted.

Task 2

“We have recently recieved an email from wbevansn1@cocolog-nifty.com demanding to know the first and last name we have him registered as. They believe they made a mistake in the application process. Please confirm the first and last name of this applicant.”

As we examine the files, the file ‘forela_uk_applicants.sql’ contains a database of all Forela application applicants. Let’s find the registered details for wbevansn1@cocolog-nifty.com.

Answer: Walden Bevans

Task 3

“What is the MAC address and serial number of the laptop assigned to Hart Manifould”

Look for the name Hart Manifould in the ‘it_assets.xml’ file.

Answer: E8–16-DF-E7–52–48, 1316262

Task 4

“What is the email address of the attacker”

The ransome note contain the attacker email address.

Answer : bes24@protonmail.com

Task 4

“City of London Police have suspiciouns of some insider trading taking part Python module designed for handling JSON data.within our trading organisation. Please confirm the email address of the person with the highest profit percentage in a single trade alongside the profit percentage.”

To parse the file ‘’trading-firebase_bkup.json”, we created a Python script that uses the json library (Python module designed for handling JSON data).

import json
path = r"C:\Users\husky\Desktop\lockpick\forela-criticaldata\trading-firebase_bkup.json"


highest_profit = None
trader = None


with open(path, "r") as file:
data = json.load(file)
for key, value in data.items():
profit_percentage = value.get("profit_percentage")
if highest_profit is None or profit_percentage > highest_profit:
highest_profit = profit_percentage
trader = value

if highest_profit:
print(trader['email'], trader['profit_percentage'])

Answer: fmosedale17a@bizjournals.com, 142303.1996053929628411706675436.

Task 6

“Our E-Discovery team would like to confirm the IP address detailed in the Sales Forecast log for a user who is suspected of sharing their account with a colleague. Please confirm the IP address for Karylin O’Hederscoll.”

We opened the file ‘sales_forecast.xlsx’ and searched for the name Karylin O’Hederscoll.

Answer: 8.254.104.208

Task 7

“Which of the following file extensions is not targeted by the malware? .txt, .sql,.ppt, .pdf, .docx, .xlsx, .csv, .json, .xml"

As we observed earlier in the process_directory function, .ppt files are not targeted by the malware.

Answer: ‘.ppt’

Task 8

“We need to confirm the integrity of the files once decrypted. Please confirm the MD5 hash of the applicants DB.”

Answer: f3894af4f1ffa42b3a379dddba384405

Task 9

“We need to confirm the integrity of the files once decrypted. Please confirm the MD5 hash of the trading backup.”

Answer: 87baa3a12068c471c3320b7f41235669

Task 10

“We need to confirm the integrity of the files once decrypted. Please confirm the MD5 hash of the complaints file.”

Answer: c3f05980d9bd945446f8a21bafdbf4e7

I hope you enjoyed the write-up. See you next time!

--

--