Unsorted bin Attack



Unosrted bin Attack 是利用glibc malloc中对unsorted bin的插入删除处理时,没有对指针进行判断,从而造成的可将任意地址写成unsortedbin(av)地址的漏洞,一般用在漏洞利用的开始阶段,为下一步劫持控制流创造条件。

原理

unsorted bin

Unsorted bin是small bins和large bins的cache,以双向链表管理空闲chunk,空闲chunk不排序。

所有的chunk在回收时都要先放到unsorted bin中,在下一次分配时,如果在unsorted bin中没有合适的chunk,就会把unsorted bin中的所有chunk分别加入到所属的bins中,然后再在bin中分配合适的chunk。
Bins数组中的元素bin[1]用于存储unsorted bin的chunk链表头。

unsorted bin的由于和smallbins一样,它的操作与smallbins也类似。

上面的宏定义比较明显,把 bin[1]设置为 unsorted bin 的 chunk 链表头。

漏洞触发

unsotred bin attack的触发条件与unlink类似。

堆在分配的时候,如果在申请的内存大小所对应的small bin或者large bin里面没有找到对应的chunk,此时会从unsorted bin里面去寻找chunk看是否存在合适的内存分配给用户,这个过程中会把unsorted bin链表给清空,
只要用户申请的不是fastbin大小的堆块都会把unsotred bin卸下来。
清空的过程简单说就是一个双向链表的unlink过程,但是该过程没有进行检查,由此可能会发生任意地址可写。
这个过程的源代码在int_malloc函数中

如果运行正常,最后的unsorted_chunks(av)同最简单的刚初始化的双向循环链表一样,fdbk都会指向自身。
容易发现,如果bck->fd可以被我们控制,这个时候我们就可以让它指向任意地址,最终使*bck->fd+0x10的值被修改成unsortedbin_chunks(av)&(main_arena+0x58),从而实现任意地址写固定值。

上述过程的源代码在malloc.c中

需要注意,为了跳出while ((victim = unsorted_chunks (av)->bk) != unsorted_chunks (av))循环,我们malloc的分配的chunk大小需要与unsoredbin的大小相一致,否则在反向遍历bins时,可能Segment fault,这是因为我们事先修改了unsorted bin的fd指针,遍历时检查会出错。

漏洞利用

虽然unsorted bin的触发条件比较容易,相对于unlink来说,该位置缺乏保护,这与unsortedbin attack的漏洞的实际威力是有关系的。
unsortedbin attack可以造成任意地址写,写的地址我们可以构造,但是写的值不可控。

永远都是unsorted_chunks (av),也就是bins[1]的地址main_arena+0x58(后记中会解释)。

所以在漏洞利用时,unsotred bin往往担任的是攻击的前奏,它能够将某个地址的值改成一个比较"大"的值,这就是unsotred bin的利用价值,可以修改globel max fast_IO_file_list等全局变量。

shellfish unsorted bin attack

shellfish unsorted bin attack

Unsorted bin Attack

程序中首先申请了两个chunk,第二个chunk为了防止在free时第一个chunk与Top chunk合并

之后修改unsorted bin的BK指针p[1]=(unsigned long)(&stack_var-2);

这样, bck->fd = unsorted_chunks (av);
使得*(stack_var-0x10+0x10)=unsorted_chunks (av)
从而实现了unsortedbin任意写功能
在第二次malloc后,清空unsorted bin的内容后main_arena的内容

可见unsorted_chunks(av)->bk = bck;将malloc_arnea的值写成了栈上的地址,同样栈中的地址也被写成了main_arena的值
运行结果:

后记

Bins对齐问题

调试时没有注意,之后突然发现了这个问题:
Unsorted Bin链表头是Bin[1],正常情况下free的unsorted bin的fd与bk的值应当是
&main_arena+0x68,但实际上fd与bk的值是main_arena+0x58

同样所有的Bins的链表都向前偏移了0x10….

bin_at宏

正常来看,双向循环链表不应该是这样的,于是我翻阅了malloc.c的源代码,发现

注意红框部分,为了便于对Bins这个双向循环链表的指针list进行管理,我们将每一对bin指针(fd,bk)看做malloc_chunk中的fd,bk来进行管理。
即Bins[1]相当于将其视为:

所以其fd与bk指向chunk的头部,即&fd-0x10的位置。
其他的bin[i]同理,这样就解释了为什么所有的bins双向链表头结点的都会向前偏移0x10了
在取bin的值是,采用的bin_at

将偏移0x10减去,利用bin_at宏消除了偏移问题。

发表评论