news 2026/5/25 2:01:07

【2026】ISCC 长虹守卫

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【2026】ISCC 长虹守卫

长虹守卫
题目类型:杂项

拿到这道题的时候我第一反应是:飞行日志 + pcap,这两个东西放在一起能有什么关系?

带着这个问题开始看。

先摸清楚题目在说什么

LX517.txt打开,73 行,每行是一条飞行记录。飞机叫 AURORA-ER,航班号 LX-517,从太平洋中部向东飞。我注意到经度在 idx=0026 附近发生了一次跳变:

0025: lon=179.1578° 0026: lon=179.2429° 0027: lon=-179.9142°

经度从正数跳成负数,这是穿越了国际日期变更线(IDL,经度 180°)。

然后我注意到一件奇怪的事——idx=0026 和 idx=0027 的时间

0026: 2026-01-19 12:27:33 0027: 2026-01-19 11:28:06

时间倒退了将近一个小时,但日期没变,还是 1月19日。

正常来说,飞机向东穿越 IDL,本地时间应该减一天。时钟往回拨了,但日期没跟着变——这是个 bug。idx=0026 的 detail 字段直接写明了:

DATE_CORR=-1DAY;bug=FDR-227(date_not_applied)

应该减一天,但没减。这个 bug 是整道题的核心。

文件末尾藏了什么

cat LX517.txt的时候,最后一行之后有一段乱码。放大看:

tail -c 600 LX517.txt | xxd | head -20

\x00之后全是A-Za-z0-9+/=,末尾有=补位,是 Base64。

Tail -c 600 LX517.txt | tr -d ‘\0\r\n\f\t’ | grep -a -oP ‘[A-Za-z0-9+/=]{80,}’ | base64 -d 2>/dev/null

解出来:

这是加密的说明书,藏在文件末尾。

读完之后整个题目的逻辑就清晰了:密钥由三个飞行事件的 UTC 时间戳拼成,用这个密钥生成 SHA256 流密码,去解密 pcap 里的密文。

三个事件,一个陷阱

根据 NOTE 找三类事件:

grep -E "EVT_A|EVT_B|EVT_C" LX517.txt

EVT_A 和 EVT_B 各只有一条,没有歧义。EVT_C 出现了三次:

idx=0033 marker=X9 desc=noise idx=0049 marker=A2 desc=timing_inconsistency_suspected idx=0056 marker=Z1 desc=decoy

noisedecoy是题目故意放的干扰,NOTE 里说的是ANOMALY_MARKER_A2,所以目标是 idx=0049。

但我在写脚本的时候没有直接排除 X9,因为noise这个词本身也可能是迷惑性的——万一 A2 解不出来,X9 也要试。事实证明这个保留是对的,脚本把 X9 和 A2 都纳入候选,最终在第 167 次尝试时命中。

三个关键事件:

事件

idx

本地时间

经度

EVT_A(TCP SYN)

0041

2026-01-19 11:54:12

-173.7042°

EVT_B(IDL 跨越)

0026

2026-01-19 12:27:33

+179.2429°

EVT_C(标记 A2)

0049

2026-01-19 11:56:21

-173.3478°

IDL bug 对时间戳的影响

这是最需要想清楚的地方。

hint 里的 IDRULE 说:

IDRULE:idx26_applied_to_idx>=27_only

意思是 idx=0026 记录的日期修正(-1天)只影响 idx>=27 的行,idx=0026 本身不受影响。

所以:

  • EVT_B(idx=0026):不需要日期修正,直接用本地时间算 UTC
  • EVT_A(idx=0041)和 EVT_C(idx=0049):idx > 26,需要考虑日期修正

"考虑"的意思是:由于 bug 的存在,这些行的本地时间日期可能是错的(多了一天),也可能是对的(如果不应用修正)。两种情况都要试。

时间转换公式:

UTC = 本地时间 + 日期修正(0天或-1天)- 时区偏移

时区偏移根据经度估算,经度 / 15取整,但靠近 IDL 的区域时区不规则,要多试几个值:

