Dark Nexus: the old, the new and the ugly

In this blog post we will focus on an ARM7 Dark Nexus sample [1] and version v5 of this malware to highlight its functionality, both old and new, and to explore more invasive (or ugly) and innovative techniques. This sample was statically linked but not stripped making it easy to reverse and analyze.

Dark Nexus is an IoT botnet found by Bitdefender at the end of 2019 and beginning of 2020 [2]. According to their findings, this botnet had approximately 1,300 bots and was very prominent in Asia. Along with a white paper the company also released a list of 327 sample hashes related to this bot [3]. From this list, 231 sample files were actually found on Virus Total, showing these binary architectures:

image.png

The Old

Part of its code was based in Mirai. By comparing this unstripped sample to the codebase of Mirai we can see what was reused:

  • static ipv4_t get_random_ip(void)

  • void attack_udp_plain(uint8_t targs_len, struct attack_target *targs, uint8_t opts_len, struct attack_option *opts)

  • BOOL killer_kill_by_port(port_t port)

  • uint16_t checksum_generic(uint16_t *addr, uint32_t count)

  • uint16_t checksum_tcpudp(struct iphdr *iph, void *buff, uint16_t data_len, int len)

  • void resolv_entries_free(struct resolv_entries *entries)

  • struct resolv_entries *resolv_lookup(char *domain)

These functions were scrapped verbatim from the original Mirai source code and the matches have been found by comparing the function symbols from both the source code and the binary sample. Other functions (eg. rand_port, retrieve_c2_server or attack_tcp_raw) are based on original Mirai functions but modified to fit the necessities of the author.

The downside of reusing Mirai’s codebase is that some of the favorable aspects of its code are often ignored. That’s the case of the encrypted data table. This table is the one in charge of converting encrypted or obfuscated strings and data to its normal state, be it integers or strings. Dark Nexus on the other hand shows passwords, usernames, command-and-control endpoints, etc. are in plain-text or deobfuscated. For example, the function retrieve_c2_server (Mirai’s retireve_cnc_addr) was adapted to resolve more than one C&C address. These addresses are in plain-text in the main function of the bot (Figure 1).

Figure 1. Hardcoded C&C list populated to later be used by the bot.

Figure 1. Hardcoded C&C list populated to later be used by the bot.

Another old method still used by this malware and many others is the Telnet brute forcing as a method of growing its botnet. Insecure Telnet services are nothing new among IoT malware and attacking them keeps being effective nowadays as devices with weak credentials are accessible from the internet. Dark Nexus does this by calling spreader_init to populate its username/password structures and  then init_syn_bruter. The latest will start the attack against telnet services across the Internet and try to infect as many devices as possible under these CPU architectures:

  1. arm

  2. rce

  3. sh4

  4. arc

  5. ppc

  6. mk68

  7. spc

  8. x86

  9. i586

  10. mpsl / mips

Figure 2. Hardcoded domain name and IP address in init_syn_bruter function.

Figure 2. Hardcoded domain name and IP address in init_syn_bruter function.

Figure 3. The malware spreads on multiple architectures to have a wider range of infection.

Figure 3. The malware spreads on multiple architectures to have a wider range of infection.

The New

Dark Nexus presents new techniques as well. Here we are going to mention two that we consider interesting to show and describe: Reverse Proxy and Killer functions. These functions were already seen on other malware but have a twist that’s worth mentioning.

Reverse Proxy

One technique employed by this malware is reverse proxying requests to always be able to deliver malware to new infections. It does this by first identifying who executed the malware, saving the IP and port addresses from the command line used during the execution (Figure 4). After this, the function init_reverse_proxy. This function is one improvement to common IoT malware, giving autonomy and self reliance to its bots. It starts by forking and connecting to its C&C servers to download the multiple binaries that belong to each supported architecture. If the malware wasn’t able to connect to any C&C server it will reach out to the IP and port registered during execution (Figure 4) to perform that action. After arming itself with multiple bot variants, it will listen to a random port for GET requests to serve its binaries, acting as a pseudo-HTTP server (Figure 5).

Figure 4. IP and port reported by the bot that infected and ran the malware sample. This will later be used as a replacement for it’s C&Cs if needed.

Figure 4. IP and port reported by the bot that infected and ran the malware sample. This will later be used as a replacement for it’s C&Cs if needed.

Figure 5. User-Agent used by the malware is: hoho_fastflux/v5. The string “hoho” is commonly used throughout this malware.

Figure 5. User-Agent used by the malware is: hoho_fastflux/v5. The string “hoho” is commonly used throughout this malware.

Killer

The idea of a killer comes straight from its Mirai codebase. The purpose of the killer is to block ports utilized by services like SSH and Telnet to avoid further invasion by other malware or clients. Also, it kills any previous invasion in order to do a full takeover of the device.

The killer process is initialized by Dark Nexus by the killer function by forking into another process while saving its own process ID (PID) ina variable called lockdown_pid, which will be discussed later. After that it will create an structure called suspect_list that will keep track of the processes being analyzed and judged by the malware (Figure 6). This structure is based on the PID of the analyzed process in the device and a “weight” which is an attribute that will define if the process is a threat to the bot and needs to be terminated. The The function killer_run is then called and it will read all the process IDs from the /proc directory and weight the threat of the current process (PID) being analyzed by:

1) Reading /proc/PID/exec and check if the executable of the process exists on the filesystem. If it was deleted and appears as "(deleted)" then add +100 of weight

2) Check /proc/PID/exec real path by using the readlink function. If binary is running in one of these paths to kill then add +90 of weight:

  • /tmp/

  • /var/

  • /dev//var/tmp/

  • /var/run/

  • /

The paths to kill list is hardcoded in the binary.
3) Open the directory /proc/PID/fd to read list of open files. If the list is greater than 250 then add +10 weight.

