TeslaCrypt Ransomware Malware Analysis

TeslaCrypt ransomware is an older ransomware family that was shut down in 2016 with the release of a master decryption key. This blog post gives a technical walkthrough of reverse engineering the ransomware loader and main payload.

Key Findings

  1. The loader retrieves the main payload from an embedded resource and decrypts it at runtime
  2. The embedded resource is executed within the loaders process memory via process hollowing

Tools Used for Analysis

  • Ghidra - For reverse engineering the loader and main payload to understand capabilities and functionality
  • X64Dbg - For debugging and dumping the main payload from memory
  • HXD - For removing junk data that was added to the dumped binary from memory
  • PeBear - For adjust the size of the dumped file to match the PE file size (PE header dictates what the size should be)
  • PeStudio - For performing high level triage of the files (imports, exports, strings, and other file information)

Loader Analysis

In an attempt to evade detection, the ransomware doesn’t deploy it’s main functionality directly, instead it uses a loader utility to execute the main payload. The loader extracts an embedded, encrypted resource and injects it into the current process via process hollowing.

The main function starts by getting user provided command-line arguments via calls to GetCommandLineW and CommandLineToArgvW. Next, 1044480 bytes of memory are allocated via a call to mallloc, this allocation is used later on for storing the unpacked main payload, I named the variable that holds a pointer to the allocated memory lpBuffer.

At the end of the main function, the embedded main payload is extracted as a resource within the unpack_resource function and it’s injected into the current process via the process_hollowing_injection function. The string “fgh57767” is passed into the unpacking function as the first parameter.

image

To unpack the main payload, the loader performs the following actions:

  1. First, a call to FindResourceW is made to identify the embedded resource by the type ID value of 899 (383 in hex).
  2. Once the embedded resource is identified a handle to it is obtained via a call to LoadResource, the handle is later used to obtain a pointer to the first byte of the resource in memory.
  3. A call to LockResource uses the previously obtained handle to retrieve a pointer to the resource in memory
  4. The size of the resource is obtained by SizeOfResource and it’s stored in a DWORD variable named rsrc_size.
  5. The value of 13 is subtracted from the resource size (the first 13 bytes are used later on as a decryption key)
  6. The extracted resource is decrypted via a call to resource_decryption, the decryption function takes the buffer containing the payload, and it’s size, as well as the decryption key bytes.

image

“fgh57767” corresponds to an embedded resource within the loader’s binary file. Inspecting the binary in PeStudio reveals the resource by name. The type ID is 899 which is how the resource is identified. The size of the embedded resource is 116,042 bytes.

image

To execute the unpacked main payload the loaded uses process hollowing. While performing injection, the loaded includes basic function call obfuscation by breaking up the function names (strings) used to dynamically resolve them. The loaded uses GetModuleHandleA and GetProcAddress to resolve the necessary functions, the strings passed to GetProcAddress are broken up and concatenated via sprintf at runtime.

The following actions are performed to inject the extracted main payload:

  1. A call to CreateProcess is made with dwCreationFlags set to CREATE_SUSPENDED, the first parameter is set to NULL so it creates another process for the current binary.
  2. A call to ZwUnmapViewOfSection is made to unmap a section of memory from the newly created process, a handle to to created process is passed as the first parameter (hProcess)
  3. Memory is allocated within the suspended process via a call to VirtualAllocEx
  4. The decrypted resource is written into the allocated memory space within the suspended process via WriteProcessMemory
  5. A handle to the suspended process is passed into FUN_00401559 which obtains the “context” of the thread
  6. SetThreadContext is used to set the EAX register to the entry point of the executable written using the previous call
  7. The thread of the suspended process is resumed via a call to ResumeThread which causes it to execute

image

We can dump the unpacked main payload by debugging the loader, setting a breakpoint on the unpacking function and capture the buffer containing the unpacked and decrypted resource as it’s being passed into the injection function.

With x64dbg we can follow the lpBuffer parameter in a memory dump and locate it’s memory region and dump it to disk

image

Once on disk, before being able to analyze it we need to clean it up with HXD (dumping it directly from x64dbg’s memory region window added junk before and after the PE file) and re-sizing it with PeBear (ensure the file size and loaded size match after cleaning it).

