Research October 20, 2023

A Deep Dive into Cactus Ransomware

Executive summary

Cactus ransomware was discovered in March 2023. The malware creates a mutex called “b4kr-xr7h-qcps-omu3cAcTuS” to ensure that only one copy is running at a time. Persistence is achieved by creating a scheduled task named “Updates Check Task”. The ransomware requires an AES key to decrypt the encrypted public RSA key stored in the binary.

The files are encrypted using the AES algorithm (OpenSSL library), with the key being encrypted using the public RSA key. The extension of the encrypted files is changed to “cts0” or “cts1”.

Analysis and findings

SHA256: 78C16DE9FC07F1D0375A093903F86583A4E32037A7DA8AA2F90ECB15C4862C17

The ransomware is packed with UPX. It retrieves the window handle used by the console:

Cactus-Ransomware-Figure-1
Figure 1

The process hides the window by calling the ShowWindow API (0x0 = SW_HIDE):

Cactus-Ransomware-Figure-2
Figure 2

It obtains a pseudo handle for the current process using GetCurrentProcess:

Cactus-Ransomware-Figure-3
Figure 3

The GetProcessAffinityMask function is utilized to extract the process affinity mask and the system affinity mask for the system:

Cactus-Ransomware-Figure-4
Figure 4

The malware can run with at least one of the following parameters: “-s”, “-r”, “-i”, “-l”, “-e”, “-c”, “-t”, “-d”, and “-f”. We’ll describe the purpose of every parameter in the upcoming paragraphs.

Cactus-Ransomware-Figure-5
Figure 5

The binary creates a mutex called “b4kr-xr7h-qcps-omu3cAcTuS” to ensure that only one copy of the executable is running at a time (see Figure 6).

Cactus-Ransomware-Figure-6
Figure 6

Running with the -s parameter

The public RSA key is stored in an encrypted form. The AES key used to decrypt the RSA key is parsed from the “C:\ProgramData\ntuser.dat” file, which should have been created earlier. The initialization vector is hard-coded “OLi3bTN6ekZCY7jd”:

Cactus-Ransomware-Figure-7
Figure 7

The public key is decrypted using AES256 Galois Counter Mode (GCM):

Cactus-Ransomware-Figure-8
Figure 8

OpenSSL’s EVP_DecryptInit_ex function is used to start decrypting the information, as highlighted below.

Cactus-Ransomware-Figure-9
Figure 9
Cactus-Ransomware-Figure-10
Figure 10

Finally, the RSA key is decrypted by calling the EVP_DecryptUpdate method (Figure 11).

Cactus-Ransomware-Figure-11
Figure 11

The ransomware checks if the decryption was successful by verifying the first 3 characters:

Cactus-Ransomware-Figure-12
Figure 12

The malicious process loads the public RSA key using the PEM_read_bio_PUBKEY function, as shown in the figure below.

Cactus-Ransomware-Figure-13
Figure 13

GetModuleFileNameW is utilized to extract the path of the executable file (see Figure 14).

Cactus-Ransomware-Figure-14
Figure 14

The binary is looking for the “D:\ProgramData” directory via a function call to CreateDirectoryW:

Cactus-Ransomware-Figure-15
Figure 15

It retrieves file system attributes for the ProgramData folder:

Cactus-Ransomware-Figure-16
Figure 16

The above folder is hidden using the SetFileAttributesW API (0x12 = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_HIDDEN):

Cactus-Ransomware-Figure-17
Figure 17

The executable is copied into the ProgramData folder as “C:\ProgramData\b4kr-xr7h-qcps-omu3.exe”:

Cactus-Ransomware-Figure-18
Figure 18

The malicious binary deletes the “ntuser.dat” file found in the ProgramData directory if it exists:

Cactus-Ransomware-Figure-19
Figure 19

It creates the above file that will be populated:

Cactus-Ransomware-Figure-20
Figure 20

Cactus ransomware writes 2 junk strings, the executable path converted to hex, and the AES key passed in the “-i” parameter to the file:

Cactus-Ransomware-Figure-21
Figure 21

The “ntuser.dat” file is hidden via a function call to SetFileAttributesW (Figure 22).

Cactus-Ransomware-Figure-22
Figure 22

The ransomware establishes persistence by creating the “Updates Check Task” scheduled task, which runs the malware with the “-r” parameter:

Cactus-Ransomware-Figure-23
Figure 23

Running with the -r parameter

The wfopen method is utilized to open the file created earlier, as highlighted in the figure below.

Cactus-Ransomware-Figure-24
Figure 24

The process extracts the AES key from the file. It’s important to mention that we don’t have the threat actor’s key and performed some modifications that allow the analysis to continue.

The “ntuser.dat” file is deleted afterwards:

Cactus-Ransomware-Figure-25
Figure 25

The binary spawns the initial executable with the “-i” parameter, including the AES key that was set to a specific string:

Cactus-Ransomware-Figure-26
Figure 26

Running with the -i parameter

The executable creates a new thread that runs the searchFilesThreadControl function:

Cactus-Ransomware-Figure-27
Figure 27

It retrieves the valid drives on the system using the GetLogicalDriveStringsW API (see Figure 28).

Cactus-Ransomware-Figure-28
Figure 28

The malware obtains the type of the drive by calling the GetDriveTypeW function:

Cactus-Ransomware-Figure-29
Figure 29

The files are enumerated using the FindFirstFileW and FindNextFileW APIs:

Cactus-Ransomware-Figure-30
Figure 30
Cactus-Ransomware-Figure-31
Figure 31

The following directories will not be encrypted:

  • “$recycle.bin” “system volume information” “windows” “tmp” “temp” “thumb” “winnt” “windows.~bt” “windows.old” “perflog” “perflogs” “boot” “programdata” “packages” “efi” “windowsapps” “microsoft” “windows defender” “microsoft shared” “internet explorer” “tor browser” “ctslck”
Cactus-Ransomware-Figure-32
Figure 32

GetFileAttributesW is used to extract file system attributes for a target file, as shown below:

Cactus-Ransomware-Figure-33
Figure 33

Cactus ransomware doesn’t encrypt the “CaCtUs.ReAdMe.txt” ransom note and the following files:

  • “desktop.ini” “update.log” “ntuser.dat”
Cactus-Ransomware-Figure-34
Figure 34

The following file extensions will be avoided:

  • “exe” “dll” “lnk” “sys” “msi” “bat” “cts0” “cts1”

The ransomware opens the target file using CreateFileW (0xC0000000 = GENERIC_READ | GENERIC_WRITE, 0x3 = OPEN_EXISTING):

Cactus-Ransomware-Figure-35
Figure 35

The binary uses Restart Manager APIs to determine if the target files are blocked by other processes (Figure 36).

Cactus-Ransomware-Figure-36
Figure 36

The wfopen function is utilized to open the file:

Cactus-Ransomware-Figure-37
Figure 37

The malicious process moves the file pointer to the end of file using lseek64 (0x2 = SEEK_END):

Cactus-Ransomware-Figure-38
Figure 38

It creates a new thread that handles the file’s encryption (see Figure 39).

Cactus-Ransomware-Figure-39
Figure 39

The file’s size is compared with 8074034 bytes (approximately 7.7MB). If the size is greater than 7.7MB, then cryptPartFile is called; otherwise, the malware calls the cryptFullFile function. Basically, a large file is partially encrypted (50%, but the percentage can be modified) by Cactus ransomware.

The ransomware allocates and obtains a cipher context using OpenSSL’s EVP_CIPHER_CTX_new:

Cactus-Ransomware-Figure-40
Figure 40

The algorithm used to encrypt the files is AES256 in CBC mode, as highlighted in the figure below.

Cactus-Ransomware-Figure-41
Figure 41

The process sets up the cipher context for encryption using the EVP_EncryptInit_ex method (Figure 42).

Cactus-Ransomware-Figure-42
Figure 42

EVP_CIPHER_get0_provider is utilized to obtain an OSSL_PROVIDER pointer to the provider:

Cactus-Ransomware-Figure-43
Figure 43

The ransomware generates a random 32-byte key using EVP_CIPHER_CTX_rand_key:

Cactus-Ransomware-Figure-44
Figure 44
Cactus-Ransomware-Figure-45
Figure 45

The 16-byte IV is generated by calling the RAND_priv_bytes_ex function:

Cactus-Ransomware-Figure-46
Figure 46

Using the key and IV previously generated, the binary calls the EVP_EncryptInit_ex method again:

Cactus-Ransomware-Figure-47
Figure 47

The executable allocates the public RSA key algorithm context via a call to EVP_PKEY_CTX_new_from_pkey, as highlighted in the figure below.

Cactus-Ransomware-Figure-48
Figure 48

The AES256 key is encrypted using the public key:

Cactus-Ransomware-Figure-49
Figure 49
Cactus-Ransomware-Figure-50
Figure 50

The encrypted file’s extension is changed to “cts0” or “cts1”:

Cactus-Ransomware-Figure-51
Figure 51

The ransomware appends the following information to the encrypted file: encrypted AES256 key, non-encrypted IV, 0x64 (encryption percentage), and “~~!!~~!”.

Cactus-Ransomware-Figure-52
Figure 52

It reads the content that will be encrypted using the _read function:

Cactus-Ransomware-Figure-53
Figure 53

EVP_EncryptUpdate is used to encrypt data:

Cactus-Ransomware-Figure-54
Figure 54

Finally, the malware calls the EVP_SealFinal method:

Cactus-Ransomware-Figure-55
Figure 55
Cactus-Ransomware-Figure-56
Figure 56

The extension is changed again to the other remaining value:

Cactus-Ransomware-Figure-57
Figure 57

The structure of an encrypted file can be seen in Figure 58.

Cactus-Ransomware-Figure-58
Figure 58

Running with the -l parameter

In this case, the ransomware sets the needLogger variable to 1 and creates a log file called “update.log” in the ProgramData directory.

Running with the -e parameter

This is the extra logging feature of the ransomware, which adds even more steps to the same log file.

Running with the -c parameter

This parameter is used to change the encryption percentage (sizeCoverGlobal variable) when partially encrypting the files.

Running with the -t parameter

The number of threads available for encryption can be changed in the maxThreads variable.

Running with the -d parameter

The ransomware only encrypts a specific directory.

Running with the -f parameter

In this case, a single file is encrypted by the malware.

Indicators of Compromise

SHA256

78C16DE9FC07F1D0375A093903F86583A4E32037A7DA8AA2F90ECB15C4862C17

Cactus Ransom Note

CaCtUs.ReAdMe.txt

Mutex

b4kr-xr7h-qcps-omu3cAcTuS

Files created

C:\ProgramData\ntuser.dat

C:\ProgramData\b4kr-xr7h-qcps-omu3.exe

C:\ProgramData\update.log

Scheduled task

Updates Check Task