CodeVinci Beginner CTF 2025

比赛地址:CodeVinciCTF

比赛时间:29 Mar 2025 21:00 CST - 30 Mar 2025 21:00 CST

复现的题目用🔁标注

Intro

Sanity Check

Challenge

Sanity Check

misc

I’m in a hurry, I’ll leave you the message in the attachments…

1
‌‌‌‌‍‌‌‌‌‌‌‍‬Welcome‌‌‌‌‍‬‍‌‌‌‌‌‍‬‍‍‌‌‌‌‍‍‍‬‌‌‌‌‍‬‬‍‌‌‌‌‍‬‬‌‌‌‌‍‬‌ ‌‌‌‌‍‬‬‍to‌‌‌‌‍‌‌‌‌‌‌‍‍‍‌ CodeVinci‌‌‌‌‍‌‍‬ ‌‌‌‌‍‬Beginner‌‌‌‌‍‬‍‬‌‌‌‌‍‬‌‌‌‌‌‍‬‌‍‌‌‌‌‍‬‍ ‌‌‌‌‍‍‌‌‌‌‍‬‬‍‌‌‌‌‍‌‌‌‌‌‍‍CTF‌‌‌‌‍‬‬‌ ‌‌‌‌‍‬‍‍‌‌‌‌‍‌‬‌‌‌‌‍‬‍‍‌‌‌‌‍‍2025. ‌‌‌‌‍‬‍‬‌‌‌‌‍‬‌‌‌‌‍‌‬The‌‌‌‌‍‍‌‌‌‌‍‌‬‌‌‌‌‍‬‍‍ ‌‌‌‌‍‬‌‍flag‌‌‌‌‍‬‌ ‌‌‌‌‍‍is‌‌‌‌‍‬‬‌‌‌‌‌‬‌‌‌‌‌‍‌‍‌‌‌‌‌‌‬ ‌‌‌‌‍‬‬‌‌‌‌‍‍here.

Solution

零宽字符解密

1
CodeVinciCTF{flag_is_here_for_real_z8q2k}

parma

Challenge

parma

some infos about benjamin’s city

parma.html

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Obscured Flag - History of Parma</title>
<style>
body {
font-family: 'Times New Roman', serif;
background-color: #f4e1c1;
color: #5a3e1b;
margin: 40px;
text-align: center;
}
.container {
max-width: 800px;
margin: auto;
background: #fff;
padding: 20px;
border-radius: 10px;
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);
}
h1 {
font-size: 32px;
color: #7a4828;
}
p {
font-size: 18px;
line-height: 1.6;
}
.obscured {
color: black;
background-color: black;
user-select: none;
}
.flag-container {
margin-top: 20px;
font-size: 24px;
font-weight: bold;
background: #ddd;
padding: 10px;
border-radius: 5px;
display: inline-block;
}
</style>
</head>
<body>
<div class="container">
<h1>The History of Parma</h1>
<p>
Parma, one of the oldest cities in Italy, has a history dating back to Roman times.
Founded in 183 BC, it became an important economic and cultural center of Northern Italy.
During the Renaissance, under the rule of the Farnese family, the city flourished artistically and politically.
Even today, Parma is renowned for its culture, architecture, and gastronomy,
being the home of the famous Prosciutto di Parma and Parmigiano Reggiano.
</p>
<div class="flag-container">
<span class="obscured">C</span>
<span class="obscured">o</span>
<span class="obscured">d</span>
<span class="obscured">e</span>
<span class="obscured">V</span>
<span class="obscured">i</span>
<span class="obscured">n</span>
<span class="obscured">c</span>
<span class="obscured">i</span>
<span class="obscured">C</span>
<span class="obscured">T</span>
<span class="obscured">F</span>
<span class="obscured">{</span>
<span class="obscured">P</span>
<span class="obscured">a</span>
<span class="obscured">r</span>
<span class="obscured">m</span>
<span class="obscured">a</span>
<span class="obscured">_</span>
<span class="obscured">i</span>
<span class="obscured">s</span>
<span class="obscured">_</span>
<span class="obscured">t</span>
<span class="obscured">h</span>
<span class="obscured">e</span>
<span class="obscured">_</span>
<span class="obscured">l</span>
<span class="obscured">a</span>
<span class="obscured">s</span>
<span class="obscured">t</span>
<span class="obscured">_</span>
<span class="obscured">i</span>
<span class="obscured">n</span>
<span class="obscured">t</span>
<span class="obscured">r</span>
<span class="obscured">o</span>
<span class="obscured">}</span>
</div>
</div>
</body>
</html>