经度 -173.7° → 可能是 -11 或 -12 经度 +179.2° → 可能是 +12、+13 或 +14

每个事件生成一组候选时间戳,三组取笛卡尔积,逐一尝试解密。

pcap 里的密文

strings -n 4 LX517.pcap | grep -a -i “CIPH”

76 个十六进制字符,38 字节。ISCC{是 5 字节,32 位 hex 是 32 字节,}是 1 字节,合计 38 字节——密文长度和 flag 格式完全吻合,说明密文就是直接加密的 flag。

用 tshark 也可以看到同样的内容:

tshark -r LX517.pcap -T fields -e data.data 2>/dev/null

解密原理

SHA256 CTR 流密码,每个块用计数器区分:

密钥流[0] = SHA256(keymat_bytes + \x00\x00\x00\x00) 密钥流[1] = SHA256(keymat_bytes + \x00\x00\x00\x01) ... 取前 38 字节 明文 = 密文 XOR 密钥流

XOR 的性质:A XOR K XOR K = A,加解密用同一套代码。

运行脚本:

hint: KEYMAT:AURORA-ER|flight=LX-517|syn=<EVT_A_UTC>|idl=<EVT_B_UTC>|a2=<EVT_C_UTC> ALGO:SHA256|XOR|CTR REASM:SEQ_ORDER|frag=3 IDRULE:idx26_applied_to_idx>=27_only UTC:local+date_corr-timezone NOTE:EVT_A=TCP_SYN_SENT,EVT_B=IDL_CROSS,EVT_C=ANOMALY_MARKER_A2 ciphertext: 6bcc44455892278c6577691d39eef5806754e33feecb956e9546fe8ca331966d2e0683c054c6 keymat: AURORA-ER|flight=LX-517|syn=1768863252|idl=1768775253|a2=1768862526 flag: ISCC{df155a9a410be4e7b14a6a191bb5eddc} tried: 167

验证成功的时间戳

python3 -c " from datetime import datetime, timezone pairs = [('EVT_A', 1768863252), ('EVT_B', 1768775253), ('EVT_C', 1768862526)] for name, ts in pairs: print(name, datetime.fromtimestamp(ts, tz=timezone.utc)) " EVT_A 2026-01-19 23:54:12+00:00 EVT_B 2026-01-19 00:27:33+00:00 EVT_C 2026-01-18 22:56:06+00:00

