how2heap-2.23-01-fastbin_dup

#include 
#include 
#include 

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);
}

fastbin支持的chunk大小

默认情况下,哪些大小的chunk释放可以放进fastbin

  • 32位系统:最大80字节
  • 64位系统:最大128字节(按照chunk 的size来说的,实际最大的是malloc(0x78))
#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

分配3个chunk malloc(8)

how2heap-2.23-01-fastbin_dup_第1张图片

释放chunk a

会在fastbinY[0]记录chunk a的地址
how2heap-2.23-01-fastbin_dup_第2张图片

分配chunk b

how2heap-2.23-01-fastbin_dup_第3张图片

fastbin是先进后出的

  • 最近释放的chunk的地址,会被放到fastbinY中
  • 原先的存储在fastbinY的地址,会被放在最新释放chunk的fd处

为什么直接释放chunk a(为什么不能连续释放chunk a)
因为会对fastbinY中之前释放的chunk与刚刚释放的chunk进行检查

if (__builtin_expect(old == p, 0)) {
    errstr = "double free or corruption (fasttop)";
    goto errout;
}

再次释放chunk a

how2heap-2.23-01-fastbin_dup_第4张图片

现在chunk a被释放了两次,这就是所谓的double-free

同时被释放的chunk,在fastbinY链中形成了一个循环链

从fastbin中申请chunk a

将fastbinY中存储的chunk申请出来,并将该chunk->fd中存储的地址放到fastbinY中
how2heap-2.23-01-fastbin_dup_第5张图片

fastbin 的利用方式

在上面,已经将chunk a给申请出来了,可以在chunk a的fd处写入想修改位置的地址-SIZE_SZ*2
再申请几次

  • malloc ,申请出chunk b
  • malloc,申请出chunk b中记录的chunk a
  • malloc,申请出chunk a中记录的欲修改的位置
    然后就可以对期望的位置进行修改了
    how2heap-2.23-01-fastbin_dup_第6张图片

需要注意的点

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,并将欲修改的位置链进去。
how2heap-2.23-01-fastbin_dup_第7张图片

在pwndbg中存在find_fake_fast命令,用于在欲修改的地址周围,搜索符合fastbin要求的地址

你可能感兴趣的:(二进制安全-01-pwn,linux,pwn)