Abyss Locker Ransomware

Encryptor striking from the depths

Overview

Abyss Locker is a powerful encryptor that focuses on carefully managing the VM instance before encrypting VM files. The locker contains typical options such as encryption mode, detaching the process from the controlling terminal, encrypting VM disks and shutting down VM instances.

Abyss Locker does have unique features we do not see often in other Linux/ESXi based encryptors. Abyss Locker will attempt to identify shared memory locks from other processes and then kill those processes in an attempt to ensure that the locker has exclusivity in encrypting the file.

The actors using Abyss Locker have resorted to double extortion schemes, by exfiltrating data and encrypting the system. There are a handful of victims listed on the Abyss leak site

Bleeping Computer

Abyss Leak site - Source: Bleeping Computer (link)


Key points

  • Multiple esxcli options for shutting down a VM instance

  • Uses on host openSSL library for encryption

  • Uses on host esxcli to obtain VM discovery and shutdown

  • Will kill any process holding a shared memory lock to an interesting file before encrypting

  • Renames a file on disk multiple times before final encryption

Technical Analysis

Hash: 72310e31280b7e90ebc9a32cb33674060a3587663c0334daef76c2ae2cc2a462

Target systems: ESXi

Virus Total first submission: 2023-07-24 17:43:45 UTC (link)

ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              DYN (Position-Independent Executable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x3120
  Start of program headers:          64 (bytes into file)
  Start of section headers:          92112 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         9
  Size of section headers:           64 (bytes)
  Number of section headers:         28
  Section header string table index: 27

Step #1

Parse command line arguments

Reversed-engineered Source code: Github

The program starts by first creating a log file to store the contents of the results from each step of the encryptors process. The file 'work.log' is created on disk in the same directory of the running encryptor. If the encryptor is ran twice, the new log lines are appended to the same file.

The arguments passed into the program will be used through out the program flow to adjust how the encryptor processes files.

Arguments
---------
1) m - mode percentage for encryption (5-10-20-25-33-50)
2) v - Verbose logging
3) d - Daemon mode
4) e - Encrypt VM Disks
5) k - Get all VM instances and kill VMs using ESXi CLI

Parsing program options

APIs

Interesting Signals

  • New file on disk called: 'work.log'

Step #2

Check library dependencies

Reversed-engineered Source code: Github

The sample will first check to see if it can get a handle to the libcrypto.so library. If it can, it will use a handle to get the address of a symbol, specifically 'EVP_MD_CTX_new'. The 'EVP_MD_CTX_new' will allocate and return a new digest context.

If it can not get a handle to the dependency of the symbols it requires, the program will throw an error: 'Error InitAPI !!!' and exits.

Check library dependencies

APIs

Interesting Signals

  • Loads on host libcrypto.so into process memory

Step #3

Get CPU features

Reversed-engineered Source code: Github

The Sample will attempt to get CPU features by accessing specific CPUID bits for the RDRAND and AES instruction set support. The sample will not terminate if the features are missing.

Get RDRand

Get AES support

Step #4

VM Manipulation

Reversed-engineered Source code: Github

Once the CPU features were identified, the sample will then check the argument for VM manipulation (-k). If the option is present, it will then first attempt to get the process list using the LOLBIN 'esxcli'. The 'esxcli' utility is present on all ESXi hosts and can be used to obtain which VM's are running.

The sample will execute the following command 'esxcli vm process list'. The command will return a list of running VMs which are then passed to the function which will attempt to shut the VM's down.

Once the running VM's are obtained, the sample will then attempt to shutdown each VM one by one, using all three shutdown options.

The first option is for 'soft' ('esxcli vm process kill -t=soft -w=%d"') shutdown, which will attempt to gracefully stop the vm using the esxcli utility.

The function will then attempt to determine if the VM is still running. The second option will use the 'hard' ('esxcli vm process kill -t=hard -w=%d"') option which will attempt to shutdown the VM without waiting gracefully, but not forcing the VM process to end.