4) Open /proc/PID/cmdline to read the command line of the process. If starts with "./" it will add +10 weight.

5) Open /proc/PID/status and check if it has the string "Groups:\t0". It will add +50 weight if it does.

6) Open the process’ binary in /proc/PID/exe and read its strings. If ".dynamic" was not found meaning that is a possible static binary then add +50 weight. If the string "UPX" is found then add +90 weight, as it is possible that the binary was also packed.

At the end of this process the malware will check the suspects list and, if the weight is above 99 points it will kill the process as it imposes a threat to the bot (Figure 7).

Figure 6. Function (and process) killer is initialized along with the structure in charge of keeping track of the processes being analyzed.

Figure 6. Function (and process) killer is initialized along with the structure in charge of keeping track of the processes being analyzed.

Figure 7. Bot recursively checks all the processes’ weight and calls kill() to terminate whoever it finds threatening for its functioning.

Figure 7. Bot recursively checks all the processes’ weight and calls kill() to terminate whoever it finds threatening for its functioning.

The Ugly

The final purpose of an IoT malware is the complete take over of the device and to persist without intervention. Or digital intervention at least, as you can always just pull the plug in most of the cases. Dark Nexus has a set of functions that ensure that no intervention is made in order to stop the bot from doing its botmaster’s work.

Persistence

In case of the persistence, Dark Nexus chooses to disable all ways for an intruder or legitimate user to reestablish the device normal behaviour by limiting execution of system commands (Figure 8). It does this by changing the file permissions to 0, thus removing the read and execute permissions to avoid them being utilized (Figure 9).

The bot will also flush the iptables (firewall) rules and stop the “crond” daemon, the one in charge of execute scheduled commands on the system. To ensure its correct functioning when scanning for victims, and also reading process IDs during the killer function, the bot will set the limit of open file descriptors to 0x1000 (or 4096 in decimal numbers).

Figure 8. Methods used by the bot to impede the system from being restored.

Figure 8. Methods used by the bot to impede the system from being restored.

Figure 9. The bot removes all permissions on specific executables so no restoration of the device is possible.

Figure 9. The bot removes all permissions on specific executables so no restoration of the device is possible.

One interesting side note on this section is that, in the case of BusyBox [4], all those binaries are symbolic links to /bin/busybox. Meaning that if the bot changes the permissions of any of those binaries it will be ultimately changing the permissions of the latter. If that happens the whole system renders useless.

Lockdown

Dark Nexus performs a lockdown of the devices and ensures that it stays that way during its execution. Lockdown is performed after the persistence procedure is in place to add an extra layer of control over the device. This lockdown phase starts with the init_lockdown function that counts the amount of PIDs currently existing in the device and then saves those PIDs into a list called lockdown_pidlist. After the bot starts its normal execution and every 2 seconds the function ensure_lockdown is called.

The ensure_lockdown function is the one in charge of killing any new process being created after the bot was executed. What it will do is to open the directory /proc and read the existent PIDs, and kill those PIDs that match this criteria (Figure 10):

  1. Is not one of the attack processes.

  2. Is not the process ID of one of these processes: bot, lockdown, scanner and reverse proxy.

  3. PID is greater than 799.

Figure 10. Main part of the lockdown process. This ensures no intruder or legitimate process is started as it gets killed if is not present in the lockdown PID list.

Figure 10. Main part of the lockdown process. This ensures no intruder or legitimate process is started as it gets killed if is not present in the lockdown PID list.

Conclusion

In this blog post we were able to take a sneak peek of what is Dark Nexus capable of and its details. We explored this by presenting it via three characteristics we named the old, the new and the ugly. In The Old we showed how this malware imported a great deal of ideas and code from a well-known IoT malware: Mirai. This is done regularly as Mirai source code was made public since 2016 and its well structured, and easy to modify, code is the perfect fit for any new malware. A good side of this is that it makes the malware easy to identify as well as to analyze.

On the other hand, in The New we presented new ideas that were adapted to work with this “old” code. Ideas like the reverse proxy that enables the bot to be more independent from it’s C&C or distribution endpoints. Or the killer function which evolved from it’s more primitive variant seen in Mirai to a more intuitive one, analyzing and judging the processes being executed in the device by its characteristics.

Finally, we present two functions that are of a questionable nature in The Ugly. These procedures, like persistence and lockdown, turn the device being infected into a “brick”, inaccessible and unrecoverable from the outside world. And a device that cannot be accessed is a device that cannot be fixed.

All these characteristics show that IoT malware is improving while retaining its roots, and Dark Nexus is the clear sign of this.

References

[1] VirusTotal (2020, April 09). bc0457d7935e29aecb338756bde213cd18aa1b617b00d30c4deedd5eef9ba877. https://www.virustotal.com/gui/file/bc0457d7935e29aecb338756bde213cd18aa1b617b00d30c4deedd5eef9ba877/details
[2] Liviu Arsene, Bitdefender (2020, April 08). New dark_nexus IoT Botnet Puts Others to Shame. https://labs.bitdefender.com/2020/04/new-dark_nexus-iot-botnet-puts-others-to-shame/
[3] Bitdefender Investigations and Forensics Unit, Bitdefender (2020). New dark_nexus IoT Botnet Puts Others to Shame (Whitepaper). https://www.bitdefender.com/files/News/CaseStudies/study/319/Bitdefender-PR-Whitepaper-DarkNexus-creat4349-en-EN-interactive.pdf
[4] Denys Vlasenko. BusyBox: The Swiss Army Knife of Embedded Linux. https://busybox.net/
[5] jgamblin, GitHub (2020, October 23). Mirai-Source-Code. https://github.com/jgamblin/Mirai-Source-Code