#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
int main()
{
fprintf(stderr, "This file demonstrates a simple double-free attack with fastbins.\n");
fprintf(stderr, "Allocating 3 buffers.\n");
int *a = malloc(8);
int *b = malloc(8);
int *c = malloc(8);
fprintf(stderr, "1st malloc(8): %p\n", a);
fprintf(stderr, "2nd malloc(8): %p\n", b);
fprintf(stderr, "3rd malloc(8): %p\n", c);
fprintf(stderr, "Freeing the first one...\n");
free(a);
fprintf(stderr, "If we free %p again, things will crash because %p is at the top of the free list.\n", a, a);
// free(a);
fprintf(stderr, "So, instead, we'll free %p.\n", b);
free(b);
fprintf(stderr, "Now, we can free %p again, since it's not the head of the free list.\n", a);
free(a);
fprintf(stderr, "Now the free list has [ %p, %p, %p ]. If we malloc 3 times, we'll get %p twice!\n", a, b, a, a);
a = malloc(8);
b = malloc(8);
c = malloc(8);
fprintf(stderr, "1st malloc(8): %p\n", a);
fprintf(stderr, "2nd malloc(8): %p\n", b);
fprintf(stderr, "3rd malloc(8): %p\n", c);
assert(a == c);
}
默认情况下,哪些大小的chunk释放可以放进fastbin
#ifndef DEFAULT_MXFAST
#define DEFAULT_MXFAST (64 * SIZE_SZ / 4)
可以支持的fastbin最大大小
#define MAX_FAST_SIZE (80 * SIZE_SZ / 4)
通过mallopt
设置fastbin支持的大小
int mallopt(int param,int value)
https://baike.baidu.com/item/mallopt/1731899
https://blog.csdn.net/u013920085/article/details/52847464
https://www.cnblogs.com/ho966/p/17671723.html
还可以通过漏洞修改glibc中的全局变量global_max_fast
,使fastbin支持的大小,超过MAX_FAST_SIZE
malloc(8)
会在fastbinY[0]记录chunk a的地址
fastbin是先进后出的
为什么直接释放chunk a(为什么不能连续释放chunk a)
因为会对fastbinY中之前释放的chunk与刚刚释放的chunk进行检查
if (__builtin_expect(old == p, 0)) {
errstr = "double free or corruption (fasttop)";
goto errout;
}
现在chunk a被释放了两次,这就是所谓的double-free
同时被释放的chunk,在fastbinY链中形成了一个循环链
将fastbinY中存储的chunk申请出来,并将该chunk->fd中存储的地址放到fastbinY中
在上面,已经将chunk a给申请出来了,可以在chunk a的fd处写入想修改位置的地址-SIZE_SZ*2
再申请几次
fastbinY中最大可以存放10个fastbin链,默认情况下仅使用了前7个。在从fastbin中申请chunk的时候,会检查该链中chunk的是否确实属于该fastbin链,检查的是在fastbin中的下标,实际检查的是该chunk的size
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;
}
所以欲修改的位置之前需要有一个正确的fastbin的size(这个位置不一定必须是前8个字节)。
只要这个size和欲修改的位置,包含在一个允许的fastbin大小中就行。
然后为了适应这个欲修改位置的fastbin,需要自己申请malloc合适该chunk的大小,再释放到fastbin,并将欲修改的位置链进去。
在pwndbg中存在find_fake_fast
命令,用于在欲修改的地址周围,搜索符合fastbin要求的地址