After the second option, the sample will determine if the VM is still running. If the VM is still running, the last option is to use the 'force' option ('esxcli vm process kill -t=force -w=%d"'). This option will immediately stop the VM, but could leave the VM in an unstable state.

APIs

Interesting Signals

  • Uses on host 'esxcli' tool

Step #5

File and Directory discovery of VM files

Reversed-engineered Source code: Github

Once the VM disks are shutdown, the sample will then attempt to find and log all VM files found. If the option for encrypting VMs was present on the command line (-e), the sample will attempt to process all directories minus key file system directories:

Files to skip:

.data:0000000000216080                                         ; "/bin"
.data:0000000000216088                 dq offset aBoot         ; "/boot"
.data:0000000000216090                 dq offset aDev          ; "/dev"
.data:0000000000216098                 dq offset aEtc          ; "/etc"
.data:00000000002160A0                 dq offset aVarLib+4     ; "/lib"
.data:00000000002160A8                 dq offset aUsrLib32+4   ; "/lib32"
.data:00000000002160B0                 dq offset aUsrLib64+4   ; "/lib64"
.data:00000000002160B8                 dq offset aLostFound    ; "/lost+found"
.data:00000000002160C0                 dq offset aProc         ; "/proc"
.data:00000000002160C8                 dq offset aRun          ; "/run"
.data:00000000002160D0                 dq offset aUsrSbin+4    ; "/sbin"
.data:00000000002160D8                 dq offset unk_11B45
.data:00000000002160E0                 dq offset aUsrInclude   ; "/usr/include"
.data:00000000002160E8                 dq offset aUsrLib       ; "/usr/lib"
.data:00000000002160F0                 dq offset aUsrLib32     ; "/usr/lib32"
.data:00000000002160F8                 dq offset aUsrLib64     ; "/usr/lib64"
.data:0000000000216100                 dq offset aUsrSbin      ; "/usr/sbin"
.data:0000000000216108                 dq offset aSys          ; "/sys"
.data:0000000000216110                 dq offset aUsrLibexec   ; "/usr/libexec"
.data:0000000000216118                 dq offset aUsrShare     ; "/usr/share"
.data:0000000000216120                 dq offset aVarLib       ; "/var/lib"

Once the sample has a valid directory it will then recursively iterate through each directory using the 'DirEnt' structure obtained from the 'readdir64' and 'stat64' APIs. If a file is found, it is then checked by a list to determine if it has an extension to skip.

Files with extensions to skip:

.data:0000000000216040                                         ; ".crypt"
.data:0000000000216048                 dq offset aReadmeToRestor ; ".README_TO_RESTORE"
.data:0000000000216050                 dq offset aTmp          ; ".tmp_"
.data:0000000000216058                 dq offset aA            ; ".a"
.data:0000000000216060                 dq offset aLibcryptoSo+9 ; ".so"
.data:0000000000216068                 dq offset aLa           ; ".la"

If the file is not skipped, it will then check that it has a valid VM extension using the list below:

VM Disk files (if option -e given as command line arguments)

.data:0000000000216020                                         ; ".vmdk"
.data:0000000000216028                 dq offset needle        ; ".vmx"
.data:0000000000216030                 dq offset aVmsd         ; ".vmsd"
.data:0000000000216038                 dq offset aVmsn         ; ".vmsn"

APIs

Step #6

Daemon Mode

The sample will attempt to use the 'daemon' function call to detach the program from the controlling terminal. It does not change the std input, output or error redirects. The process will change the current working directory of the process to the root directory.

APIs

Step #7

Data encrypted for Impact

Reversed-engineered Source code: Github

The sample will start a new thread using 'pthread_create' call. Once the thread is created, it will process the given file that was passed to it, found during file discovery.

