Key Takeaways
- Trigona is a ransomware family written in the Delphi programming language that has been active since at least June 2022
- The Trigona threat group claims to perform double extortion attacks by combining data exfiltration with file encryption
- Trigona utilizes 4,112-bit RSA and 256-bit AES encryption in OFB mode for file encryption
- The file decryption process is fairly convoluted with a tool that requires several steps to function properly
- The ransomware has been regularly updated with new capabilities including a new data wiper feature
Zscaler ThreatLabz has been tracking the Trigona ransomware family, which dates back to June 2022. There has been public reporting that some of the group’s tactics, techniques, and procedures (TTPs) have overlapped with BlackCat/ALPHV ransomware. However, the two ransomware codebases are very different. Trigona is written in the Delphi programming language and encrypts files with a 4,112-bit RSA public key and a 256-bit AES symmetric key. The group claims to exfiltrate data prior to performing file encryption and hosts a data leak site that is hosted on a publicly available website rather than a TOR hidden service. Trigona’s ransomware code contains numerous idiosyncrasies such as an AES implementation without padding, the use of multiple AES modes (CBC and OFB), and a large encrypted file footer with extraneous fields and integrity checks. In this blog, we will analyze Trigona ransomware’s features, encryption algorithms, and file decryption process. We have also created a Python-based tool to extract and decrypt Trigona’s ransomware configuration.
Technical Analysis
Trigona can be executed with or without command-line arguments. The latest versions of Trigona support the following parameters shown in Table 1.
Command-Line Parameter |
Description |
/erase |
Overwrite files with NULL bytes, rename with a ._erased extension, and delete; by default the first 0x80000 bytes (512KB) will be overwritten, but this can be combined with the /full option to overwrite the full file content |
/is_testing |
Sets a testing flag that must be used with the /test_cid and /test_vid command-line parameters |
/shdwn |
Shutdown the system with the parameters -f -s -t 00 |
/r |
Randomize file encryption order |
/full |
Encrypt the full content of files; by default Trigona encrypts only the first 0x80000 bytes (512KB) |
!autorun |
Do not create an autorun registry value |
/test_cid |
Use the specified value instead of generating a computer ID |
/test_vid |
Use the specified value instead of the hardcoded victim ID (VID) from the configuration |
/p |
Recursively encrypt files in the specified path |
/path |
Recursively encrypt files in the specified path |
/!local |
Do not encrypt local files |
/!lan |
Do not encrypt files on network shares |
/autorun_only |
Create an autorun registry value that will execute the ransomware upon logon, but do not perform file encryption |
Table 1. Trigona ransomware command-line arguments
The first three parameters in this table have been added in more recent versions. The CID value that is referenced in the code appears to be an acronym for a computer ID. This value is generated based on performing several MD5 hash calculations of system information (such as the computer name) with the formatted result matching the regular expression [A-F0-9]{8}-[A-F0-9]{4}-[A-F0-9]{8}. The VID value is likely a victim ID for the victim organization, although there are many Trigona samples where this value is left blank. The autorun registry value will be created in HKEY_CURRENT_USERSOFTWAREMicrosoftWindowsCurrentVersionRun with a registry name that consists of an uppercase hex string derived from the MD5 hash of the CID reversed, with the registry value pointing to the Trigona ransomware executable path.
Ransomware Configuration
After parsing the command-line parameters, Trigona loads an embedded configuration that is used to initialize an internal data structure. The ransomware stores this configuration in the binary’s resource section as a string resource named CFGS as shown in Figure 1.
Figure 1. Encrypted Trigona ransomware configuration stored as a string resource
The configuration is encrypted with two layers of AES in Cipher Block Chaining (CBC) mode. The first layer uses the first 32 bytes of the configuration as the AES key, followed by 16 bytes that are used as the AES initialization vector (IV), followed by the encrypted data. The result is another encrypted block of data with the order of the AES key and IV reversed, where the first 16 bytes represent another AES IV and the following 32 bytes are used as an AES key to decrypt the remaining encrypted data. There is one notable caveat related to Trigona’s use of AES with respect to padding. Since AES is a block cipher, padding is typically appended to the last block of data if it is not a multiple of the block length. However, the author of Trigona chose not to pad the final encrypted data block and instead implemented a variant of residual block termination. Thus, Trigona’s AES configuration decryption process is the following:
- Decrypt all 16-byte blocks using AES in CBC mode
- If the last encrypted block is not a multiple of 16 bytes, encrypt 16 NULL bytes
- Use the resulting ciphertext as an XOR key to decrypt the final block
This alternative to padding breaks compatibility with some encryption libraries including PyCryptodome, which by default does not allow an encryption operation to follow decryption. However, ThreatLabz has developed a Python-based script that overrides the encryption library’s internal state to support this variant of residual block termination and decrypt Trigona’s ransomware configuration. The decrypted Trigona configuration format varies slightly between versions, but the general format is the following:
struct trigona_cfg {
BYTE num_padding_bytes;
BYTE padding[num_padding_bytes];
BYTE config_md5[16];
DWORD section1_size;
BYTE cfg_section1[section1_size];
DWORD section2_size;
BYTE cfg_section2[section2_size];
DWORD section3_size;
BYTE cfg_section3[section3_size];
};
Note that all integer values are stored in big-endian byte order.
The structure of the first configuration section is shown below (note that there are two NULL bytes added in newer versions of Trigona):
struct cfg_section1 {
BYTE unk_null[2]; // added in newer versions
struct cfg_item file_rsa_pub_key;
struct cfg_item ransom_note_rsa_pub_key;
struct cfg_item vid;
struct cfg_item build_id;
struct cfg_item unknown1;
struct cfg_item extension_whitelist;
struct cfg_item contact_email;
struct cfg_item dir_whitelist;
struct cfg_item unknown2;
struct cfg_item unknown3;
struct cfg_item unknown4;
struct cfg_item unknown5;
struct cfg_item ransom_note_aes_key;
};
Each configuration item consists of the following structure:
struct cfg_item {
DWORD item_size;
BYTE item[item_size];
};
The structure of the first configuration section contains a variety of information including two RSA public keys. The first public key is used for file encryption and the second RSA key is used for encrypting an integrity value that is embedded in the ransom note and required for creating an account on the victim ransom portal. The note also includes a victim ID (VID), build ID, extension whitelist, directory whitelist, an email address to contact the threat actors.
The victim ID (VID) values that ThreatLabz has observed in Trigona samples are shown in Table 2 (some of the values are obfuscated to protect the identity of the victim).
Table 2. Observed Trigona ransomware victim ID (VID) values
The Trigona build IDs identified in Trigona samples are shown in Table 3.
Table 3. Observed Trigona ransomware build IDs
These build IDs appear to be incremental and may represent the version number of the ransomware with newer versions having a larger value.
ThreatLabz has observed the following contact email addresses in Trigona ransom notes:
- [email protected]
- [email protected]
- [email protected]
- [email protected]
- [email protected]
- [email protected]
- [email protected]
- [email protected]
The second configuration block has the following structure with 13 file extension blocks:
struct cfg_section2 {
struct extensions_block[13];
};
Each file extension block can be defined as follows:
struct extensions_block {
DWORD extension_block_size;
struct file_extension extension_block[];
};
Finally, each individual file extension structure is stored in the structure:
struct file_extension {
BYTE length;
BYTE extension[length];
};
Trigona samples analyzed by ThreatLabz have a total of 7,336 file extensions in the ransomware’s configuration. A list of these file extensions can be found here.
The third and last configuration block stores the ransom note template with the structure:
struct cfg_section3 {
DWORD length;
BYTE ransom_note_template[length];
};
The Trigona ransom note template can be found here.
Data Wiper Functionality
Trigona recently added data wiper functionality with the ability to overwrite files with NULL bytes in recent versions. The wiper functionality is triggered by passing the /erase command-line parameter. By default, Trigona will overwrite the first 0x80000 bytes of a file. However, similar to file encryption, a threat actor can pass the /full command-line parameter to overwrite the entire content with NULL bytes. After the file data is overwritten, the file is renamed with pseudo randomly generated characters in the format [a-z0-9]{1,32}.[a-z0-9]{1,10} and the extension _erased is appended. After the file is renamed, Trigona attempts to delete it. The ransomware will also attempt to remove any directories that are located within the specified path. The purpose of this feature may be to hinder forensic analysis or to destroy a victim’s data if they are not willing to pay a ransom.
Encryption Algorithms
Trigona uses a combination of RSA and AES for file encryption and for encrypting information that is stored in the ransom note. The AES algorithm is implemented using the open source Delphi DCPcrypt library and residual block termination is used in lieu of padding.
File Encryption
Trigona is capable of encrypting files on local drives as well as network drives. For the former, the ransomware will enumerate all drive letters from A to Z. Before file encryption begins, Trigona pseudo randomly generates a single master 32-byte AES key that is used for encrypting all files. For each file, Trigona generates another 80 pseudo random byte block that consists of 32 bytes of padding, a 32-byte AES key and a 16-byte IV. This 80-byte block is then encrypted using a 4,112-bit RSA public key that is hardcoded in Trigona’s configuration. This randomly generated AES key and IV are used to encrypt another block of data using AES in CBC mode that contains the actual master AES key that is used for file encryption. The AES mode used for file encryption is Output feedback (OFB) in contrast to CBC mode (which is used to decrypt Trigona’s configuration information and the master AES key). After a file has been encrypted, Trigona appends a large footer to the end of the file that contains a variety of information including the file’s encrypted AES key parameters, a (per-file) pseudo random 16-byte IV, along with MD5 hash values of the AES key and the RSA public key that was used to encrypt the file. Trigona also adds random padding in the footer to avoid a fixed length. The footer starts with 8 bytes where each odd byte (red) when concatenated together forms the size of the footer and each even byte (blue) is the hex value 0x53 (or the letter ‘S’) as shown below:
The encrypted file footer includes many additional parameters including the CID, VID and build ID. There is also additional binary data that is appended that comes directly from the ransomware’s configuration. The purpose of this binary data is not known, but it may be used to further pad the file footer to evade behavioral-based EDR detections.
After a file is encrypted, the filename extension is replaced with _locked. In recent versions, Trigona will also replace the original filename with pseudo randomly generated characters with the format [a-z0-9]{1,50}.[a-z0-9]{1,10} and append the _locked extension. The original filename is encrypted using the same AES key and IV that is used to decrypt the file content in OFB mode and then appended to the file footer. Figure 2 shows an example directory after Trigona’s file encryption has completed.
Figure 2. Directory encrypted by Trigona ransomware
Ransom Note Key Generation
Trigona creates an HTML Application (HTA) file named how_to_decrypt.hta that contains the ransom note. Figure 3 shows an example of the Trigona ransom note when opened.
Figure 3. Example Trigona ransom note
In order to start the negotiation process to recover files, a victim must provide an authentication key that can be retrieved via the Copy button in Step 3 of the ransom note. This key is a large hex-encoded string. When decoded, there is a header that starts with the string @CLADID followed by a hex encoded MD5 hash of the VID from the configuration and another hex encoded MD5 hash of the VID reversed. This is followed by a block of data encrypted with a 4,096-bit RSA public key that is hardcoded in Trigona’s configuration. When this block is decrypted, the result is 32 bytes of padding followed by a 32-byte AES key and a 16-byte IV. This AES key and IV are used to encrypt victim information including the computer name, user name, Windows domain, operating system version, system architecture, and keyboard language.
In addition, there’s a hex encoded string for an MD5 hash value of the encrypted victim data that is encrypted with two layers of AES. The first layer is encrypted with a hardcoded AES key from Trigona’s configuration. The second layer is encrypted using a pseudo random 32-byte AES key and pseudo random IV.
Ransomware Decryption
Trigona provides a quirky file decryption process, requiring a user to create an account on their ransom portal with the authentication key provided in the ransom note. After account creation, the victim can test file decryption and communicate with the threat group. Interestingly, the victim portal provides a (green) button to download a decryption tool as shown in Figure 4 without paying a ransom.
Figure 4. Trigona victim ransom portal
However, the tool itself cannot be used to decrypt files because it does not contain the necessary encryption parameters. The tool requires a file named keys.dat that is provided to the victim after payment has been received as shown in Figure 5.
Figure 5. Trigona ransomware decryption menu requiring a keys.dat file
This keys.dat file requires a user to send the threat actor another file named scan.dat, which contains a set of one or more RSA encrypted AES keys. The victim can use the decryption tool to scan for encrypted files to generate the scan.dat file as shown in Figure 6.
Figure 6. Trigona ransomware decryption tool feature to scan for encrypted files
After the encrypted file scan is complete, the scan.dat file is generated as shown in Figure 7.
Figure 7. Trigona ransomware decryption tool after a scan has completed
The scan.dat file contains a header with the magic bytes TDSF followed by the data encrypted with two layers of AES similar to Trigona’s configuration. After decryption, the scan data contains meta information including the VID, CID and build ID followed by the RSA encrypted AES key that was used for file encryption. When the threat actor receives the scan.dat file, they can use the victim’s RSA private key to decrypt an AES session key that is used to protect the victim’s AES key to generate the keys.dat file. The scan.dat file may include multiple CIDs, and therefore, multiple RSA encrypted AES keys.
The keys.dat file header contains the magic bytes TDKF (green) followed by the subsequent keys.dat file size (orange), followed by the number of AES keys (purple), followed by one or more AES keys (blue) and the corresponding MD5 hash value (red) for each AES key as shown below.
After the keys.dat file is provided to the decryption tool, the user interface will allow a victim to decrypt specific files or folders as shown in Figure 8.
Figure 8. Trigona decryption tool with a valid keys.dat file provided
When the Start full recovery button is pressed, the tool will enumerate files encrypted by Trigona by parsing each file to identify the file footer and use the corresponding AES key to decrypt the content. An example of the Trigona decryption tool upon completion is shown in Figure 9.
Figure 9. Trigona ransomware decryption tool after completion
Conclusion
Trigona ransomware is a ransomware family that claims to perform double extortion attacks. However, the group does not appear to be as sophisticated as many rival ransomware threat groups. The use of AES without padding and the multiple modes of AES are not commonly observed in ransomware. In addition, the file decryption process entails running a file scan to generate another file that is sent back to the threat actor, who in turn provides a file with the necessary encryption keys. The introduction of a data wiper feature is a noteworthy addition that may be used to hinder forensic analysis or to destroy a victim’s data. Zscaler ThreatLabz continues to track this threat group and add detections to protect our customers.
Cloud Sandbox Detection
In addition to sandbox detections, Zscaler’s multilayered cloud security platform detects indicators related to Trigona at various levels with the following threat names:
- Win32.Ransom.Trigona
Indicators Of Compromise (IOCs)
SHA256 |
Description |
8cbe32f31befe7c4169f25614afd1778006e4bda6c6091531bc7b4ff4bf62376 | Trigona ransomware with data wiper functionality |
efb688214c3fe5d9273ec03641cf17af5f546b11c97a965a49f8e617278ac700 | Triigona ransomware decryption tool |
f64211b0a49589bb53523dfb88eb9937ab88c8fcea98e2aabcbee90f1828e94e |
Trigona ransomware |
11b0e9673bbeb978aa9b95bcad43eb21bbe0bbaaf7e5a0e20d48b93d60204406 |
Trigona ransomware |
eda603f4d469d017917f5d6affeb992fdf3b7971e49868ece8c38fb8e6f8b444 |
Trigona ransomware |
c4529a061f205aaee46c219123d15059d2161df2bd7c7b738dd2a2c1ffd8d3ee |
Trigona ransomware |
170fa5d29cdb562d41a054abf2a57ca29fc233805b59692a1a57ebf25449be7c |
Trigona ransomware |
f29b948905449f330d2e5070d767d0dac4837d0b566eee28282dc78749083684 |
Trigona ransomware |
197f4933680a611ad2234a22769bd079885f81956221ec0de172d5a19eab648e |
Trigona ransomware |
1017fcf607a329bb6ad046181c3656b686906a0767fff2a4a3c6c569c2a70a85 |
Trigona ransomware |
761b78ddab55b4e561607ce5ce9d424a7aec4f1994aad988f0612b096cdd1d6d |
Trigona ransomware |
097d8edb1762d7d3ded4360a9f5b4673a898937421f36853d2f5cde77e1bac93 |
Trigona ransomware |
4a06231957c53dee1a11ff3eb84caad082f18761aee49e72d79c7f1d32884e34 |
Trigona ransomware |
Source: https://www.zscaler.com/blogs/security-research/technical-analysis-trigona-ransomware