ThunderX ransomware: analysis and a free decryptor!

By 21 September 2020 November 16th, 2020 Blog


Ransomware is still one of the major cyber security threats for both businesses and consumers. And even though in many of the larger incidents one of the big names in ransomware, such as NetWalker, Clop or Maze, is used, new ransomware families still frequently appear in the wild.

In this blog post we describe our findings on the new ransomware family ThunderX that was recently discovered.  We also announce a free decryptor that we are making available to help victims at no charge. We intend to make this decryptor available through the NoMoreRansom initiative soon, and will distribute it through our own CERT team for free until then. Apart from a couple of tweets (notably one by Michael Gillespie mentioning that files can be decrypted) there does not appear to be much information available publicly on this ransomware, so we decided to write a blog post describing some of our internal analysis. In this post, we will give a general overview of the malware and point out some of its peculiarities. Then we will dive deeper into the way it encrypts files. We also point out an issue that might cause the ransomware to corrupt encrypted files, making recovery of the data hard or even impossible.

General overview

ThunderX is a dedicated file encryption ransomware, and at a high level its operation does not differ much from other dedicated file encryption ransomware.

Like many other ransomwares, it starts by checking or creating a Mutex to prevent multiple instances running in parallel. Then it checks for an attached debugger, and skips the remainder of its functionality if one is found. If no debugger was found, some encrypted strings are loaded from the resources and decrypted. These strings contain among other things lists of processes and services that are then terminated if found running. Subsequently some commands are executed to delete shadow copies and make some modifications to the boot configuration.

After all this is done, the actual encryption commences by initializing the cryptography, generating the ransom note and finally starting separate threads for each drive and network share to find files to encrypt. The sample we have analysed includes a ‘-nolan’ commandline option to skip encryption of network shares. No other run-time options are present.

One particular detail of the ransomware that deserves mention is its ability to overwrite specific files with zeroes, instead of encrypting them. This means ThunderX contains functionality to destroy some data irreversibly on purpose. The embedded configuration in the resources contains the target filenames for this destructive overwriting.

The sample that we base our description on here, contains some obfuscation to thwart analysis. A number of strings have been hex-encoded in the binary, to make them less obvious. This is for example the case for the command lines that are used to remove shadow copies. Some other strings are stored in the resources with a simple single byte XOR encryption, for example the ransom note template and the lists of processes and services to terminate.

File encryption

Just like most other ransomware, ThunderX uses a combination of asymmetrical and symmetrical cryptography. For its asymmetrical cipher it uses 2048 bits RSA with a public key embedded in the ransomware. The lesser-known Salsa20 cipher is used as a symmetrical cipher for encrypting file data.

Salsa20 supports different key sizes, but 256 bits and 128 bits are the most common choices. At first glance, ThunderX uses the more secure 256 bits variant. However, even though 256 bits keys are generated, ThunderX has a bug in the initial state setup code that causes it to operate in the 128 bits key mode of Salsa, using only the first 128 bits of the 256 bits key!

The parts of the file that are encrypted are determined by the size of the original file. For smaller files, only the first part is encrypted. For larger files, four parts spread over the file are encrypted. Within the ransomware, these are respectively modes 1 and 2. The code also contains a mode 3 but in our sample this mode never seems to be used. (Mode 3 also seems to contain a bug in its code, so it would probably be best if it is unused.)

Mode 4 also exists within the code, but this mode does not encrypt the data in a file but rather overwrites it with zeroes, making recovery impossible.

As with most ransomware, a footer containing information for the decryptor on how to decrypt the file is appended to the encrypted files. This footer contains the RSA encrypted Salsa20 key and nonce, as well as the original file size and the encryption mode. Finally, the footer contains a special value 0xB0E0E0F0 that can be used to verify that the file was indeed encrypted by this ransomware. In our sample, encrypted files get the extension ‘.tx_locked’, but this is configurable and might be different for other binaries.

The footer added to encrypted files by some of the ‘big names’ in ransomware these days, such as NetWalker, contains a digest of the original data, or sometimes of the entire original file, enabling the ransomware author to verify the correctness of the decryption. Unfortunately, the authors of ThunderX have not included such a digest. This makes it impossible for their decryptor to reliably detect file corruption during decryption.

Finally, the code of ThunderX is structured in such a way that some of the parameters for the file encryption, such as the sizes of the encrypted parts, or the file size threshold between one and four encrypted parts, seem to be configurable when building a ransomware binary. However, in other ransomwares where these parameters are configurable, we often see their values stored in the encrypted file footers so the decryptor can use them. This way, a single decryptor code base can be used to serve multiple ransomware binaries with different parameters. This is not the case in ThunderX however, so if any of these parameters do change in a future version, the authors will have to make the corresponding changes to the decryptor as well.

screenshot ThunderX ransomware note


As mentioned in the general overview, ThunderX creates a separate thread for each drive and network share to find the files to encrypt. This is quite common for ransomware families. In some ransomware, the encryption of the files themselves is handled by the thread that looks for files to encrypt, in others (e.g. Clop) a separate thread is spawned for each file. ThunderX works a bit differently: using the IoCompletionPort mechanism in windows, it creates a queue for files to be encrypted. It then starts a pool of threads that handle the actual encryption. The number of threads in this pool is equal to twice the number of processors returned by a call to GetSystemInfo(). The encryption threads share some global memory that is used for their initial Salsa states. This introduces a small window for a bug described below that may prevent the correct decryption of files. The easiest fix for this would be to give each thread its own copy.

Bugs in ThunderX

During our analysis we encountered a number of interesting bugs. We will describe two of the most interesting ones.

The most obvious bug encountered in ThunderX is the bug in the Salsa key scheduling: even though a 256 bit key is generated, the ransomware only uses the first 128 bits. As each additional bit in the key usually increases the ‘space’ of all possible keys (and thus roughly the ‘security’ of the cipher) by a factor of two, this implies a substantial reduction in security of the cryptography used for file encryption.

One of the much less obvious bugs we encountered, is a possible race condition between the encryption threads. The threads share some global memory for the Salsa20 algorithm. At the start of the encryption of a part, this state is initialized and then read by the encryption code. When the encryption of a part is finished, the global memory is updated to reflect the final internal state of the thread that just finished its decryption. If this update takes place between the initialisation for a new block in a different thread, and the reading of the initialized state by that same thread, the initial state for the encryption might be incorrect, leading to data that cannot be decrypted. Furthermore, as ThunderX does not contain a digest of the original data in its footer, it is impossible to detect when this happens. So even when the ransom is paid, we believe there is a small chance that not all files might be restored correctly. Fortunately for ThunderX victims, the chances of hitting this race condition seem very small and we have not seen this happen in our own experiments.

A free Decryptor

Based on our analysis of this ransomware we have come to the conclusion that it is possible to decrypt all (non-corrupted) affected files without paying the ransom. Tesorion has built a decryptor that we are providing free of charge to victims of this ransomware.  The decryptor is available for download via the NoMoreRansom initiative or via the Tesorion CERT-team.

Indicators of Compromise:

– SHA256 of the ThunderX binary used in this analysis: 0fbfdb8340108fafaca4c5ff4d3c9f9a2296efeb9ae89fcd9210e3d4c7239666