ESXi Ransomware – A case
study of Royal Ransomware
Prepared by: Vlad Pasca, Senior Malware &
Threat Analyst
[Link]
info@[Link]
Tower 49
12 E 49th Street
Suite 15-001
New York, NY 10017
1.800.682.1707
Table of contents
Table of contents 1
Executive summary 2
Analysis and findings 2
Indicators of Compromise 19
[Link] | 1
Executive summary
Royal ransomware joins other ransomware groups targeting ESXi servers. The malware powers
off all virtual machines using the esxcli tool and doesn’t encrypt a list of files that are embedded
in the code. As in the case of the Windows version, a parameter called “-id” consisting of 32
characters must be specified in the command line.
The files are encrypted using the AES algorithm, with the key and IV being encrypted using the
RSA public key that is hard-coded in the executable. The process can partially encrypt a file
depending on its size and the value of the “-ep” parameter. The extension of the encrypted files
is changed to “.royal_u”.
Analysis and findings
SHA256: 06abc46d5dbd012b170c97d142c6b679183159197e9d3f6a76ba5e5abf999725
The ransomware retrieves the command line arguments and compares them with “-id”, “-ep”,
“-stopvm”, “-vmonly”, “-fork”, and “-logs”:
Figure 1
The “-id” parameter consisting of 32 characters is mandatory; otherwise, the following message
[Link] | 2
is displayed:
Figure 2
The “-ep” parameter represents the encryption percentage of the files. It is converted from string
to integer using the atoi function, as shown in figure 3.
Figure 3
When running with the “-stopvm” parameter, the process calls a function named stop_vm. It
creates a child process via a call to fork (see figure 4).
[Link] | 3
Figure 4
The child process obtains a list of running virtual machines, which are identified by World ID
and Display Name. It saves it in a file called “list”:
Figure 5
The parent process opens the “list” file and gets the file status using the stat method, as
displayed below.
Figure 6
[Link] | 4
The above file’s content is read using a function called read_all, which is a wrapper for the read
method:
Figure 7
Figure 8
All virtual machines are powered off based on the World ID by spawning a new process:
Figure 9
[Link] | 5
Figure 10
If the malware is running with the “-vmonly” parameter, then no files are encrypted, and the
execution flow isn’t impacted.
Whether the “-logs” parameter is specified, multiple logs are displayed in the standard output:
Figure 11
Figure 12
In the case of running with the “-fork” parameter, the executable creates a child process and
performs a function call to setsid:
[Link] | 6
Figure 13
The first parameter should be a directory that will be encrypted. The Windows version of the
ransomware uses the “-path” parameter in order to encrypt a target directory. The malware calls
a function called search_files with the targeted path as the first parameter (figure 14).
Figure 14
The process retrieves the number of processors using the sysconf method:
[Link] | 7
Figure 15
Royal ransomware creates 8 * number of processors threads by calling the pthread_create
function (see figure 16).
Figure 16
The opendir function is utilized to open the target directory:
[Link] | 8
Figure 17
A ransom note called “readme” is created in the traversed directory. The “-id” parameter is also
included in the text:
Figure 18
[Link] | 9
The malware reads the directory by calling the readdir method, as shown below:
Figure 19
The file type is compared with 0x4 (DT_DIR) and 0x8 (DT_REG):
Figure 20
In the case of directories, the search_files function is called recursively. For regular files, the
ransomware avoids files containing the following strings: ".royal_u", ".royal_w", ".sf", ".v00", ".b00",
"royal_log_", and "readme" (see figure 21).
[Link] | 10
Figure 21
The malicious process imports a hard-coded RSA public key:
Figure 22
Figure 23
[Link] | 11
The RSA public key is read by calling the PEM_read_bio_RSAPublicKey function (figure 24).
Figure 24
Each of the created threads receives a file to be encrypted as a parameter:
Figure 25
The ransomware calls a function named prepare_file for all files to be encrypted, as highlighted
in figure 26.
[Link] | 12
Figure 26
A file is opened for reading and writing via a function call to open (0x2 = O_RDWR):
Figure 27
If the “-logs” parameter is specified, the process outputs a message containing the file to be
encrypted:
Figure 28
[Link] | 13
The logging function implementation is shown in figure 29. It also displays the current date and
time obtained using the current_date_time method.
Figure 29
The malware generates 32 random bytes representing the AES key and 16 random bytes
representing the IV:
Figure 30
The randomly generated bytes are encrypted using the RSA public key (see figure 31).
[Link] | 14
Figure 31
The malicious binary rounds up the file size to a multiple of 16, which is required by the AES
algorithm:
Figure 32
The entire file content is encrypted if the file length is less than or equal to 5,245,000 bytes or if
the “-ep” parameter equals 100. As we’ve already described in our whitepaper about the
Windows version, the ransomware can modify the encryption percentage and perform
intermittent encryption:
[Link] | 15
Figure 33
The AES key is set for encryption by calling the AES_set_encrypt_key function:
Figure 34
The file content is read by calling the read_all function (figure 35).
Figure 35
The content is encrypted using the AES algorithm in CBC mode:
[Link] | 16
Figure 36
The implementation of the AES_encrypt function from OpenSSL is displayed in the figure
below.
Figure 37
[Link] | 17
The encrypted AES key and IV (512 bytes), followed by the file length (8 bytes) and the
encryption percentage (8 bytes), are written to the encrypted file:
Figure 38
Finally, the extension of all encrypted files is changed to “.royal_u”:
Figure 39
[Link] | 18
Indicators of Compromise
SHA256
06abc46d5dbd012b170c97d142c6b679183159197e9d3f6a76ba5e5abf999725
Royal Ransom Note
readme
Processes spawned
esxcli vm process list > list
esxcli vm process kill --type=hard --world-id=<World ID>
[Link] | 19