██████╗  ██████╗ ██╗  ██╗ █████╗ 
╚════██╗██╔═══██╗██║  ██║██╔══██╗
 █████╔╝██║   ██║███████║███████║
 ╚═══██╗██║   ██║██╔══██║██╔══██║
██████╔╝╚██████╔╝██║  ██║██║  ██║
╚═════╝  ╚═════╝ ╚═╝  ╚═╝╚═╝  ╚═╝

Welcome to 3OHA, a place for random notes, thoughts, and factoids that I want to share or remember.



21 December 2022

Bash malware (II): The DarkRadiation ransomware

DarkRadiation is a ransomware targeting Linux and Docker containers that was first spotted in the wild in May 2021. It is part of a collection of shell scripts that include not only several versions of the ransomware sample but also an SSH worm (which is also a Bash script) and other supporting tools. Trend Micro and SentinelOne reported on DarkRadiation in June 2021.

The sample I analyzed was dubbed supermicro_cr and has hash 1c2b09417c1a34bbbcb8366c2c184cf31353acda0180c92f99828554abf65823. The ransomware is implemented in 272 lines of a Bash script that is not obfuscated. Both the original sample and the beautified version that I prepared (slightly reformatted and profusely commented) are available in this GitHub repository.

Operation

The DarkRadiation ransomware works as follows:

  1. It checks that the environment is okay for execution. Specifically, it checks that the script runs with root privileges and that its dependencies (curl, wget, openssl) are installed in the system. If not, it tries to install them via both the apt and yum package managers.
  2. The sample then downloads and installs what appears to be a Telegram bot from a hardcoded endpoint. The program is saved as /usr/share/man/man8/supermicro_bt and then executed.
  3. It then calls home to report it's been installed. It does so using the Telegram API with a hardcoded API key. This communication channel is used throughout the code to report about the progress of the file encryption process.
  4. The sample then enters a loop in which it checks every minute if it should start the encryption process. It does so by trying to grab a text file named 0.txt from a remote endpoint. Successful downloading the file triggers the encryption process, which consists of the following steps:
    1. It creates a user account with username ferrum and a password grabbed from an endpoint.
    2. It effectively disables all other user accounts in the system by changing their passwords, removing them from the wheel group, disabling their login shells and killing all processes of logged on users. Only one user (jackie in the sample I analyzed) is left out of this process.
    3. It then encrypts the following items and remove the original files afterward:
    4. The encrypted files retain their original names but are given as extension a radioactive symbol (.☢). The encryption is done on a file-basis using AES-256-CBC, such as in the following snippet:
      grep -r '/home' -e "" --include=\*.* -l | tr '\n' '\0' | xargs -P 10 -I FILE -0 openssl enc -aes-256-cbc -salt -pass pass:$PASS_DEC -in FILE -out FILE.☢
      
      The encryption/decryption password ($PASS_DEC) is generated using contents retrieved via curl from a remote endpoint
    5. It then stops and disables the docker service and removes docker images and containers (rm -rf /var/lib/docker/), if any.
    6. It puts the following message in the message-of-the-day system:
    7. create_message ()
      {
      cat>/etc/motd << EOF
      █████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
      ███████▀▀▀░░░░░░░▀▀▀█████████████████▀▀▀░░░░░░░▀▀▀█████████████████▀▀▀░░░░░░░▀▀▀█████████████████▀▀▀░░░░░░░▀▀▀███████
      ████▀░░░░░░░░░░░░░░░░░▀███████████▀░░░░░░░░░░░░░░░░░▀███████████▀░░░░░░░░░░░░░░░░░▀███████████▀░░░░░░░░░░░░░░░░░▀████
      ███│░░░░░░░░░░░░░░░░░░░│█████████│░░░░░░░░░░░░░░░░░░░│█████████│░░░░░░░░░░░░░░░░░░░│█████████│░░░░░░░░░░░░░░░░░░░│███
      ██▌│░░░░░░░░░░░░░░░░░░░│▐███████▌│░░░░░░░░░░░░░░░░░░░│▐███████▌│░░░░░░░░░░░░░░░░░░░│▐███████▌│░░░░░░░░░░░░░░░░░░░│▐██
      ██░└┐░░░░░░░░░░░░░░░░░┌┘░███████░└┐░░░░░░░░░░░░░░░░░┌┘░███████░└┐░░░░░░░░░░░░░░░░░┌┘░███████░└┐░░░░░░░░░░░░░░░░░┌┘░██
      ██░░└┐░░░░░░░░░░░░░░░┌┘░░███████░░└┐░░░░░░░░░░░░░░░┌┘░░███████░░└┐░░░░░░░░░░░░░░░┌┘░░███████░░└┐░░░░░░░░░░░░░░░┌┘░░██
      ██░░┌┘▄▄▄▄▄░░░░░▄▄▄▄▄└┐░░███████░░┌┘▄▄▄▄▄░░░░░▄▄▄▄▄└┐░░███████░░┌┘▄▄▄▄▄░░░░░▄▄▄▄▄└┐░░███████░░┌┘▄▄▄▄▄░░░░░▄▄▄▄▄└┐░░██
      ██▌░│██████▌░░░▐██████│░▐███████▌░│██████▌░░░▐██████│░▐███████▌░│██████▌░░░▐██████│░▐███████▌░│██████▌░░░▐██████│░▐██
      ███░│▐███▀▀░░▄░░▀▀███▌│░█████████░│▐███▀▀░░▄░░▀▀███▌│░█████████░│▐███▀▀░░▄░░▀▀███▌│░█████████░│▐███▀▀░░▄░░▀▀███▌│░███
      ██▀─┘░░░░░░░▐█▌░░░░░░░└─▀███████▀─┘░░░░░░░▐█▌░░░░░░░└─▀███████▀─┘░░░░░░░▐█▌░░░░░░░└─▀███████▀─┘░░░░░░░▐█▌░░░░░░░└─▀██
      ██▄░░░▄▄▄▓░░▀█▀░░▓▄▄▄░░░▄███████▄░░░▄▄▄▓░░▀█▀░░▓▄▄▄░░░▄███████▄░░░▄▄▄▓░░▀█▀░░▓▄▄▄░░░▄███████▄░░░▄▄▄▓░░▀█▀░░▓▄▄▄░░░▄██
      ████▄─┘██▌░░░░░░░▐██└─▄███████████▄─┘██▌░░░░░░░▐██└─▄███████████▄─┘██▌░░░░░░░▐██└─▄███████████▄─┘██▌░░░░░░░▐██└─▄████
      █████░░▐█─┬┬┬┬┬┬┬─█▌░░█████████████░░▐█─┬┬┬┬┬┬┬─█▌░░█████████████░░▐█─┬┬┬┬┬┬┬─█▌░░█████████████░░▐█─┬┬┬┬┬┬┬─█▌░░█████
      ████▌░░░▀┬┼┼┼┼┼┼┼┬▀░░░▐███████████▌░░░▀┬┼┼┼┼┼┼┼┬▀░░░▐███████████▌░░░▀┬┼┼┼┼┼┼┼┬▀░░░▐███████████▌░░░▀┬┼┼┼┼┼┼┼┬▀░░░▐████
      █████▄░░░└┴┴┴┴┴┴┴┘░░░▄█████████████▄░░░└┴┴┴┴┴┴┴┘░░░▄█████████████▄░░░└┴┴┴┴┴┴┴┘░░░▄█████████████▄░░░└┴┴┴┴┴┴┴┘░░░▄█████
      ███████▄░░░░░░░░░░░▄█████████████████▄░░░░░░░░░░░▄█████████████████▄░░░░░░░░░░░▄█████████████████▄░░░░░░░░░░░▄███████
      ██████████▄▄▄▄▄▄▄███████████████████████▄▄▄▄▄▄▄███████████████████████▄▄▄▄▄▄▄███████████████████████▄▄▄▄▄▄▄██████████
      
      ██╗   ██╗ ██████╗ ██╗   ██╗    ██╗    ██╗███████╗██████╗ ███████╗    ██╗  ██╗ █████╗  ██████╗██╗  ██╗███████╗██████╗ 
      ╚██╗ ██╔╝██╔═══██╗██║   ██║    ██║    ██║██╔════╝██╔══██╗██╔════╝    ██║  ██║██╔══██╗██╔════╝██║ ██╔╝██╔════╝██╔══██╗
       ╚████╔╝ ██║   ██║██║   ██║    ██║ █╗ ██║█████╗  ██████╔╝█████╗      ███████║███████║██║     █████╔╝ █████╗  ██║  ██║
        ╚██╔╝  ██║   ██║██║   ██║    ██║███╗██║██╔══╝  ██╔══██╗██╔══╝      ██╔══██║██╔══██║██║     ██╔═██╗ ██╔══╝  ██║  ██║
         ██║   ╚██████╔╝╚██████╔╝    ╚███╔███╔╝███████╗██║  ██║███████╗    ██║  ██║██║  ██║╚██████╗██║  ██╗███████╗██████╔╝
         ╚═╝    ╚═════╝  ╚═════╝      ╚══╝╚══╝ ╚══════╝╚═╝  ╚═╝╚══════╝    ╚═╝  ╚═╝╚═╝  ╚═╝ ╚═════╝╚═╝  ╚═╝╚══════╝╚═════╝ 
      
                                                                                     
      Contact us on mail: nationalsiense@protonmail.com
      您已被黑客入侵!您的数据已被下载并加密。请联系Email:nationalsiense@protonmail.com。如不联系邮件,将会被采取更严重的措施。 
      EOF
      }
      
    8. Finally, it tries to wipe the free disk space (where the contents of the original files that have just been removed still are) by using the following trick:
      del_zero ()
      {
         dd if=/dev/zero of=/null
         rm -rf /null
      }
      
      There's nothing wrong with this, which is actually a neat way of getting the job done. However, it's unclear to me why the designers chose this option instead of, say, using shred to wipe all files after encrypting them.
    9. The script then exits.

An unfinished sample?

Some elements in the code make me think that this could be an unfinished sample that is still in development. For example, the $PATH_TEMP_FILE variable in check_root() is undefined. Some other variables are never used, such as $PASS_ENC or PATH_FILE. Also, the user_change() function contains two very obvious bugs that would be easily spotted with some testing or code review:

  1. The exception when disabling all user accounts is for a user named jackie. I presume that it should be the username which has just been created instead (ferrum).
  2. The filter to kill all processes whose controlling terminal is associated with a logged on user (except this process) is not very accurate. The cut filter looks for exactly 6 spaces to identify the tty field, but this might not always be the case.

Another interesting point is that the password generation process does not use salt, which is recommended to avoid (potential) brute force attacks. More importantly, the password generation method used by the sample is deprecated, and openssl recommends to use -iter or pbkdf2 instead.



© 2022 Juan Tapiador