重庆工商大学校赛个人WP

MISC

666和999的故事

将9替换成@得到一张二维码

扫描后得到flag

ctbuctf{The_Misc_Begins_Here_a00df5}

Do you know SSTV?

听到这个声音就猜到是声音转图片,之前跟一个玩无线电的朋友玩过这个

不过手机上很容易受到杂音的干扰,看不请上面的字

电脑上用虚拟声卡播放看得很清楚

ctbuctf{N0thing_1s_impossible}

Ez_Base64

一把梭

ctbuctf{Base64_1s_Fun_7e6b89}

Zip_Master

AI梭

用bandizip打不开,但是用7zip可以打开

ctbuctf{Wooowoow_Yooua_Zip_Masteeeer!!!!!}

【签到】Welcome to CTBUCTF2025

直接给的

ctbuctf{Welcome_to_CTBUCTF2025}

书读万遍其意自现

每次输入取一位secret,判断他加上key是否等于输入

ctbuctf{CAYLESsaNDdOMoRe}

Crypto

Caesar_Salad

vnwqzre{297jf36j-303p-4v4u-8v7a-cd190e694j54}

第一位位移19,第二位20…数字跳过(位移会加一)

ctbuctf{297fa36b-303c-4f4c-8a7d-dd190a694b54}

Prime_Alchemy

不会密码,AI梭

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
import uuid
from Crypto.Util.number import bytes_to_long, getRandomNBitInteger, isPrime as crypto_isPrime, long_to_bytes, inverse
from sympy import nextprime, isprime as sympy_isprime
import math

# 题目给定的值
n_val = 1453273352925249470095211806718117618912214179789181787238861765412223649923774033033160104903651377501015607116224705290716290896828401284504688550321192688861952057616123687734073757392758919574092921386421400358068577682683663691
e_val = 65537
c_val = 69821434810639898086705801843771679384936981536773881072202785776011214181282844938536297781999582346226156967398464463215845344993519293615963219614824678722311404183637250306235309075386059078019233706113533688380177630122904768
r_val = 71027232075164735205009199032831071477036566797258769709514666348775682672270

print("Step 1: Calculate nextprime(r)")
npr_val = nextprime(r_val)
print(f"r = {r_val}")
print(f"nextprime(r) = {npr_val}")

print("\nStep 2: Calculate q_approx")
denominator = npr_val + r_val
q_squared_approx = n_val // denominator
q_approx = math.isqrt(q_squared_approx)
print(f"q_approx = {q_approx}")
print(f"q_approx bit_length: {q_approx.bit_length()}")

print("\nStep 3: Search for the true q")
q_found = None
p_found = None

# 从 q_approx 开始向下搜索
# 通常 q 和 q_approx 非常接近,所以不需要搜索很大的范围
for i in range(2000): # 稍微增大搜索范围以确保找到,一般几十到几百内就能找到
q_candidate = q_approx - i
if q_candidate <= 1: # q 必须是大于1的素数
print(f"q_candidate became too small ({q_candidate}), stopping search.")
break

if i > 0 and i % 50 == 0: # 打印进度
print(f"Searching... tried {i} values from q_approx. Current q_candidate has {q_candidate.bit_length()} bits.")

# 检查 q_candidate 是否是素数 (使用 Crypto.Util.number.isPrime)
if not crypto_isPrime(q_candidate):
continue

# 检查 q_candidate 是否是 n 的因子
if n_val % q_candidate == 0:
p_candidate = n_val // q_candidate

# 计算 nextprime(q_candidate)
npq_candidate = nextprime(q_candidate) # sympy.nextprime

# 验证 p 的构造
p_check = q_candidate * npr_val + npq_candidate * r_val

if p_candidate == p_check:
# 最后验证 p_candidate 是否是素数
if crypto_isPrime(p_candidate): # Crypto.Util.number.isPrime
q_found = q_candidate
p_found = p_candidate
print(f"\nFound p and q after {i + 1} iterations from q_approx!")
print(f"q = {q_found} (bit_length: {q_found.bit_length()})")
print(f"p = {p_found} (bit_length: {p_found.bit_length()})")
break