image

Once obtaining the cleaned unpacked main payload, inspecting it in PeStudio reveals a lot of sensitive strings that indicate it’s the main ransomware payload. From here we can perform additional reverse engineering to uncover the ransomware’s functionality.

image

Main Payload Analysis

image

image

image

The malware maintains persistence on the system by setting the Software\\Microsoft\\Windows\\CurrentVersion\\Run Registry keys for HKEY_LOCAL_MACHINE and HKEY_LOCAL_USER. The directory path of a copy of the current process is stored in a value of msconfig after a call to RegSetValueExW. The malware attempts to set both the LOCAL_MACHINE and CURRENT_USER key.

image

Four threads are created:

  1. Deleting volume shadow copies: ShellExecuteEx is used to delete the system volume shadow copies via vssadmin.exe
  2. Data exfiltration: System information is gathered and is BASE64 encoded, this gets sent to a set of C2 servers
  3. Killing Processes: The running processes are enumerated and certain processes are killed by name
  4. File Encryption:

image

Deleting volume shadow copies:

The malware attempts to delete the systems volume shadow copies using vssadmin.exe via a call to ShellExecuteExW. The malware tries to run the command: vssadmin.exe delete shadows /all /Quiet

image

Killing Processes:

A thread executes a function called kill_processes_by_name, this function is responsible for enumerating current processes and killing specific process by name via a call to TerminateProcess.

The current processes PID is obtained by calling GetCurrentProcessId, the PID is checked when terminating processes, processes can’t have the same PID (this ensure the process doesn’t kill itself). The EnumProcesses function is called to get a listing of the current process, it opens a HANDLE to them and checks the processes name by calling GetProcessImageFileName.

image

If a process is running that contains one of the blacklisted subtrings, it’s terminated via a call to TerminateProcess.

image

Since this occurs in a loop, the call to Sleep causes this to happen every 200 milliseconds

StringDescription
procexpProcess explorer
regeditRegistry Editor
msconfigMSConfig, used for troubleshooting and managing configurations
cmd.exeCommand line utility for Windows

Data exfiltration:

TeslaCrypt contains network functionality that enables the capability of exfiltrating system information back to a set of embedded TOR based C2 servers. The malware prepares a data buffer containing information such as:

  • files - The number of encrypted files, the malware includes a logging capability that captures this
  • size
  • version
  • date
  • OS - The OS build number
  • ID - A unique identification value
  • subid
  • gate - The C2 that is was contacted
  • is_admin - A boolean value to determine if the process is running with Administrative privileges
  • is_64 - A boolean value that determines the systems architecture
  • ip - The systems external IPV4 address obtained from making an HTTP request to http://ipinfo.io/ip
  • exe_type

To obtain the systems external IP address, the payload uses InternetOpenW, InternetOpenUrlW, and InternetReadFile to reach out to http://ipinfo.io/ip. The website endpoint returns the external IPV4 IP address, the IP is stored in a char buffer and is passed on to the exfiltration preparation function.

  • InternetOpenW is used to prepare the network request, it initializes the usage of WinInet, it returns a HANDLE that can be used for subsequent WinInet function calls
  • InternetOpenW uses the HANDLE returned from InternetOpenW to make a network request to a domain/IP address
  • InternetReadFile reads the data obtained from the HTTP response, in this case it’s a char IPV4 address

image

The network requests use a hardcoded HTTP user-agent string Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022 which can be used to identify malicious network requests. In the below image, the censored red data is the returned IPV4 address.

image

To exfiltrate the prepared data buffer, the malware uses the same WinInet process for making an outbound HTTP GET request to a set of C2 servers. The HTTP requests are sent to the hardcoded /state1.php endpoint, the data is BASE64 encoded using an OpenSSL encoding function.

image

The payload loops through a set of embedded C2 servers that use TOR while trying to exfiltrate information

image

If a C2 server can be contacted it responds with a ---!!!Done!!!--- message to indicate it was successful, the malware checks the buffer returned via a call to InternetReadFile.

image

create message window

image

message window

image

Conclusion

Indicators

Detection Rules

Updated: