0%

Ptmalloc算法:Unsortedbin Attack

Ptmalloc算法:Unsortedbin Attack

Unsortedbin Attack,也是堆中较为常见的利用手段,可以用来 泄露地址WAA

概念:利用ptmalloc算法中,Unsortedbin的机制进行攻击


Unsorted Chunk

Unsorted Chunk就是暂时没有被程序处理的chunk

来源:

  • 当一个较大的chunk被分割成两半后,剩下的部分大于MINSIZE
  • 释放一个不属于fastbin的chunk,并且该chunk不和top chunk紧邻
  • 当进行malloc_consolidate时,合并后的chunk会优先成为Unsorted Chunk(不与top chunk相邻)

这些Unsorted Chunk会以双向链表的形式构成Unsorted Bin

Unsorted Bin

Unsorted Bin就是专门用于管理Unsorted Chunk的数据结构,可以存储不同大小的chunk,有且只有一条

使用:

  • 采用的遍历顺序是FIFO:先被释放的chunk,将会优先被申请( 先进先出队列)
  • 在程序 malloc 时,如果在 fastbin,small bin 中找不到对应大小的 chunk,就会尝试从 Unsorted Bin 中寻找 chunk,如果取出来的 chunk 大小刚好满足,就会直接返回给用户,否则就会把这些 chunk 分别插入到对应的 bin 中

Unsorted Bin Leak

原理:

低libc版本的Unsorted Bin有一个特点:

  • 第一个chunk的BK指针:指向“main_arena+xx”
  • 最后一个chunk的FD指针:指向“main_arena+xx”

而“main_arena+xx”距离“libc_base”的偏移是固定的,所以可以通过泄露“main_arena+xx”来计算“libc_base”

案例:

利用:

如果程序拥有“打印模块”和UAF漏洞,则可以直接打印该地址

除此之外,很难泄露“main_arena+xx”

Unsorted Bin Attack

原理:

当将一个 unsorted bin 取出的时候,会将 bck->fd 的位置写入本 Unsorted Chunk 的位置

1
2
3
4
5
/* remove from unsorted list */
if (__glibc_unlikely (bck->fd != victim))
malloc_printerr ("malloc(): corrupted unsorted chunks 3");
unsorted_chunks (av)->bk = bck;
bck->fd = unsorted_chunks (av);

换而言之,如果我们控制了 bk 的值,我们就能将 unsorted_chunks (av) 写到任意地址

  • unsorted bin 也是以链表的方式进行组织的,和 fast bin 不同的是其分配方式是FIFO,即一个chunk放入unsorted bin链时将该堆块插入链表头,而从这个链取堆块的时候是从尾部开始的,因此unsorted bin遍历堆块的时候使用的是bk指针

通常 Unsorted Bin Attack 就是为了 Fastbin Attack 提供“\x7f”的

案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>
#include <malloc.h>
#include <unistd.h>
#include <string.h>
int main()
{
int size=0x100;
char *p=malloc(size);
printf("%p\n",p); /* sleep函数为程序打断点使用,无其他作用 */
free(p);
sleep(0); //第一步

*(long*)(p+8)=0x601100; //0x601100是我们的攻击目标
sleep(0); //第二步

char *r=malloc(size);
printf("%p\n",r);
sleep(0); //第三步

return 0;
}

第一步:

chunkP是 Unsortedbin 中唯一的chunk

第二步:

chunkP的BK指针被改为“0x601100”

第三步:

chunkP被申请后,Unsortedbin 中没有chunk了,但是“0x601100”中被写入“main_arena+xx”

如果“0x601110-0x3”是我们的攻击目标的话,那么“0x601110-0x3”的指定偏移用于表示size的地址处就被我们写入了0x7f的数值

版本对Unsorted Bin Attack的影响

glibc2.23

1
2
3
4
5
6
7
8
9
10
11
12
13
14
for (;;)
{
int iters = 0;
while ((victim = unsorted_chunks (av)->bk) != unsorted_chunks (av))
{
bck = victim->bk;
if (__builtin_expect (victim->size <= 2 * SIZE_SZ, 0)
|| __builtin_expect (victim->size > av->system_mem, 0))
malloc_printerr (check_action, "malloc(): memory corruption",
chunk2mem (victim), av);
/* remove from unsorted list */
unsorted_chunks (av)->bk = bck;
bck->fd = unsorted_chunks (av);
}

只检查了“victim->size”,形同虚设,可以直接打Unsorted Bin Attack

glibc2.29

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
for (;;)
{
int iters = 0;
while ((victim = unsorted_chunks (av)->bk) != unsorted_chunks (av))
{
bck = victim->bk;
size = chunksize (victim);
mchunkptr next = chunk_at_offset (victim, size);

if (__glibc_unlikely (size <= 2 * SIZE_SZ)
|| __glibc_unlikely (size > av->system_mem))
malloc_printerr ("malloc(): invalid size (unsorted)");
if (__glibc_unlikely (chunksize_nomask (next) < 2 * SIZE_SZ)
|| __glibc_unlikely (chunksize_nomask (next) > av->system_mem))
malloc_printerr ("malloc(): invalid next size (unsorted)");
if (__glibc_unlikely ((prev_size (next) & ~(SIZE_BITS)) != size))
malloc_printerr ("malloc(): mismatching next->prev_size (unsorted)");
if (__glibc_unlikely (bck->fd != victim)
|| __glibc_unlikely (victim->fd != unsorted_chunks (av)))
malloc_printerr ("malloc(): unsorted double linked list corrupted");
if (__glibc_unlikely (prev_inuse (next)))
malloc_printerr ("malloc(): invalid next->prev_inuse (unsorted)");
unsorted_chunks (av)->bk = bck;
bck->fd = unsorted_chunks (av);
}

直接把“victim的全家”都给检查了,基本上不能打Unsorted Bin Attack

其实也有办法打Unsorted Bin Attack,以后遇到再说