if p_found is None or q_found is None:
print("Failed to find p and q with this search range.")
exit()

print("\nStep 4: Calculate phi")
phi = (p_found - 1) * (q_found - 1)
print(f"phi = {phi}")

print("\nStep 5: Calculate d (private exponent)")
d_val = inverse(e_val, phi)
print(f"d = {d_val}")

print("\nStep 6: Decrypt ciphertext c")
m_val = pow(c_val, d_val, n_val)
print(f"m_val (decrypted message as long) = {m_val}")

print("\nStep 7: Convert message to bytes and then to string")
# 估算字节长度,确保不会丢失数据
byte_len = (m_val.bit_length() + 7) // 8
flag_bytes = long_to_bytes(m_val, byte_len)
try:
flag_str = flag_bytes.decode('utf-8')
print(f"\nFlag: {flag_str}")
except UnicodeDecodeError:
print(f"\nCould not decode flag bytes to UTF-8. Raw bytes: {flag_bytes}")
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
Step 1: Calculate nextprime(r)
r = 71027232075164735205009199032831071477036566797258769709514666348775682672270
nextprime(r) = 71027232075164735205009199032831071477036566797258769709514666348775682672321

Step 2: Calculate q_approx
q_approx = 101145417666702901428629971949799084420404974663970101504809220600550818364156
q_approx bit_length: 256

Step 3: Search for the true q

Found p and q after 8 iterations from q_approx!
q = 101145417666702901428629971949799084420404974663970101504809220600550818364149 (bit_length: 256)
p = 14368158107904748381924430862275776814058794907286362788355652593016651552866866977879820582509398565068235908334390728100582465729030896202072334785636159 (bit_length: 513)

Step 4: Calculate phi
phi = 1453273352925249470095211806718117618912214179789181787238861765412223649923759664875052200155269453070153331339410646495809004534040045631911671898768325720738654570330712860539033571685340108441017674950590864652645904797079663384

Step 5: Calculate d (private exponent)
d = 610695456605602490294370098677341947676005592434717280628625860497926962157259886333810482510278479905275229947775595533737888290087475116389939180799848793035118282297142563425927103227402331300877775426694423188944691061714358753

Step 6: Decrypt ciphertext c
m_val (decrypted message as long) = 912396200799613787975790773606557340316526091833584643916779032146413804979399082199642618048151976064659837

Step 7: Convert message to bytes and then to string

Flag: ctbuctf{2772e794-84f0-47e0-a708-e07399ad4091}

ctbuctf{2772e794-84f0-47e0-a708-e07399ad4091}

撒豆成兵

依然是AI

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 已知参数
n = 20250427
e = 65537
ct = [12385674, 5936435, 14149074, 14788627, 12385674, 5936435, 1035132, 6977025, 4810471, 1719471, 1719471, 1753036, 1669202, 18035719, 14149074, 18035719, 11051005, 4810471, 10294460, 10660074, 10294460, 11051005, 10294460, 12385674, 12530148, 1753036, 11051005, 14149074, 19959794, 16564519, 19959794, 11051005, 6637936, 1753036, 6637936, 12530148, 1035132, 10660074, 1719471, 10660074, 9659730, 1035132, 10660074, 10294460, 15043166] # 完整密文见用户输入

# Step 1: 分解n (已通过计算得出)
p = 6287
q = 3221

# Step 2: 计算私钥d
phi = (p-1)*(q-1)
d = pow(e, -1, phi) # Python 3.8+的逆元计算语法

# Step 3: 解密密文
plaintext = []
for c in ct:
m = pow(c, d, n) # RSA解密核心计算
plaintext.append(m)

# Step 4: 转换为ASCII
flag_bytes = bytes([x for x in plaintext])
print("Flag:", flag_bytes.decode())
1
Flag: ctbuctf{1ee095b5-1434-4c80-b6a6-7078f3e3df34}

ctbuctf{1ee095b5-1434-4c80-b6a6-7078f3e3df34}

WEB

Welcome !!

发现点击破解没发送请求,猜测是纯前端实现的,复制源码丢给AI分析

ctbuctf{we1c0me_t0_CT9UC7F2025}

terminal

也是纯前端,丢给AI解密

flag{7h15_15_a_v3ry_g00d_5747}

Poem:Imprisoned XII

里面可以传cmd通过rot13后直接执行

UA里存在CRYCHIC才能访问通过

1
http://ctf.ctbu.edu.cn:33352/?cmd=flfgrz("png /synt.cuc");

ctbuctf{Saki-Chan-Saki-Chan-195405f77e92-Saki-Chan-Saki-Chan}

vite_dev👻

RUN npm install vite@6.2.1 -D --force

dockerfile里发现vite版本,搜索到CVE-2025-30208

http://ctf.ctbu.edu.cn:33356/proc/self/environ?import&raw??

查看当前进程的环境变量,得到flag

ctbuctf{g00d_272da8f0-4ffa-4ae4-aeb9-14a71a83da8c}

🎭 Mutsumi or Mortis?

刚好b站上刷到过这个漏洞,CVE-2025-29927

请求头中加入x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware

即可访问/admin

1
2
3
4
5
6
7
8
export function middleware(request) {
const isAdmin = request.cookies.get('isAdmin')?.value;


if (!isAdmin && request.nextUrl.pathname.startsWith('/admin')) {
return Response.redirect(new URL('/403', request.url));
}
}

根据源码,其实cookie设置了isAdmin就能访问/admin,一个小非预期

ctbuctf{42ec9f00-c582-405e-b576-99415116adcd-SOYO-LOVE}

terminal pro

about.md里提示是伪造jwt

想法是吧jwt里的alg设置为none,然后role设为admin

然后访问的时候报错了,没识别出alg的加密方式

不过报错中泄露了key(应该是非预期吧)

根据key生成jwt

得到flag

ctbuctf{21e30106-a458-4376-9ae2-dec498438a1e}

Sql_No_map…?

一开始以为是盲注,用盲注确实能行,但是FLAG字段会被扫描成flag,转成小写了,导致一直没获取到值

之后无意打开源码才发现给出了后端源码

用union联合注入就行了

http://ctf.ctbu.edu.cn:33359/?id=-1/**/UNION/**/SELECT/**/group_concat(k),group_concat(v)/**/FROM/**/FLAG--

得到flag
ctbuctf{39aec934-0c33-47d9-9892-fa3ff188f9e0_TIGER_DRAGON_[TEAM_HASH]}

SecureCorp Employee Portal

这题应该是web中最绕的了

1
2
3
4
5
6
7
8
9
10
11
12
@app.route('/admin', methods=['GET'])
def admin():
logger.info(f'Admin panel accessed - Token check: {X_Admin_Token}')
logger.debug(f'Cookies received: {request.cookies}')

if request.cookies.get('X-Admin-Token') != X_Admin_Token:
logger.warning(f'Unauthorized access attempt from {request.remote_addr}')
return 'Access denied: Invalid security credentials', 403

logger.info('Admin authentication successful')
prompt = request.args.get('prompt')
return render_template('admin.html', cmd=f"{prompt if prompt else 'prompt$/>'}{run_cmd()}".format(run_cmd))

/admin这个路径要有X_Admin_Token,访问不了,既然有防护肯定是要进这个页面的

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
def visit_report(url, X_Admin_Token):
options = Options()
options.add_argument('--headless')
options.set_preference("security.warn_submit_secure_to_insecure", False)
browser = webdriver.Firefox(options=options)

try:
print(f'[Bot] Initializing security verification')
browser.get('http://127.0.0.1:5000/')
cookie = {
'name':'X-Admin-Token',
'value': X_Admin_Token,
'secure': False,
'httpOnly': False,
'expiry': None
}
browser.add_cookie(cookie)
print(f'[Bot] Visiting target URL: {url}')
browser.get(url)
WebDriverWait(browser, 10).until(lambda r: r.execute_script('return document.readyState') == 'complete')
print(f'[Bot] Page loaded successfully')
except Exception as e:
print(f"[Bot] Error during verification: {e}")
finally:
browser.quit()
print(f'[Bot] Security verification completed')

bot访问页面时直接带上了X_Admin_Token