反推:

  • EVT_A:本地11:54:12,时区-12→ UTC23:54:12,日期 1月19日(未应用修正)✓
  • EVT_B:本地12:27:33,时区+12→ UTC00:27:33,日期 1月19日(idx=26 不修正)✓
  • EVT_C:UTC22:56:06,反推本地11:56:06,日期2026-01-18(应用了 -1天修正,时区-11

EVT_C 的本地时间反推是11:56:06,而 idx=0049 记录的是11:56:21,差了 15 秒。这说明暴力搜索命中的候选值并不是从 idx=0049 精确推算出来的,而是候选集足够宽,覆盖了正确答案。这也是为什么要把 X9 也纳入候选——扩大搜索空间,容错。

回头看这道题的设计

整道题围绕一个现实中真实存在的问题:飞行数据记录仪(FDR)在跨越 IDL 时的日期处理 bug

题目把这个 bug 做成了密钥的一部分——因为 bug 的存在,时间戳有歧义,所以不能精确计算,只能枚举。这个设计让暴力搜索成为必要,而不是偷懒。

三个 EVT_C 的设置也很有意思:noiseA2decoy,中间夹着真正的目标,两侧都是干扰。如果只看名字就排除,可能会漏掉 X9 这个候选,导致搜索空间不够宽,最终找不到答案。

Flag:

EXP:

import base64 import csv import hashlib import io import re import struct from datetime import datetime, timedelta, timezone from itertools import product from pathlib import Path import dpkt WORK_DIR = Path(__file__).resolve().parent LOG_FILE = WORK_DIR / "LX517.txt" CAP_FILE = WORK_DIR / "LX517.pcap" FLAG_RE = re.compile(rb"^ISCC\{[0-9a-fA-F]{32}\}$") # ── 1. 从日志末尾提取并解码 Base64 hint ─────────────────────────────────── def load_hint(path: Path) -> str: raw = path.read_text(encoding="utf-8", errors="ignore") for token in re.findall(r"[A-Za-z0-9+/=]{80,}", raw): try: s = base64.b64decode(token).decode() if "KEYMAT:" in s and "ALGO:" in s: return s except Exception: pass raise ValueError("hint not found") # ── 2. 用 csv 模块解析飞行日志 ──────────────────────────────────────────── def load_log(path: Path) -> list[dict]: lines = [ ln for ln in path.read_text(encoding="utf-8", errors="ignore").splitlines() if re.match(r"^\d{4},", ln) ] reader = csv.reader(io.StringIO("\n".join(lines)), skipinitialspace=True) records = [] for row in reader: if len(row) < 10: continue # csv 把 detail 字段(含逗号)也正确处理了,但我们用 maxsplit=9 的原始行更安全 # 这里直接用 row,detail 是 row[9] try: records.append({ "seq": int(row[0]), "dt": datetime.strptime(row[1].strip(), "%Y-%m-%d %H:%M:%S"), "lat": float(row[2]), "lon": float(row[3]), "evt": row[8].strip(), "note": row[9].strip(), }) except (ValueError, IndexError): continue return records # ── 3. 用 dpkt 解析 pcap,提取 TCP 载荷中的密文 ────────────────────────── def extract_ct(path: Path) -> bytes: payload_buf = bytearray() with open(path, "rb") as f: for _, pkt in dpkt.pcap.Reader(f): try: eth = dpkt.ethernet.Ethernet(pkt) if not isinstance(eth.data, dpkt.ip.IP): continue ip = eth.data if not isinstance(ip.data, dpkt.tcp.TCP): continue tcp = ip.data if tcp.data: payload_buf += tcp.data except Exception: continue hit = re.search(rb"CIPH:([0-9a-fA-F]+)", bytes(payload_buf)) if not hit: hit = re.search(rb"CIPH:([0-9a-fA-F]+)", path.read_bytes()) if not hit: raise ValueError("ciphertext not found") return bytes.fromhex(hit.group(1).decode()) # ── 4. 时区候选:经度附近所有合理偏移 ──────────────────────────────────── def tz_candidates(lon: float) -> list[int]: base = round(lon / 15) extra = [] if lon > 150: extra = [12, 13, 14] elif lon < -150: extra = [-10, -11, -12] return sorted({base, *extra}) # ── 5. 生成候选 UTC epoch,用生成器避免预先展开 ─────────────────────────── def epoch_gen(rec: dict): for tz, dc in product(tz_candidates(rec["lon"]), (0, -1)): t = rec["dt"] + timedelta(days=dc) - timedelta(hours=tz) yield int(t.replace(tzinfo=timezone.utc).timestamp()) # ── 6. SHA256 流密码,用 bytearray 原地 XOR ─────────────────────────────── def stream_decrypt(ct: bytes, key: str) -> bytes: key_b = key.encode() out = bytearray(len(ct)) block_idx = 0 pos = 0 while pos < len(ct): ks_block = hashlib.sha256(key_b + struct.pack(">I", block_idx)).digest() for byte in ks_block: if pos >= len(ct): break out[pos] = ct[pos] ^ byte pos += 1 block_idx += 1 return bytes(out) # ── 7. 主逻辑 ───────────────────────────────────────────────────────────── def main(): hint = load_hint(LOG_FILE) log = load_log(LOG_FILE) ct = extract_ct(CAP_FILE) tmpl = re.search(r"^KEYMAT:(.+)$", hint, re.MULTILINE).group(1).strip() syn_pool = [e for e in log if e["evt"] == "EVT_A"] idl_pool = [e for e in log if e["evt"] == "EVT_B"] a2_pool = [e for e in log if e["evt"] == "EVT_C" and ("marker=A2" in e["note"] or "marker=X9" in e["note"])] count = 0 for ea, eb, ec in product(syn_pool, idl_pool, a2_pool): seen = set() for syn, idl, a2 in product( set(epoch_gen(ea)), set(epoch_gen(eb)), set(epoch_gen(ec)), ): key = (syn, idl, a2) if key in seen: continue seen.add(key) km = (tmpl .replace("<EVT_A_UTC>", str(syn)) .replace("<EVT_B_UTC>", str(idl)) .replace("<EVT_C_UTC>", str(a2))) count += 1 plain = stream_decrypt(ct, km) if FLAG_RE.match(plain): print("hint:") print(hint) print("ciphertext:", ct.hex()) print("keymat:", km) print("flag:", plain.decode()) print("tried:", count) return raise RuntimeError(f"not solved after {count} attempts") if __name__ == "__main__": main()
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/25 1:57:41

除了Ctrl+Alt+A,国产系统(UOS/麒麟/NFS)还有哪些隐藏的截图姿势?

国产操作系统截图功能全攻略&#xff1a;超越CtrlAltA的高效玩法在国产操作系统如统信UOS、麒麟KOS和中科方德NFS的日常使用中&#xff0c;截图功能无疑是高频操作之一。大多数用户可能只熟悉默认的CtrlAltA快捷键&#xff0c;却不知道这些系统其实内置了丰富多样的截图工具和技…

作者头像 李华
网站建设 2026/5/25 1:56:32

5秒音频也能玩转AI?手把手教你用ESC-50数据集入门环境声音分类

5秒音频也能玩转AI&#xff1f;手把手教你用ESC-50数据集入门环境声音分类当你第一次听说"用AI识别声音"时&#xff0c;脑海中浮现的可能是科幻电影里的场景。但现实中的音频分类技术&#xff0c;其实可以从短短5秒的录音开始。这就是ESC-50数据集的魅力——它把2000…

作者头像 李华
网站建设 2026/5/25 1:56:31

10分钟上手oam-tools:昇腾NPU运维自动化工具集

前言 要用昇腾NPU做运维自动化&#xff0c;但不知道从哪入手&#xff1f;监控NPU状态、自动重启异常NPU、批量升级NPU驱动——这些操作有没有一个工具能一站式搞定&#xff1f; oam-tools就是为了这个场景准备的。第一次看到它的时候&#xff0c;也被它的"运维自动化"…

作者头像 李华
网站建设 2026/5/25 1:49:44

从0到10万粉:用ChatGPT批量生成B站选题、脚本、标题、简介、弹幕预埋——完整工作流拆解,含5大防限流校验节点

更多请点击&#xff1a; https://codechina.net 第一章&#xff1a;从0到10万粉&#xff1a;ChatGPT驱动的B站内容工业化生产全景图 当单人创作者面临选题枯竭、脚本耗时、剪辑低效、发布时间不稳定等瓶颈时&#xff0c;一套可复用、可度量、可扩展的内容工业化流水线成为破局…

作者头像 李华
网站建设 2026/5/25 1:49:19

OpenAI Codex Goal Mode 介绍和开启教程

导读 OpenAI 正式宣布 Codex 的 Goal Mode 脱离实验阶段&#xff0c;覆盖 app、IDE 扩展和 CLI 三端。用户只需设定一个目标&#xff0c;Codex 就能围绕这个目标持续推进数小时甚至数天——coding agent 从「逐条提示」跨入了「定目标、自己干」的新阶段。一条 /goal 命令&…

作者头像 李华
网站建设 2026/5/25 1:44:56

神经网络量化技术:TruncQuant在边缘计算中的高效实现

1. 神经网络量化技术背景解析 在边缘计算设备上部署深度神经网络(DNN)面临的核心矛盾是&#xff1a;模型性能与计算资源消耗之间的权衡。随着模型复杂度提升&#xff0c;参数量呈指数级增长&#xff0c;这对存储空间和计算能力有限的边缘设备构成了严峻挑战。量化技术通过降低权…

作者头像 李华