【Pwn 笔记】堆利用总结--空闲块篇

自己的一点小总结,会一直改进

制造伪造堆块时利用 top_chunk

1.释放的堆块都被top chunk合并

再新建一个比原先chunk小的chunk后,会生成两个top_chunk的size位

可用于绕过 double free

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
0xc3f470 PREV_INUSE {
prev_size = 0x0,
size = 0x421,
fd = 0x0,
bk = 0x201,
fd_nextsize = 0x6020e8,
bk_nextsize = 0x6020f0,
}
0xc3f890 PREV_INUSE {
prev_size = 0x0,
size = 0x20771,
fd = 0x0,
bk = 0x0,
fd_nextsize = 0x0,
bk_nextsize = 0x0,
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
0x6d2470 PREV_INUSE {
prev_size = 0x0,
size = 0x411,
fd = 0x0,
bk = 0x201,
fd_nextsize = 0x6020e8,
bk_nextsize = 0x6020f0,
}
0x6d2880 PREV_INUSE {
prev_size = 0x0,
size = 0x20781,
fd = 0x0,
bk = 0x20771,
fd_nextsize = 0x0,
bk_nextsize = 0x0,
}

在一个大的空闲块上用 free 释放掉内部一个原有的堆块时

1. 原有堆块 fd 上的数值会全部被设置成’\x00’

1
2
3
4
5
6
7
8
9
10
释放前:

0x5651c9c8bee0: 0x0000000000000000 0x0000000000000081
0x5651c9c8bef0: 0x6262626262626262 0x0000000000000000
0x5651c9c8bf00: 0x0000000000000000 0x0000000000000000
0x5651c9c8bf10: 0x0000000000000000 0x0000000000000000
0x5651c9c8bf20: 0x0000000000000000 0x0000000000000000
0x5651c9c8bf30: 0x0000000000000000 0x0000000000000000
0x5651c9c8bf40: 0x0000000000000000 0x0000000000000000
0x5651c9c8bf50: 0x0000000000000000 0x0000000000000000
1
2
3
4
5
6
7
8
9
10
释放后:

0x5651c9c8bee0: 0x0000000000000000 0x0000000000000081
0x5651c9c8bef0: 0x0000000000000000 0x0000000000000000
0x5651c9c8bf00: 0x0000000000000000 0x0000000000000000
0x5651c9c8bf10: 0x0000000000000000 0x0000000000000000
0x5651c9c8bf20: 0x0000000000000000 0x0000000000000000
0x5651c9c8bf30: 0x0000000000000000 0x0000000000000000
0x5651c9c8bf40: 0x0000000000000000 0x0000000000000000
0x5651c9c8bf50: 0x0000000000000000 0x0000000000000000

在一个大的空闲块上用 malloc 申请一个小堆块时

1. 旧堆块会在它起始的地址处割出一块空间来存放新堆块

且旧堆块的 size 位会减少相应的数值

1
2
3
4
5
6
7
8
9
10
旧空闲堆块:

0x556631cade60: 0x0000000000000000 0x0000000000000481
0x556631cade70: 0x00007fb1a6bb0ca0 0x00007fb1a6bb0ca0
0x556631cade80: 0x0000000000000000 0x0000000000000000
0x556631cade90: 0x6161616161616161 0x6161616161616161
0x556631cadea0: 0x6161616161616161 0x6161616161616161
0x556631cadeb0: 0x6161616161616161 0x6161616161616161
0x556631cadec0: 0x6161616161616161 0x6161616161616161
0x556631caded0: 0x6161616161616161 0x6161616161616161
1
2
3
4
5
6
7
8
9
10
11
生成新堆块,申请大小为 0x10,总大小为 0x20
这时新堆块的初始地址会存放在旧地址的 prev_size 位

0x556631cade60: 0x0000000000000000 0x0000000000000021
0x556631cade70: 0x6565656565656565 0x00007fb1a6bb10b0
0x556631cade80: 0x0000556631cade60 0x0000000000000461
0x556631cade90: 0x00007fb1a6bb0ca0 0x00007fb1a6bb0ca0
0x556631cadea0: 0x0000000000000000 0x0000000000000000
0x556631cadeb0: 0x6161616161616161 0x6161616161616161
0x556631cadec0: 0x6161616161616161 0x6161616161616161
0x556631caded0: 0x6161616161616161 0x6161616161616161

这样如果原先在0x556631cade80处是已经释放掉的某堆块
那么这一操作可以让此处释放掉的堆块的 fd 指向旧空闲堆块的fd
这样下次分配的fastbin或者tcachebin就会被分配到 fd 指向的地址
靠着这个特性可以用fastbin或者tcachebin实现一些地址劫持

2.如果 unsorted bin 在这次分配之后,下次不能分配最小的 fastbin 时

这种情况下也就是说在64位下,在 unsorted bin chunk 中还剩余0x100x08大小的地址时

或者是在32位下,在 unsorted bin chunk 中还剩余0x080x04大小的地址时

这时候被分配的 fastbin chunk 的 size 位等于上次分配 chunk 时,unsorted bin 剩下的大小

也等于当前 fastbin chunk 的大小加上剩余空间的大小

那么在 free 的时候,会把当前的 fastbin chunk 连同剩下的空间一并释放到当前 size 对应的 bin 中

内存演示(32位)

1
2
3
4
5
6
7
8
9
申请最后一块符合的 fastbin chunk 之前

0x859c080: 0x7f7f7f7f 0x00000019 0xf7f317b0 0xf7f317b0
0x859c090: 0x7f7f7f7f 0x000a7f7f 0x00000018 0x00000010

此处 0x859c090 到 0x859c097 为之前的 unsorted bin 剩余的内存,大小为 0x08

0x859c0a0: 0x080486be 0x080486fe 0x00000000 0x00020f59
0x859c0b0: 0x00000000 0x00000000 0x00000000 0x00000000
1
2
3
4
5
6
7
8
9
申请一个大小为 0x08 的 fastbin chunk,总大小应为 0x11

0x859c080: 0x7f7f7f7f 0x00000019 0x080486be 0x080486fe

可以看到 0x859c087 上面的数值还是 0x19

0x859c090: 0x7f7f7f7f 0x000a7f7f 0x00000018 0x00000011
0x859c0a0: 0x080486be 0x080486fe 0x00000000 0x00020f59
0x859c0b0: 0x00000000 0x00000000 0x00000000 0x00000000
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
释放掉该 fastbin chunk
申请大小为 0x08 的 chunk 却进入到了 0x18 的 fastbin 链表中

pwndbg> x/16wx 0x859c080
0x859c080: 0x7f7f7f7f 0x00000019 0x00000000 0x080486fe
0x859c090: 0x7f7f7f7f 0x000a7f7f 0x00000018 0x00000011
0x859c0a0: 0x080486be 0x080486fe 0x00000000 0x00020f59
0x859c0b0: 0x00000000 0x00000000 0x00000000 0x00000000
pwndbg> bin
fastbins
0x10: 0x0
0x18: 0x859c080 ◂— 0x0
0x20: 0x0
0x28: 0x0
0x30: 0x0
0x38: 0x0
0x40: 0x0
unsortedbin
all: 0x0
smallbins
empty
largebins
empty

这种特性使得我们可以在一些一次性创造两个堆块且有UAF漏洞的题目中
起到改变堆块位置从而改变原有函数执行代码的特性

文章目录
  1. 1. 制造伪造堆块时利用 top_chunk
  2. 2. 在一个大的空闲块上用 free 释放掉内部一个原有的堆块时
  3. 3. 在一个大的空闲块上用 malloc 申请一个小堆块时
    1. 3.1. 1. 旧堆块会在它起始的地址处割出一块空间来存放新堆块
    2. 3.2. 2.如果 unsorted bin 在这次分配之后,下次不能分配最小的 fastbin 时
|