0x01 unsorted bin
基本来源
- 当一个较大的 chunk 被分割成两半后,如果剩下的部分大于 MINSIZE,就会被放到 unsorted bin 中。
- 释放一个不属于 fast bin 的 chunk,并且该 chunk 不和 top chunk 紧邻时,该 chunk 会被首先放到 unsorted bin 中。
- 当进行 malloc_consolidate 时,可能会把合并后的 chunk 放到 unsorted bin 中,如果不是和 top chunk 近邻的话。
基本使用情况
- Unsorted Bin 在使用的过程中,采用的遍历顺序是 FIFO,即插入的时候插入到 unsorted bin 的头部,取出的时候从链表尾获取。
- 在程序 malloc 时,如果在 fastbin,small bin 中找不到对应大小的 chunk,就会尝试从 Unsorted Bin 中寻找 chunk。如果取出来的 chunk 大小刚好满足,就会直接返回给用户,否则就会把这些 chunk 分别插入到对应的 bin 中。
0x02 unsorted bin attack原理
源码在glibc2.23 /malloc/malloc.c:3515中,当将一个 unsorted bin 取出的时候,会将 bck->fd 的位置写入本 Unsorted Bin 的位置。如果能控制bk的值,就能能将unsorted_chunks(av)写入到任意地址。将某个位置写入一个大数。
/* remove from unsorted list */
unsorted_chunks (av)->bk = bck;
bck->fd = unsorted_chunks (av);
如果将chunk1的bk覆盖为G_ptr-0x10,当chunk1被取下的时候
- *G_ptr将会被重新赋值为chunk1->fd
- main_arena_unsortedbin->bk=&G_ptr-0x10
简单示例
程序是在ubuntu1604的系统中编译(没有tcache)。
- 申请0x80,0x10(防止和topchunk合并)两个堆块
- 释放0x80的堆块进入unsorted bin
- 修改bk为&ptr-0x10
- 重新申请0x80大小的堆块
- 此时ptr的内容已经被修改了
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
char *ptr1=NULL,*ptr2,*ptr3;
ptr2 = malloc(0x80);
malloc(0x10);
free(ptr2);
((void**)ptr2)[1]=&ptr1-2;
fprintf(stderr,"ptr1:%p\n",ptr1);
malloc(0x80);
fprintf(stderr,"ptr1:%p\n",ptr1);
return 0;
}
0x03 总结
利用流程
- Unsorted Bin Attack
利用 unsorted bin attack ,修改 global_max_fast 全局变量,由于 global_max_fast 变量为控制最大的 Fast chunk 的大小,将这里改写为 unsorted bin 的地址 (一般来说是一个很大的正数),就能使之后的 chunk 都被当作 fast chunk,即可进行 Fast bin attack。 - Fast Bin Attack