1
2
3
4
<div class="search-result">
<p>> Performing external lookup for employee: <span class="search-term">{{query|safe}}</span></p>
<p>> Searching external databases... <span class="blink">_</span></p>
</div>

而external-lookup页面中使用了{xx|safe},这不会将显示的内容转义

环环相扣,用report让AI访问external-lookup页面,query中将cookie发送到自己的服务器中

得到X_Admin_Token,然后带上访问admin

本以为就要结束了,没想到是新的开始

这页面还真不能执行命令,但是注意到admin返回的是

1
return render_template('admin.html', cmd=f"{prompt if prompt else 'prompt$/>'}{run_cmd()}".format(run_cmd))

所以可以让prompt为{0},这样prompt的内容就是run_cmd这个函数(其实我一开始想的是SSTI,有点像搞了半天)

得到这个函数后用__globals__查看有哪些变量,发现了有os,os中的environ可以看到程序的环境变量

读到flag

ctbuctf{55f629912ca2_V3ry_go0d_!55f629912ca2}

REVERSE

SignUp

base32解密得到flag

ctbuctf{W3lc0m3_t0_ctbuctf2025_3nj0y!}

PytheSnake

pyinstaller逆向,得到源码

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
#!/usr/bin/env python
# visit https://tool.lu/pyc/ for more information
# Version: Python 3.11

import pygame
import random
import sys
import time
import base64
pygame.init()
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
(WIDTH, HEIGHT) = (600, 400)
GRID_SIZE = 20
GRID_WIDTH = WIDTH // GRID_SIZE
GRID_HEIGHT = HEIGHT // GRID_SIZE
SNAKE_SPEED = 10
BASE_TABLE = '234567XYZABCDEFGHIJKLMNOPQRSTUVW'
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption('Snake - Need 555!')
clock = pygame.time.Clock()
score = 0
font = pygame.font.SysFont('arial', 20)

class Snake:

def __init__(self):
self.positions = [
(GRID_WIDTH // 2, GRID_HEIGHT // 2)]
self.direction = (1, 0)
self.length = 1
self.score = 0
self.color = GREEN


def get_head_position(self):
return self.positions[0]


def update(self):
head = self.get_head_position()
(x, y) = self.direction
new_head = ((head[0] + x) % GRID_WIDTH, (head[1] + y) % GRID_HEIGHT)
if new_head in self.positions[1:]:
return False
None.positions.insert(0, new_head)
if len(self.positions) > self.length:
self.positions.pop()
return True


def reset(self):
self.positions = [
(GRID_WIDTH // 2, GRID_HEIGHT // 2)]
self.direction = (1, 0)
self.length = 1
self.score = 0


def render(self, surface):
pass
# WARNING: Decompyle incomplete



class Food:

def __init__(self):
self.position = (0, 0)
self.color = RED
self.randomize_position()


def randomize_position(self):
self.position = (random.randint(0, GRID_WIDTH - 1), random.randint(0, GRID_HEIGHT - 1))


def render(self, surface):
rect = pygame.Rect((self.position[0] * GRID_SIZE, self.position[1] * GRID_SIZE), (GRID_SIZE, GRID_SIZE))
pygame.draw.rect(surface, self.color, rect)
pygame.draw.rect(surface, BLACK, rect, 1)



def decode_flag(encoded):
'''使用自定义字母表的标准Base32解码'''
custom_to_std = str.maketrans(BASE_TABLE, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567')
std_encoded = encoded.translate(custom_to_std)
padding = '=' * ((8 - len(std_encoded) % 8) % 8)
flag_bytes = base64.b32decode(std_encoded + padding)
return flag_bytes.decode('utf-8')
# WARNING: Decompyle incomplete


def draw_grid(surface):
pass
# WARNING: Decompyle incomplete


def show_game_over(surface):
font = pygame.font.SysFont('arial', 24)
text = font.render('You Died!Press R to restart', True, BLACK)
text_rect = text.get_rect(center = (WIDTH // 2, HEIGHT // 2))
surface.blit(text, text_rect)
pygame.display.update()


def show_flag(surface):
font = pygame.font.SysFont('arial', 24)
e_flag = 'DERX6UC5FIKYNMBWBAGKZORJXDR54ORHG7GKFR3KCTRNTE5CXEGLRE3MXTQO6ZBVCUGYR'
flag = decode_flag(e_flag)
text = font.render(f'''Flag: {flag}''', True, BLUE)
text_rect = text.get_rect(center = (WIDTH // 2, HEIGHT // 2 - 50))
surface.blit(text, text_rect)
pygame.display.update()


def main():
snake = Snake()
food = Food()
game_over = False
flag_shown = False
# WARNING: Decompyle incomplete

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

换表的base32,解密出flag

ctbuctf{U_R_4_R341_Py_7h3_5n4k3_M4573r!^_^}

SignUpx+÷-

根据题目,有个upx壳,脱壳后找到加密的部分丢给AI,得到一个解密脚本

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
encrypted = [
0x64, 0x72, 0x26, 0x1D, 0x68, 0x6E, 0xCA, 0x0F,
0x5B, 0x29, 0xB2, 0x04, 0x5F, 0x27, 0xFD, 0x05,
0x42, 0x23, 0x0D, 0x02, 0x49, 0x1F, 0xFF, 0x01,
0x5F, 0x3B, 0x3A, 0x03, 0x54, 0x12, 0x81, 0x02,
0x6D, 0x12, 0x2B, 0x00, 0xA2
]

def check_prefix(s):
"""
模拟 C++ 里对前 len(s) 个字符加密后,是否都与 encrypted 对应位置一致。
"""
n = len(s)
for i, ch in enumerate(s):
i1 = i + 1
v = ord(ch)
m = i1 % 4
if m == 1:
v = v + i1
elif m == 2:
v = v - i1
elif m == 3:
v = (v * i1) & 0xFF
else: # m == 0
v = v // i1
if v != encrypted[i]:
return False
return True

def gen_candidates(i):
"""
返回位置 i(0-based)上,所有可能的原字符列表。
"""
i1 = i + 1
e = encrypted[i]
m = i1 % 4
cands = []
# 限定在常见可打印 ASCII 范围
for c in range(0x20, 0x7F):
v = c
if m == 1:
v = v + i1
elif m == 2:
v = v - i1
elif m == 3:
v = (v * i1) & 0xFF
else: # m == 0
v = v // i1
if v == e:
cands.append(chr(c))
return cands

# 预先生成每个位置的候选字符列表
candidates = [gen_candidates(i) for i in range(len(encrypted))]

# 递归 DFS,带前缀剪枝
def dfs(pos, prefix):
if pos == len(encrypted):
return prefix # 找到完整解
for ch in candidates[pos]:
new_str = prefix + ch
# 仅当新前缀加密后与 encrypted 前缀匹配时,才继续深入
if check_prefix(new_str):
res = dfs(pos + 1, new_str)
if res:
return res
return None

if __name__ == "__main__":
flag = dfs(0, "")
print("Recovered flag:", flag)

但是运行后的结果是ctbtctfxR3V0R53P15_(45Y FUNT70_@L4Y },每隔4个就有一个错误

人肉修复

ctbuctf{R3V3R53_15_345Y&FUN_70_PL4Y!}

小学数学_v1

打开后很多等式,用python的z3太慢了,我让AI写了个c++的

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
#include <iostream>
#include <vector>
#include <string>
#include "z3++.h" // Z3 C++ header

int main() {
z3::context ctx;
z3::solver s(ctx);

// Declare 35 integer variables for the flag characters
z3::expr_vector flag_chars(ctx);
for (int i = 0; i < 35; ++i) {
// Create a unique name for each Z3 variable
std::string var_name = "flag_" + std::to_string(i);
flag_chars.push_back(ctx.int_const(var_name.c_str()));
}

// Add constraints: characters must be printable (e.g., ASCII 32-126)
for (int i = 0; i < 35; ++i) {
s.add(flag_chars[i] >= 32);
s.add(flag_chars[i] <= 126);
}

// Map assembly variables to our flag_chars array
// Str -> flag_chars[0]
// v5 -> flag_chars[1]
// v6 -> flag_chars[2]
// ...
// v38 -> flag_chars[34]

z3::expr Str = flag_chars[0];
z3::expr v5 = flag_chars[1];
z3::expr v6 = flag_chars[2];
z3::expr v7 = flag_chars[3];
z3::expr v8 = flag_chars[4];
z3::expr v9 = flag_chars[5];
z3::expr v10 = flag_chars[6];
z3::expr v11 = flag_chars[7];
z3::expr v12 = flag_chars[8];
z3::expr v13 = flag_chars[9];
z3::expr v14 = flag_chars[10];
z3::expr v15 = flag_chars[11];
z3::expr v16 = flag_chars[12];
z3::expr v17 = flag_chars[13];
z3::expr v18 = flag_chars[14];
z3::expr v19 = flag_chars[15];
z3::expr v20 = flag_chars[16];
z3::expr v21 = flag_chars[17];
z3::expr v22 = flag_chars[18];
z3::expr v23 = flag_chars[19];
z3::expr v24 = flag_chars[20];
z3::expr v25 = flag_chars[21];
z3::expr v26 = flag_chars[22];
z3::expr v27 = flag_chars[23];
z3::expr v28 = flag_chars[24];
z3::expr v29 = flag_chars[25];
z3::expr v30 = flag_chars[26];
z3::expr v31 = flag_chars[27];
z3::expr v32 = flag_chars[28];
z3::expr v33 = flag_chars[29];
z3::expr v34 = flag_chars[30];
z3::expr v35 = flag_chars[31];
z3::expr v36 = flag_chars[32];
z3::expr v37 = flag_chars[33];
z3::expr v38 = flag_chars[34];

// Add the equations as constraints
s.add(v5 * v6 + Str - v7 + v8 == 11449);
s.add(v12 + v10 * v9 - v11 - v13 == 11663);
s.add(v14 + v15 * v16 - v17 * v18 == 927);
s.add(v21 * v20 * v19 - v22 + v23 == 625575);
s.add(v25 * v26 + v24 - v27 - v28 == 11448);
s.add(v30 * v29 - v31 - v32 + v33 == 5612);
s.add(v37 + v35 * v36 + v34 + v38 == 5537);
s.add(v37 * v31 + v38 == 2828);
s.add(v16 + v17 - v32 * v33 == -5499);
s.add(v29 * v21 + v34 == 2811);
s.add(v30 + v16 + v35 == 271);
s.add(v31 * v22 + v36 == 5666);
s.add(v23 + v32 * v37 == 5829);
s.add(v33 + v24 + v38 == 291);
s.add(v34 * v25 * v35 == 687764);
s.add(v15 + v16 * v17 == 6066);
s.add(v20 + v19 + v21 == 275);
s.add(v23 * v22 + v24 == 5782);
s.add(v25 + v24 + v26 == 330);
s.add(v26 + v27 * v28 == 5763);
s.add(v30 * v29 + v31 == 5771);
s.add(v32 + v31 - v33 == 108);
s.add(v34 * v33 - v35 == 5983);
s.add(Str * v35 + v5 == 4967);
s.add(v10 + v9 - v11 == 95);
s.add(v13 + v14 * v15 == 5279);

// Check for satisfiability
if (s.check() == z3::sat) {
z3::model m = s.get_model();
std::string result_flag = "";
for (int i = 0; i < 35; ++i) {
result_flag += static_cast<char>(m.eval(flag_chars[i]).as_int64());
}
std::cout << "Found flag: " << result_flag << std::endl;
} else {
std::cout << "Failed to find a solution." << std::endl;
}

return 0;
}

运行后是ctbxf~^}'_l0v3_rp1m4ry_m47h3m4t1k5}

依然人肉修复

ctbuctf{1_l0v3_pr1m4ry_m47h3m4t1k5}

FORENSICS

学弟复仇记Ⅰ:情人节行动

软件一把梭,还得到了secret

ctbuctf{xxxLoveyyy1314_xxx20000818_qweasdzxc123456}

ctbuctf{39o475}

学弟复仇记Ⅱ:网络谜踪

沙箱梭

ctbuctf{103.117.120.68}