文章目录
- chunk extend/overlapping
- fastbin与topchunk相邻free时候不会合并
- unsortedbinchunk中与topchunk相邻的被free时会合并
- extend向后overlapping
- 先修改header,再free,再malloc
- 先free,再修改header,再malloc
- extend向前overlapping
- 利用放入unsorted bin之前的合并机制
- 先修改header,再free,再malloc
- 先free,再修改header,再malloc
chunk extend/overlapping
其实就是使得得到chunk的大小扩大,从而能够覆盖到原本不属于本chunk的内存部分(覆盖其他chunk)。从而控制写该部分内存的内容
条件:可修改chunk header的数据,修改后有再次mallloc申请对应修改后对应在bin的chunk的机会,这样才能使得修改有用最终实现扩展chunk范围
fastbin与topchunk相邻free时候不会合并
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <stdint.h>
int main()
{void *ptr1,*ptr2,*ptr3,*ptr4,*ptr5,*ptr6,*ptr7,*ptr8,*ptr9;ptr1=malloc(0x10);//分配第1个 0x10 的chunk1ptr2=malloc(0x10);//分配第1个 0x10 的chunk1ptr3=malloc(0x10);//分配第1个 0x10 的chunk1ptr4=malloc(0x10);//分配第1个 0x10 的chunk1ptr5=malloc(0x10);//分配第1个 0x10 的chunk1ptr6=malloc(0x10);//分配第1个 0x10 的chunk1ptr7=malloc(0x10);//分配第1个 0x10 的chunk1ptr8=malloc(0x10);//分配第1个 0x10 的chunk1free(ptr1);free(ptr2);free(ptr3);free(ptr4);free(ptr5);free(ptr6);free(ptr7);free(ptr8);}
结果
unsortedbinchunk中与topchunk相邻的被free时会合并
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <stdint.h>
int main()
{void *ptr1,*ptr2,*ptr3,*ptr4,*ptr5,*ptr6,*ptr7,*ptr8,*ptr9;ptr1=malloc(0x80);//分配第1个 0x80 的chunk1ptr2=malloc(0x80);//分配第1个 0x80 的chunk1ptr3=malloc(0x80);//分配第1个 0x80 的chunk1ptr4=malloc(0x80);//分配第1个 0x80 的chunk1ptr5=malloc(0x80);//分配第1个 0x80 的chunk1ptr6=malloc(0x80);//分配第1个 0x80 的chunk1ptr7=malloc(0x80);//分配第1个 0x80 的chunk1ptr8=malloc(0x80);//分配第1个 0x80 的chunk1free(ptr1);free(ptr2);free(ptr3);free(ptr4);free(ptr5);free(ptr6);free(ptr7);free(ptr8);}
extend向后overlapping
此时是修改size较大,从而使得chunk内容范围扩大,从而能覆盖到高地址的内容
具体可以分先修改size再free,再malloc和先free,再修改,再malloc两个类型
此时注意源码中的各个检测
此时是fastbin libc2.23的源码,此时是malloc时候的源码
if ((unsigned long) (nb) <= (unsigned long) (get_max_fast ())){idx = fastbin_index (nb);mfastbinptr *fb = &fastbin (av, idx);mchunkptr pp = *fb;do{victim = pp;if (victim == NULL)break;}while ((pp = catomic_compare_and_exchange_val_acq (fb, victim->fd, victim))!= victim);if (victim != 0){*/if (__builtin_expect (fastbin_index (chunksize (victim)) != idx, 0)){errstr = "malloc(): memory corruption (fast)";errout:malloc_printerr (check_action, errstr, chunk2mem (victim), av);return NULL;}check_remalloced_chunk (av, victim, nb);void *p = chunk2mem (victim);alloc_perturb (p, bytes);return p;}}
检查函数
static void
do_check_remalloced_chunk (mstate av, mchunkptr p, INTERNAL_SIZE_T s)
{INTERNAL_SIZE_T sz = p->size & ~(PREV_INUSE | NON_MAIN_ARENA);if (!chunk_is_mmapped (p)){assert (av == arena_for_chunk (p));if (chunk_non_main_arena (p))assert (av != &main_arena);elseassert (av == &main_arena);}do_check_inuse_chunk (av, p);/* Legal size ... */assert ((sz & MALLOC_ALIGN_MASK) == 0);assert ((unsigned long) (sz) >= MINSIZE);/* ... and alignment */assert (aligned_OK (chunk2mem (p)));/* chunk is less than MINSIZE more than request */assert ((long) (sz) - (long) (s) >= 0);assert ((long) (sz) - (long) (s + MINSIZE) < 0);
}
do_check_inuse_chunk (av, p);函数
static void
do_check_inuse_chunk (mstate av, mchunkptr p)
{mchunkptr next;do_check_chunk (av, p);if (chunk_is_mmapped (p))return; /* mmapped chunks have no next/prev *//* Check whether it claims to be in use ... */assert (inuse (p));next = next_chunk (p);/* ... and is surrounded by OK chunks.Since more things can be checked with free chunks than inuse ones,if an inuse chunk borders them and debug is on, it's worth doing them.*/if (!prev_inuse (p)){/* Note that we cannot even look at prev unless it is not inuse */mchunkptr prv = prev_chunk (p);assert (next_chunk (prv) == p);do_check_free_chunk (av, prv);}if (next == av->top){assert (prev_inuse (next));assert (chunksize (next) >= MINSIZE);}else if (!inuse (next))do_check_free_chunk (av, next);
}
先修改header,再free,再malloc
对于fastbin
修改可free至faastbin的chunk的size大小,使其覆盖下一个目标chunk,free后再malloc可得到覆盖目标chunk的大chunk
#include<stdio.h>
#include <stdlib.h>int main(void)
{void *ptr,*ptr1,*ptr2;ptr=malloc(0x10);//分配第一个0x10的chunkptr2=malloc(0x10);//分配第二个0x10的chunk//free(ptr2)不影响后面的extend*(long long *)((long long)ptr-0x8)=0x41;// 修改第一个块的size域free(ptr);ptr1=malloc(0x30);// 实现 extend,控制了第二个块的内容printf("控制的地址:%p",ptr1);return 0;
}
此时修改0x41的1是pre_inuse位,因为此时为1方便绕过检查,此时
对于不属于fastbin
当free一个不属于fastbin的的chunk,并且该chunk不与topchunk相邻,该chunk会被首先放到unsortedbin中。修改其size大小,使其覆盖下一个目标chunk,free后再malloc可得到覆盖目标chunk的大chunk
#include<stdio.h>#include <stdlib.h>
int main()
{void *ptr,*ptr1,*ptr2,*ptr3;ptr=malloc(0x80);//分配第一个 0x80 的chunk1ptr2=malloc(0x10); //分配第二个 0x10 的chunk2ptr3=malloc(0x10); //防止与top chunk合并*(int *)(ptr-0x8)=0xb1; //此时覆盖后的下一个chunk为ptr3free(ptr);ptr1=malloc(0xa0);printf("控制的地址为:%p",ptr1);
}
先free,再修改header,再malloc
对于fastbin
由于free后malloc取出的chunk会检查size是否正确,如果此时被修改将会报错,所以不行
对于不属于fastbin
当free一个不属于fastbin的的chunk,并且该chunk不与topchunk相邻,该chunk会被首先放到unsortedbin中。先free,然后修改该chunksize大小,最后再次申请即可覆盖
#include<stdio.h>
#include <stdlib.h>
int main()
{void *ptr,*ptr1,*ptr2,*ptr3;ptr=malloc(0x80);//分配第一个0x80的chunk1ptr2=malloc(0x10);//分配第二个0x10的chunk2free(ptr);//首先进行释放,使得chunk1进入unsorted bin*(int *)(ptr-0x8)=0xb1;ptr1=malloc(0xa0);printf("控制的地址为:%p",ptr1);
}
extend向前overlapping
利用放入unsorted bin之前的合并机制
前向 extend 利用了 然后再将合并chunk放到unsorted bin中(不能与topchunk相邻),通过修改 pre_size 域可以跨越多个 chunk (即根据pre_size和pre_inuse确定的前一个chunk可能实际涵盖了多个实际的chunk)进行合并实现 overlapping。
通过修改当前chunk的pre_inuse和pre_size,当free当前chunk时,会根据pre_size和pre_inuse确定的前一个chunk的地址可是否free,如果是pre_inuse为0从而实现合并
先修改header,再free,再malloc
#include<stdio.h>
#include <stdlib.h>
int main(void)
{void *ptr1,*ptr2,*ptr3,*ptr4,*ptr5,*ptr6;ptr1=malloc(128);//smallbin1ptr2=malloc(0x10);//fastbin1ptr3=malloc(0x10);//fastbin2ptr4=malloc(128);//smallbin2ptr5=malloc(0x10);//防止与top合并free(ptr1);//使得下个chunk对应的前一个chunk是free的*(int *)((long long)ptr4-0x8)=0x90;//修改pre_inuse域*(int *)((long long)ptr4-0x10)=0xd0;//修改pre_size域free(ptr4);//unlink进行前向extendptr6=malloc(0x150);//得到extend的chunkprintf("控制的地址为:%p",ptr6);
}
先free,再修改header,再malloc
没用,因为free时才会合并,如果先free后再修改,那么将不会有任何合并操作