In the first half of 2021, we started to see the REvil ransomware operators pivot to targeting Linux-based systems with a new Linux version of their ransomware, similar to the malware they commonly used on Windows systems. Since then, there have been a few versions of this Linux-based malware.
In this post, we look at the latest version of their Linux-based ransomware "1.2a".
Quick Snapshot:
The malicious file is a Linux executable
Class: ELF64
Type: Dynamically Linked
Machine: X86-64
Number of section headers: 28
Entry Point: 0x401650
callq: __libc_start_main@plt
MD5: c83df66c46bcbc05cd987661882ff061
Yara Rules:
https://github.com/YaraExchange/yarasigs/blob/master/ransomware/crime_lin_revil.yar
https://github.com/YaraExchange/yarasigs/blob/master/ransomware/crime_lin_revix.yar
Introduction
The execution of this malware is straightforward. It traverses through the directories specified as targets and encrypts the files present in those directories. Once encryption is complete, it drops a ransom note in the directory with the usual ransom message and instructions on paying the threat actor to get the decryption key.
This variant of Revix requires a couple of parameters to be passed to execute successfully. It also requires escalated privileges to run and encrypt files on the disk successfully. Additionally, the malware checks the files in the target directories to see if they are already encrypted.
One of the main targets for this malware is VMware ESX platform's, which we've seen before in a different Linux ransomware from DarkSide.
Analysis
For this post, we analyzed Revix both statically and dynamically. Both methodologies have been used together throughout the analysis process presented below.
Let’s take a quick look at a couple of sections of this executable so that we have the offsets to some of the initial calls that can be used for further analysis.
Figure 1: Header Information
Section .init:
This section holds executable instructions that need to be executed before the main program entry point.
Figure 2: section
Section .text:
This section contains executable code.
Figure 3: section
Functions
Revix loads several functions upon initialization. Following are some of the more interesting functions we can extract useful information from, to understand the flow of execution, along with developing threat detections that we've provided at the end of this post.
We execute the malware while attached to a debugger and break at the main function to view these functions presented below. Once we hit the main function, we follow the jump to 'puts' function to look at the CPU at that location. We can see all the loaded functions at this point.
Figure 4: Malware functions loaded upon initialization
Figure 5: Function sequence during execution
Initialization
Let's take a quick look at the program initialization:
The malware requires to be run with a couple of command-line arguments. We can see these being passed through the stack in the image below/
Figure 6: Parameters for the command-line arguments
The image below shows another view from the CPU that shows the program execution in flight.
Figure 7: Program execution in flight
Figure 8: Stack view
Execution
When executed as a non-privileged user, the malware is not able to achieve full execution.
As shown in the image below, the malware has been provided with the directory 'here/' for this analysis.
Figure 9: Write execution on dir
The malware tries to access the data in this directory for read/write and is unsuccessful, as shown below.
Figure 10: getdent64 unsuccessful
The malware also tries to encrypt a test file that we used in our analysis, but the encryption process fails as that action requires higher privileges.
Figure 11: Encryption unsuccessful
As a result, the execution fails to achieve the desired outcome for the malware, as shown below.
Figure 12: Encryption failed
Another point of interest from this failed execution is that the malware attempted to execute a esxcli command but this action fails as there is no esxcli on our test machine.
Figure 13: esxcli not found
When we execute Revix with elevated privileges, we start to see more successful activity from the malware.
Firstly, Revix can access the data in the target directory.
Figure 14: getdents64 successful
We can see in the image above, the system call ‘getdents’. This system call returns directory entries for the directory it’s run against.
Figure 15: getdents64(2) Synopsis
In this case, there are three entries as we can see from the result shown in the image above.
Next, we can see that Revix is able to perform read/write functions on the data in the target directories, resulting in successful encryption of files.
Figure 16: Encryption successful
The Revix output below shows that it can write the ransom note text file to the victim's disk.
Figure 17: Ransom note write successful
Finally, we can see that the execution is completed successfully, resulting in the data present in the target directory being encrypted:
Figure 18: Execution complete
The file we provided in the target directory is now encrypted, and a ransom note is created in the same directory:
Figure 19: Execution complete, file encrypted
The malware also checks if the data in the target directory is already encrypted. To demonstrate this, we ran Revix against the same target directory one more time.
Upon execution, Revix runs a check on the data present in the target directory and identifies it to be already encrypted:
Figure 20: Encryption check performed
As a result, the execution ends up with no data being encrypted.
Figure 21: Execution complete
VMware ESX Targeting
Revix also tries to use esxcli, the command line interface for VMware’s ESX platform.
Let's take a quick look at the parameters passed to esxcli by Revix when it executes:
esxcli --formatter=csv --format-param=fields=="WorldID,DisplayName" vm process list | awk -F "\"*,\"*" '{system("esxcli vm process kill --type=force --world-id=" $1)}'
vm process list
List the virtual machines on this system. This command currently will only list running VMs on the system.
vm process kill
Used to forcibly kill Virtual Machines that are stuck and not responding to normal stop operations.
--type
There are three types of VM kills that can be attempted: [soft, hard, force].
--world-id | -w
The World ID of the Virtual Machine to kill. This can be obtained from the 'vm process list' command (required)
Essentially, these ESX command-line arguments are shutting down all virtual machines running on the ESX platform.
Revix attempts to target the '/vmfs' directory and encrypt all the data present in that directory, so all the virtual machines are rendered inoperable until the data is decrypted. This targeting is similar to that seen in DarkSide's Linux variant.
Command-line Arguments
The malware requires the following parameters to be passed for its execution to begin:
elf.exe --path /vmfs/ --threads 5
It also allows the '--silent' option that executes the malware without stopping any VMs
--silent (-s) use for not stoping VMs mode *
Parameter | Purpose |
--path | Specifies the path of the data that needs to be encrypted |
--threads | Specifies the number of threads, by default the malware uses 50 threads |
--silent | Executes the malware without stopping the VMs running on ESX |
Configuration
The configuration of Revix is similar to that of its Windows variant, only with fewer fields.
Field | Description |
pk | Public Key |
pid | ID |
Sub | Tag |
Dbg | Debug mode |
nbody | Base64-encoded body of the ransom-note |
nname | Filename of the ransom-note |
rdmcnt | Readme Count |
ext | File extension of the encrypted files |
Here's an image showing the configuration we were able to extract from the sample we analysed:
Figure 22: Configuration
Profiling
Revix also gathers information about the victim machine by running the "uname" command:
uname -a && echo " | " && hostname
Figure 23: System profiling
The results of the above command appear in the stack:
Figure 24: Stack view of system profiling in action
The info is then passed through the registers:
Figure 25: Register view od system profiling in action
And the end-result is created in the form of this configuration with the victim information:
Figure 26: System profiling complete
Encryption
The malware uses Salsa20 encryption algorithm, just like its Windows variant, to encrypt the data. Here is the pseudocode for the function that implements this encryption:
Figure 27: Pseudo-code for the encryption algorithm
Mitigation
Detections
Commands
Revix runs this command to determine machine info:
uname -a && echo " | " && hostname
Revix tries to query this directory:
/dev/urandom
Revix runs the below command to stop VMs running on the ESX platform in order to encrypt the data on those VMs:
esxcli --formatter=csv --format-param=fields=="WorldID,DisplayName" vm process list | awk -F "\"*,\"*" '{system("esxcli vm process kill --type=force --world-id=" $1)}'
Typos:
In some instances, typos that malware authors commit to the code are useful in detecting specific malware or similar code used in other malware families. Below are some of the typos we found in this variant of Revix:
--silent (-s) use for not stoping VMs mode
semms to be protected by os but let's encrypt anyway…
YARA Ruleset 1
rule Revix { meta: description = "Detects REvil Linux - Revix 1.1 and 1.2"author = "Josh Lemon" reference = "https://angle.ankura.com/post/102hcny/revix-linux-ransomware" date = "2021-11-04" version = "1.0" hash1 = "f864922f947a6bb7d894245b53795b54b9378c0f7633c521240488e86f60c2c5" hash2 = "559e9c0a2ef6898fabaf0a5fb10ac4a0f8d721edde4758351910200fe16b5fa7" hash3 = "ea1872b2835128e3cb49a0bc27e4727ca33c4e6eba1e80422db19b505f965bc4" strings: $s1 = "Usage example: elf.exe --path /vmfs/ --threads 5" fullword ascii $s2 = "uname -a && echo \" | \" && hostname" fullword ascii $s3 = "esxcli --formatter=csv --format-param=fields==\"WorldID,DisplayName\" vm process list" ascii $s4 = "awk -F \"\\\"*,\\\"*\" '{system(\"esxcli" ascii $s5 = "--silent (-s) use for not stoping VMs mode" fullword ascii $s6 = "!!!BY DEFAULT THIS SOFTWARE USES 50 THREADS!!!" fullword ascii $s7 = "%d:%d: Comment not allowed here" fullword ascii $s8 = "Error decoding user_id %d " fullword ascii $s9 = "Error read urandm line %d!" fullword ascii $s10 = "%d:%d: Unexpected `%c` in comment opening sequence" fullword ascii $s11 = "%d:%d: Unexpected EOF in block comment" fullword ascii $s12 = "Using silent mode, if you on esxi - stop VMs manualy" fullword ascii $s13 = "rand: try to read %hu but get %lu bytes" fullword ascii $s14 = "Revix" fullword ascii $s15 = "without --path encrypts current dir" fullword ascii $e1 = "[%s] already encrypted" fullword ascii $e2 = "File [%s] was encrypted" fullword ascii $e3 = "File [%s] was NOT encrypted" fullword ascii $e4 = "Encrypting [%s]" fullword ascii condition: uint16(0) == 0x457f and filesize } |
YARA Ruleset 2
/* import "pe" rule revixStatic { strings: $header = { 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 02 00 3e 00 01 00 00 00 50 16 40 00 00 00 00 00 } $config = { 7B 22 76 65 72 22 3A ?? ?? 2C 22 70 69 64 22 3A 22 ?? ?? 22 2C 22 73 75 62 22 3A 22 ?? ?? 22 2C 22 70 6B 22 3A 22 ?? ?? 22 2C 22 75 69 64 22 3A 22 ?? ?? 22 2C 22 73 6B 22 3A 22 ?? ?? 22 2C 22 6F 73 22 3A 22 ?? ?? 22 2C 22 65 78 74 22 3A 22 ?? ?? 22 7D } $uname = { 75 6E 61 6D 65 20 2D 61 20 26 26 20 65 63 68 6F } condition: all of them and filesize } rule revixCode { strings: $err1 = { 45 72 72 6F 72 20 6F 70 65 6E 20 75 72 61 6E 64 6D } $err2 = { 45 72 72 6F 72 20 64 65 63 6F 64 69 6E 67 20 6D 61 73 74 65 72 5F 70 6B } $err3 = { 66 61 74 61 6C 20 65 72 72 6F 72 2C 6D 61 73 74 65 72 5F 70 6B 20 73 69 7A 65 20 69 73 20 62 61 64 } $err4 = { 45 72 72 6F 72 20 64 65 63 6F 64 69 6E 67 20 75 73 65 72 5F 69 64 } $err5 = { 45 72 72 6F 72 20 64 65 63 6F 64 69 6E 67 20 6E 6F 74 65 5F 62 6F 64 79 } $form1 = { 65 78 70 61 6E 64 20 33 32 2D 62 79 74 65 ?? ?? } $form2 = { 65 78 70 61 6E 64 20 31 36 2D 62 79 74 65 ?? ?? } $config = { 7B 22 76 65 72 22 3A ?? ?? 2C 22 70 69 64 22 3A 22 ?? ?? 22 2C 22 73 75 62 22 3A 22 ?? ?? 22 2C 22 70 6B 22 3A 22 ?? ?? 22 2C 22 75 69 64 22 3A 22 ?? ?? 22 2C 22 73 6B 22 3A 22 ?? ?? 22 2C 22 6F 73 22 3A 22 ?? ?? 22 2C 22 65 78 74 22 3A 22 ?? ?? 22 7D } condition: all of them and filesize } rule revixESX { strings: $cmd1 = { 65 73 78 63 6C 69 } $cmd2 = { 2D 66 6F 72 6D 61 74 74 65 72 3D ?? ?? ?? } $cmd3 = { 2D 2D 66 6F 72 6D 61 74 2D 70 61 72 61 6D } $cmd4 = { 76 6D 20 70 72 6F 63 65 73 73 20 6C 69 73 74 } $cmd5 = { 65 73 78 63 6C 69 20 76 6D 20 70 72 6F 63 65 73 73 20 6B 69 6C 6C } $cmd6 = { 2D 2D 77 6F 72 6C 64 2D 69 64 3D 22 ?? ?? ?? } $config = { 7B 22 76 65 72 22 3A ?? ?? 2C 22 70 69 64 22 3A 22 ?? ?? 22 2C 22 73 75 62 22 3A 22 ?? ?? 22 2C 22 70 6B 22 3A 22 ?? ?? 22 2C 22 75 69 64 22 3A 22 ?? ?? 22 2C 22 73 6B 22 3A 22 ?? ?? 22 2C 22 6F 73 22 3A 22 ?? ?? 22 2C 22 65 78 74 22 3A 22 ?? ?? 22 7D } condition: all of them and filesize } rule revixPE { condition: pe.entry_point == 0x401650 } |
Conclusion
As we can see in the analysis shown above, the execution of Revix is a bit clunky in this variant. It requires multiple conditions to be met before the ransomware is successful in encrypting data.
Revix needs to be executed as a command-line argument with elevated privileges, specified target directories, and the number of threads. Basically, it's not a standalone application at this time and is quite noisy as well.
If Revix is not run with silent mode enabled, it will try to stop any VMWare ESX virtual machines, triggering incident response processes from the victim. Revix could quite possibly fail to encrypt the virtual machines due to reduced/restricted access of where they reside on a Linux system.
As new variants for the Revix ransomware are released, we expect the execution to be more efficient, requiring fewer manual processes from the threat actor.
References
ESXi 7.0 U3 ESXCLI Command Reference
DarkSide on Linux: Virtual Machines Targeted - Naiim, M.,2021
getdents64(2) - Linux man page
Code Analysis details by Intezer Analyse
© Copyright 2021. The views expressed herein are those of the author(s) and not necessarily the views of Ankura Consulting Group, LLC., its management, its subsidiaries, its affiliates, or its other professionals. Ankura is not a law firm and cannot provide legal advice.