Wednesday, April 10, 2019

Mozi botnet analysis

The sample in our hands is tagged by AV engines as Mirai. This is probably due to the sample sharing functionality/strings with Mirai. This sample is an ARM32 as per file:

ELF 32-bit LSB executable, ARM, version 1 (ARM), statically linked, stripped

When checking the headers of the file it can be observed that it is packed using UPX; something common in linux malware. However, when running UPX to unpack the program it returns an error:

xxd sample | head

upx -d sample

This is due to an unpacking technique common in IOT malware. This technique abuses the UPX headers to slow-down the analyst when analyzing this file. p_info is a struct that is important for the UPX unpacker to work properly:

While the header shows the correct UPX! header, the 

After UPX! the version can be found and the zeroes previous to the underline are member of p_progid; so what is next is p_filesize and p_blocksize that have been zeroed out (the underlined ones). Fortunately, the required values of p_filesize and p_blocksize can be found at the end:

What we need to do now is  to restore these bytes back to where they should be and we should be able to unpack the sample:  xxd -r mozi_patched.hex mozi.patched and get our unpacked file:

The initial setup consists of deleting previous presence of itself or required files that share the same names and setting up iptables to drop connections to several ports:

Deletes previous files named /usr/networkstmp and /usr/networks and writes new files with these names, these are copies of itself to persist

The stored ELF file is chosen depending on the target architecture (determined on execution) and the different headers for the different architectures can be found embedded in the source:

Pesistence is achieved by downloading the payload using HTTP from a remote address requests and storing the output in several scripts and every script attempt to spawn the binary in /usr/networks. In this fragment it can be spotted performing an HTTP request and storing data to a file.

To ensure that the system is not easily accessible it drops connections to known ports (SSH, TELNET) and 2323 is used by some devices for TELNET as an alternative to 23:

            run_bash_command((int)"iptables -I INPUT  -p tcp --destination-port 22 -j DROP");

            run_bash_command((int)"iptables -I INPUT  -p tcp --destination-port 23 -j DROP");

            run_bash_command((int)"iptables -I INPUT  -p tcp --destination-port 2323 -j DROP");

            run_bash_command((int)"iptables -I OUTPUT -p tcp --source-port 22 -j DROP");

            run_bash_command((int)"iptables -I OUTPUT -p tcp --source-port 23 -j DROP");

            run_bash_command((int)"iptables -I OUTPUT -p tcp --source-port 2323 -j DROP");

Everytime this sample stores bash scripts it appends exit 1 to the end of the script, unless the script that it its trying to infect already has content. In this case , it will spawn using the & operator the binary in /usr/networks, keep the original script code and append at the end exit 1:

A characteristic one is the following one named S95Baby stored in /etc/init.d/

Loads the lists of users and passwords for bruteforce attacks: 

Attacks against vulnerable devices using the realtek SDK


[ss] – Bot role

[ssx] – enable/disable tag [ss]

[cpu] – CPU architecture

[cpux] – enable/disable tag [cpu]

[nd] – new DHT node

[hp] – DHT node hash prefix

[atk] – DDoS attack type

[ver] – Value in V section in DHT protocol

[sv] – Update config

[ud] – Update bot

[dr] – Download and execute payload from the specified URL

[rn] – Execute the specified command

[dip] – ip:port to download Mozi bot

[idp] – report bot

[count] – URL that used to report bot


Every year I start writing about a wrap-up of my year but I never end up finishing it. Hope this year is different. I'm starting with th...