Solution

写个脚本提取一下就好了

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
# 假设数据存储在一个列表中,每行是一个字符串
lines = """ <span class="obscured">C</span>
<span class="obscured">o</span>
<span class="obscured">d</span>
<span class="obscured">e</span>
<span class="obscured">V</span>
<span class="obscured">i</span>
<span class="obscured">n</span>
<span class="obscured">c</span>
<span class="obscured">i</span>
<span class="obscured">C</span>
<span class="obscured">T</span>
<span class="obscured">F</span>
<span class="obscured">{</span>
<span class="obscured">P</span>
<span class="obscured">a</span>
<span class="obscured">r</span>
<span class="obscured">m</span>
<span class="obscured">a</span>
<span class="obscured">_</span>
<span class="obscured">i</span>
<span class="obscured">s</span>
<span class="obscured">_</span>
<span class="obscured">t</span>
<span class="obscured">h</span>
<span class="obscured">e</span>
<span class="obscured">_</span>
<span class="obscured">l</span>
<span class="obscured">a</span>
<span class="obscured">s</span>
<span class="obscured">t</span>
<span class="obscured">_</span>
<span class="obscured">i</span>
<span class="obscured">n</span>
<span class="obscured">t</span>
<span class="obscured">r</span>
<span class="obscured">o</span>
<span class="obscured">}</span>"""

flag = ''.join([line[len(' <span class="obscured">')] for line in lines.split("\n")])
print(flag)

Misc

Insanity Check

Challenge

Human Verification

You have to verify yourself by completing this easy function:

1
2
def sumlist(l: list) -> int:
[your_input]

I will send a random list to this function and check the result!

Solution

只能用一句话,要尽可能简短,不能引入库,不能使用 sum()

写一个单行循环就好了

1
2
def sumlist(l: list) -> int:
t=0;[t:=t+x for x in l];return t

CodeVinciBeginnerCTF2025-1

1
CodeVinciCTF{y0uv3_b3en_v3rif1ed!!}

FlagGyatter

Challenge

FlagGyatter

On skibidi Ohio NPC rizz you really think you can solve this? If you do you’re officially cooked and need to say goodbye to your rizz. Your only hope? Touching some grass before the irreversible damage sets in.

Author: @xairae

1
nc codevincictf.itis.pr.it 9967

chall.gyat

1
2
3
4
5
6
7
8
9
10
11
12
13
14
glaze signal, base64; from secret glaze FLAG; 
yap("""
,------.,--. ,----. ,--. ,--.
| .---'| | ,--,--. ,---. ' .-./pics/CodeVinciBeginnerCTF2025/ ,--. ,--.,--,--.,-' '-.,-' '-. ,---. ,--.--.
| `--, | |' ,-. || .-. | | | .---.\ ' /' ,-. |'-. .-''-. .-'| .-. :| .--'
| |` | |\ '-' |' '-' ' ' '--' | \ ' \ '-' | | | | | \ --.| |
`--' `--' `--`--'.`- / `------'.-' / `--`--' `--' `--' `----'`--'
`---' `---'

-----------------------------------------------------------------------

Bro really thinks he can try solving this :skull:
Remember: try not to hit by the great meme depression of 2025.""")
chat is this real __name__ == "__main__": signal.alarm(300); yap("Yah, you'd win " + FLAG) chat is this real(len(base64.b85encode(input("Rizz me up: ").encode()).hex()) == len(base64.b64encode("According to all known laws of aviation, there is no way a bee should be able to fly. Its wings are too small to get its fat little body off the ground. The bee, of course, flies anyway because bees don't care what humans think is impossible. Yellow, black. Yellow, black. Yellow, black. Yellow, black. Ooh, black and yellow! Let's shake it up a little. Barry! Breakfast is ready! Coming! Hang on a second. Hello? - Barry? - Adam? - Can you believe this is happening? - I can't. I'll pick you up. Looking sharp. Use the stairs. Your father paid good money mewing those. Sorry. I'm excited. Here's the graduate. We're very proud of you, son. A perfect report card, all B's. Very proud. Ma! I got a thing going here. - You got lint on your fuzz. - Ow! That's me! - Wave to us! We'll be diddy row 118,000. - Bye!".encode()).hex())) only in ohio yap("Bro thinks he can get me to spill the flag, get your unemployed ahhh out of here.")

Solution

在网上搜了一下 gyat 发现了这个项目 shamith09/pygyat

主要就是把 Python 的一些关键字映射转化成另一个词,并且这个过程是可逆的

在这个项目的官网找到了这个 PyPI 包 pygyat · PyPI

1
pip install pygyat

安装下来之后用 pygyat -h 查看到有下面的功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
┌──(kali㉿kali)-[~/桌面]
└─$ pygyat -h
usage: pygyat [-h] [-V] [-v] [-c] [-k] [-2] [-o OUTPUT] input ...

PyGyat is a python preprosessor that translates braces into indentation

positional arguments:
input pygyat files to process
args arguments to script

options:
-h, --help show this help message and exit
-V, --version show program's version number and exit
-v, --verbose print progress
-c, --compile translate to python only (don't run files)
-k, --keep keep generated python files
-2, --python2 use python2 instead of python3 (default)
-o OUTPUT, --output OUTPUT
specify name of output file (if -c is present)

可以看到 -c 方法可以把它还原成 Python 代码

1
pygyat -c chall.gyat

得到的代码经过格式化后如下

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
import signal, base64
from secret import FLAG

# 打印 ASCII 艺术标题和提示信息
print("""
,------.,--. ,----. ,--. ,--.
| .---'| | ,--,--. ,---. ' .-./pics/CodeVinciBeginnerCTF2025/ ,--. ,--.,--,--.,-' '-.,-' '-. ,---. ,--.--.
| `--, | |' ,-. || .-. | | | .---.\ ' /' ,-. |'-. .-''-. .-'| .-. :| .--'
| |` | |\ '-' |' '-' ' ' '--' | \ ' \ '-' | | | | | \ --.| |
`--' `--' `--`--'.`- / `------'.-' / `--`--' `--' `--' `----'`--'
`---' `---'

-----------------------------------------------------------------------

Bro really thinks he can try solving this :skull:
Remember: try not to hit by the great meme depression of 2025.
""")

# 主程序入口
if __name__ == "__main__":
# 设置超时时间为 300 秒(5 分钟)
signal.alarm(300)

# 提示用户输入,并对输入进行编码
user_input = input("Rizz me up: ")
encoded_user_input = base64.b85encode(user_input.encode()).hex()

# 定义固定的字符串并对其进行编码
fixed_string = (
"According to all known laws of aviation, there is no way a bee should be "
"able to fly. Its wings are too small to get its fat little body off the ground. "
"The bee, of course, flies anyway because bees don't care what humans think is "
"impossible. Yellow, black. Yellow, black. Yellow, black. Yellow, black. Ooh, "
"black and yellow! Let's shake it up a little. Barry! Breakfast is ready! Coming! "
"Hang on a second. Hello? - Barry? - Adam? - Can you believe this is happening? "
"- I can't. I'll pick you up. Looking sharp. Use the stairs. Your father paid "
"good money for those. Sorry. I'm excited. Here's the graduate. We're very proud "
"of you, son. A perfect report card, all B's. Very proud. Ma! I got a thing going "
"here. - You got lint on your fuzz. - Ow! That's me! - Wave to us! We'll be in "
"row 118,000. - Bye!"
)
encoded_fixed_string = base64.b64encode(fixed_string.encode()).hex()

# 比较两个编码后的字符串长度
if len(encoded_user_input) == len(encoded_fixed_string):
print("Yah, you'd win " + FLAG)
else:
print(
"Bro thinks he can get me to spill the flag, "
"get your unemployed ahhh out of here."
)

这里将用户的输入经过 Base85 转 16 进制,将题目的字符串经过 Base64 转 16 进制,然后把这两者的长度进行对比,如果相同就输出 flag

构造出来的输入如下

1
11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
1
CodeVinciCTF{my_br41n_1snt_r0tt3n_3nough_f0r_th1s_}

🕵️‍♂️Undetectable Data Phantom🕵️‍♂️

Challenge

🕵️‍♂️Undetectable Data Phantom🕵️‍♂️

medium

I found a new way to share secrets data, they are undetectable!

Author: @benjamin

Undetectable_Data_Phantom

Solution

附件是一个 ELF 文件

用 IDA 打开后发现这是一个用 Pyinstaller 打包的应用

CodeVinciBeginnerCTF2025-2

先用 pyinstxtractor 解包

1
python pyinstxtractor.py Undetectable_Data_Phantom

然后用 pycdc 逆向得到的 main.pyc

1
pycdc main.pyc > main.py

得到代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# Source Generated with Decompyle++
# File: main.pyc (Python 3.12)

import socket
import time
ENCODED_FLAG = b"\x02+%!\x17-/'(\x07\x15\x02:+\x0c#\x1e1\x1ep3w\x1e%\x0f\x1b\x14%\x14\x1e\t q5w39"
KEY = b'ADADADADADADADADADADADADADA'
TARGET_IP = '127.0.0.1'
TARGET_PORT = 4444

def xor_crypt(data, key):
''' Esegue XOR tra i byte dei dati e la chiave '''
pass
# WARNING: Decompyle incomplete


def send_udp_packet():
pass
# WARNING: Decompyle incomplete

if __name__ == '__main__':
send_udp_packet()
return None

接下来只要解开这个 XOR 加密就能拿到 flag 了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def xor_decrypt(ciphertext_hex, key_hex):
ciphertext_bytes = bytes.fromhex(ciphertext_hex)
key_bytes = bytes.fromhex(key_hex)

decrypted_bytes = bytes([c ^ key_bytes[i % len(key_bytes)] for i, c in enumerate(ciphertext_bytes)])

try:
return decrypted_bytes.decode('utf-8')
except UnicodeDecodeError:
return decrypted_bytes.hex()

ENCODED_FLAG = b"\x02+%!\x17-/'(\x07\x15\x02:+\x0c#\x1e1\x1ep3w\x1e%\x0f\x1b\x14%\x14\x1e\t q5w39".hex()
KEY = b'ADADADADADADADADADADADADADA'.hex()

# 示例
if __name__ == "__main__":
print(xor_decrypt(ENCODED_FLAG, KEY))
1
CodeVinciCTF{oMg_u_4r3_aN_UdP_Ma5t3r}

Binary

🔐🛡️Password Manager🛡️🔐

Challenge

🔐🛡️Password Manager🛡️🔐

easy

upx! I forgot to write the description.

Author: @benjamin

passwordManager

Solution

先用 upx 脱壳

1
upx -d passwordManager

然后用 IDA 打开

CodeVinciBeginnerCTF2025-3

发现这行代码,拼好就是 flag 了

1
CodeVinciCTF{d0n7_u5e_UpX_FoR_r3m0v3_1nFoS_}

Compiled Rome

Challenge

Compiled Rome

Rome has been compiled please help us reconquer it!

Check if there is any data inside that could endanger our enemies

RomaCompilata

Solution

刚用 IDA 打开就看到 flag 了

CodeVinciBeginnerCTF2025-4

1
PbqrIvapvPGS{I3av_ivQ1_P0zc1y1}

CodeVinciBeginnerCTF2025-5

直接 Rot13 解码拿到 flag

1
CodeVinciCTF{V3ni_viD1_C0mp1l1}