【PWN · Heap · how2heap】[fastbin_dup.c]

开始学习PWN堆相关的部分时,被繁复的知识冲昏了头脑。了解到how2heap是国外大神的系列堆漏洞小实验,于是尝试通过复现这些漏洞,并提取知识点。


一、fastbin_dup.c

#include 
#include 
#include 

int main()
{
	setbuf(stdout, NULL);
	printf("This file demonstrates a simple double-free attack with fastbins.\n");
	//在Glibc的2.26中 新增了Tcache机制 这里将其填充完毕 不影响我们继续fastbin
	printf("Fill up tcache first.\n");
	void *ptrs[8];
	for (int i=0; i<8; i++) {
		ptrs[i] = malloc(8);
	}
	for (int i=0; i<7; i++) {
		free(ptrs[i]);
	}
  //动态申请了三块内存,大小为8,tcache满了,所以就放到fastbins里
	//c用于和未分配的内存块隔开,避免合并
	printf("Allocating 3 buffers.\n");
	int *a = calloc(1, 8);
	int *b = calloc(1, 8);
	int *c = calloc(1, 8);

	printf("1st calloc(1, 8): %p\n", a);
	printf("2nd calloc(1, 8): %p\n", b);
	printf("3rd calloc(1, 8): %p\n", c);
	//将a第一次free,这时a的地址就被放到了fastbins中
	printf("Freeing the first one...\n");
	free(a);
	//虽然会有double free漏洞,但是fastbins还是会做一些基本的检查,连续两块链表节点不能一样,简单来说不能紧邻free
	printf("If we free %p again, things will crash because %p is at the top of the free list.\n", a, a);
	// free(a);
	//通过free一块别的内存,让fastbins中的链表结构为a->b->a,将两个a隔开,避免报错
	printf("So, instead, we'll free %p.\n", b);
	free(b);
	//double free
	printf("Now, we can free %p again, since it's not the head of the free list.\n", a);
	free(a);
	//fastbins中,块大小为8的链表结构为 a->b->a->0
	printf("Now the free list has [ %p, %p, %p ]. If we malloc 3 times, we'll get %p twice!\n", a, b, a, a);
	//连续malloc,内存从fastbins中选取合适的进行分配
	//b->a->0
	a = calloc(1, 8);
	//a->0
	b = calloc(1, 8);
	//->0
	c = calloc(1, 8);
	printf("1st calloc(1, 8): %p\n", a);
	printf("2nd calloc(1, 8): %p\n", b);
	printf("3rd calloc(1, 8): %p\n", c);
	assert(a == c);
}


二、分析过程

在Glibc的2.26中 新增了Tcache机制,因此在做fastbin的实验时,需要向先将tcache填满,保证我们free掉的内存块会被记录在fastbins中。

具体过程如下:

我们连续申请三块内存a,b,c,其作用——a用于double free,b用于避免触发fastbins的纠错机制,c用于隔离已分配区域与未分配区域从而避免free时合并。

先期tcache已经被填满,接下来不会free到tcache

(这里有点疑问,为什么分配abc时,不从tcache中取呢?确实没从中取,经过pwndbg调试过)

(——再次经过pwndbg,此时我将所有的calloc改成了malloc,发现malloc时,tcache中的块被取出用于分配。说明这是calloc的原因)

     free(a),a指针地址记录到fastbins。 →a→0

        free(b),b指针地址记录到fastbins。→b→a→0

        free(a),a指针的地址再次记录到fastbins。→a→b→a→0

开始连续申请三块8bytes内存(fastbins最小的一组是16bytes,加上两个控制字段,共0x20bytes)。

        申请第一块,从fastbins的0x20链中,取出第一块 ——> 原a的地址 ——> 赋给a

        申请第二块,从fastbins的0x20链中,取出第二块 ——> 原b的地址 ——> 赋给b

        申请第三块,从fastbins的0x20链中,取出第三块 ——> 原a的地址 ——> 赋给c

结果就是 a==c 

你可能感兴趣的:(how2heap,heap)