The encryption function will start by setting up temporary and final file name extensions, using '.tmp_' during pre-processing and '.crypt' once the file is encrypted successfully. If the file cannot be encrypted or an error occurs, the file is renamed back from '.tmp_' to the original file name prior to processing.

Note: There is a great deal of file system activity per file.

Once the file is prepared, the encryption process flow will take over the next steps in processing the file.

Before encrypting the file, the sample will check for shared memory lock on the file, and get the PID of the owning process. If the file has exclusive lock on it, the file will not be processed. An error is posted in the log file with 'error lock_exclusively:%s owner pid:%d\n'.

If the encryptor was able to process the file, it will then check if the file is on a block device by getting the file stats using 'stat64'.

The encryptor will attempt to write a new readme file using the '.README_TO_RESTORE' file name. The following text will be written to the file.

Once the encryptor prepares the file, it will first get a number of random bytes using the openSSL function 'RAND_bytes'. The sample will use the openSSL 'EVP_EncryptInit_ex' and 'EVP_EncryptUpdate' functions to process the file buffer contents by encrypting them using initialized EVP Context. A computed ECDH key is used with the following string.

The openSSL 'EC_KEY_new' function is called to construct the public key, and 'EC_GROUP_new_curve_GFp' to setup a new Elliptic Curve.

The sample will log the statistics about the encryption process, including the amount encrypted and speed per second. Notice the error in the spelling of the word 'progress'.

APIs

  • - rename - link

  • - fnctl - link

  • - popen - link

  • - pthread_cond_signal - link

  • - sem_post - link

  • - sem_timedwait - link

  • - pthread_create - link

  • - stat64 - link

  • - EC_KEY_new - link

  • - EC_GROUP_new_curve_GFp - link

  • - EVP_EncryptUpdate - link

Interesting Signals

  • Uses .tmp_ file name before encrypting

  • Uses .crypt once file is processed successfully

  • Processes are killed if they have a shared memory lock to a file being encrypted

Remarks

Abyss Locker focuses on VM manipulation and file identification you can expect from a top-notch ESXi locker. It contains similar options seen in other ESXi ransomware, such as the managing of the VM instance shutdown process, key VM files and the use of the on device openSSL library.

However, a few differences are seen. The sample will check for shared memory locking of pages to a specific process and take actions accordingly to either skip the file or circumvent the owning process. The sample will also log a number of statistics about the encryption process to a specific file during all aspects of file processing, discovery, encryption context initialization and encrypting a file. Lastly, the encryptor swaps between file renaming using two different custom extensions '.tmp_' and '.crypt', this increases file system activity. It will be interesting to see how this capable encryptor shapes up over time.

Yara

/*
MIT License

Copyright 2023 ShadowStackRe.com

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

rule AbyssLocker {

meta:
      description = "rule to detect ESXi variant of AbyssLocker"
      author = "ShadowStackRe.com"
      date = "2023-08-13"
      Rule_Version = "v1"
      malware_type = "ransomware"
      malware_family = "Ransom:Linux/AbyssLocker"
      hash1 = "72310e31280b7e90ebc9a32cb33674060a3587663c0334daef76c2ae2cc2a462"
      License = "MIT License, https://opensource.org/license/mit/"

strings:
    $usage_string = "Usage:%s [-m (5-10-20-25-33-50) -v -d] Start Path" ascii
    $audit_log = "work.log" ascii
    $prog_opts = "m:vdekc:" ascii
    $daemon_switch = "switch to daemon" ascii
    $encrypt_progress = "porgress %s:%.2f GB\ttotal %.2f GB\t%.2f sec.\t%.4f GB\\s" ascii
    $file_ext = ".crypt" ascii
    $readme_ext = ".README_TO_RESTORE" ascii
    $readme_note = "We are the Abyss Locker" ascii

condition:
    all of them
}
Previous
Previous

Good Day Ransomware

Next
Next

Blacksuit Ransomware