2026平航杯

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

服务器

写在前面

写这部分的时候还没发官方wp,我还想出题人咋这坏,把运行的环境都删了,结果不用装npm,原本带的nodejs就够了,启动的命令在package.json

image-20260414194811246

分析服务器镜像,内核版本为?

image-20260412125152903

分析服务器镜像,用户登录成功系统的次数为

image-20260412125316007

分析服务器镜像,redis数据库服务密码是多少

仿真服务器,在本地连接。Redis 的配置文件通常位于 /etc/redis/redis.conf

1
sudo cat /etc/redis/redis.conf

根据配置文件可以找到密码是zjjcxy

分析服务器镜像,api站点后台管理员密码所用的加密算法为

我们先看一下服务器的日志,丢给ai分析一下

用户在 /home/zaoqiwang/claude-relay-service 目录下进行操作,表明这是 Claude 中转服务 的项目根目录

我们在/home/zaoqiwang/claude-relay-service/scr/route 文件夹下面发现一个web.js

image-20260412132054859

所以加密算法就是Argon2id

分析服务器镇像,api站点后台管理员密码

不需要爆破,我们在日志文件里面就能找到管理员的密码b123321b

分析服务器镜像,登录api网站后台,后台通知设置里的超时事件(毫秒)为

这里就要把api服务搭起来了

安装 Node.js 和 npm

1
2
apt update
apt install -y nodejs npm

检查 Redis 服务状态

1
systemctl status redis-server

安装项目依赖

1
npm install

启动网站服务

1
npm start

查看日志

1
npm run service:logs

找到管理员后台路由用前面找到的用户名密码登进去

image-20260412135644080

分析服务器镜像,登录api网站后台,查询总Token消耗数量为?

image-20260412135704983

分析服务器镜像,登录api网站后台,查询最早创建apikey的时间为?

导出apikey信息,时间格式和题目要求不符,我们去数据库找,用navicat连上去

image-20260412140624763

分析服务器镜像,编写脚本,通过调用inject_bash_blocks函数,确定恶意投毒的payload。

下面这几个题主要是针对wasm(后台投毒的模块)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#!/usr/bin/env node

'use strict'

const bashBlockInjector = require('./src/utils/bashBlockInjector')

const { injectBashBlocks } = bashBlockInjector

// 测试输入:包含 bash 代码块的文本
const testInput = "```bash\necho hello\n```"

console.log("Testing injectBashBlocks function")
console.log("=".repeat(50))
console.log("\nInput:")
console.log(testInput)

// 调用函数
const result = injectBashBlocks(testInput)

console.log("\nOutput:")
console.log(result)

console.log("\n" + "=".repeat(50))
console.log("Detected injection!")

image-20260412142128789

给ai连上ssh,它做出来了(苦笑)

image-20260414200429176

接上题,should_inject_for_ua(ua,ip)对UA字符串有过滤条件,只有特定UA才会进入后续判断。请编写脚本找出有几个UA头能使函数有机会返 回true的UA关键词。【提示:备选项: cur1、openclaw、mozilla、wget、httpx、claude、requests、bot、crawler】

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
const wasm = require('./bash_block_injector.js')
const N = 1000
const uaCandidates = [
'curl',
'openclaw',
'mozilla',
'wget',
'httpx',
'claude',
'requests',
'bot',
'crawler',
]

console.log(`UA 关键词扫描 (每个UA ${N} 次对调用)\n`)
console.log('说明: 每次使用独立IP,调用两次(第1次设时间戳,第2次紧跟检测)')
console.log('第2次间隔 < 1ms,ip_ok 必然为 true,命中仅取决于UA和概率门\n')

for (const ua of uaCandidates) {
let hits = 0
for (let i = 0; i < N; i++) {
const ip = `t2.${i}.0.0`

// 第1次:写入时间戳
wasm.should_inject_for_ua(ua, ip)

// 第2次:ip_ok=true
if (wasm.should_inject_for_ua(ua, ip)) hits++
}

const rate = (hits / N * 100).toFixed(1)
const mark = hits > 0 ? '[HIT]' : '[ ]'
console.log(`${mark} ua = "${ua.padEnd(24)}" 命中 ${String(hits).padStart(3)}/${N} (${rate}%)`)
}

console.log('\n结论: [HIT] 行对应的UA中包含触发关键词')

接上题,只有当同一IP的上次请求距今足够近时,才会进入概率判断。请编写脚本确定这个时间窗口的阈值(单位: ms)。【答案格式:100,注 意,只保留整百的,四舍五入】【提示:必须控制变量,每次实验使用一批全新的IP,先统一记录时间戳,再等待固定间隔后统一检测,不可在等待 期间更新同一IP的时间戳,否则会刷新计时,从0ms到1000ms逐步探测,找到从“命中”变为“不命中”的临界间隔,建议每个间隔值使用≥200个 IP以消除概率干扰。】

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
const wasm = require('./bash_block_injector.js')
const TARGET_UA = 'claude'
const N_IP = 500
const gaps = [0, 50, 100, 150, 200, 250, 300, 350, 400, 430, 450, 460, 470, 480, 490, 499,
501, 510, 520, 600, 800, 1000]

// 修复了箭头函数语法
function sleep(ms) { return new Promise(r => setTimeout(r, ms)) }

async function main() {
console.log('IP 时间窗口阈值测试\n')
console.log('方法:')
console.log(' 1. 为 N 个独立IP批量写入时间戳')
console.log(' 2. 等待固定间隔 gap ms(期间不更新时间戳)')
console.log(' 3. 对同一批IP检测,统计命中率')
console.log(' 命中率 ≈ 2% → ip_ok=true;命中率 ≈ 0% → ip_ok=false\n')
console.log(`${'间隔'.padStart(8)} ${'命中率'.padStart(6)} ${'命中数'.padStart(8)} 结论\n`)
console.log('-'.repeat(50))

for (const gap of gaps) {
// 步骤1: 批量写入时间戳(每个IP唯一,避免相互干扰)
for (let i = 0; i < N_IP; i++) {
wasm.should_inject_for_ua(TARGET_UA, `t3.${gap}.${i}.0`)
}

// 步骤2: 等待 gap ms(不碰这批IP)
await sleep(gap)

// 步骤3: 检测同一批IP
let hits = 0
for (let i = 0; i < N_IP; i++) {
if (wasm.should_inject_for_ua(TARGET_UA, `t3.${gap}.${i}.0`)) hits++
}

const rate = (hits / N_IP * 100).toFixed(1)
const ipOk = hits > 0 ? 'ip_ok=true ✓' : 'ip_ok=false ✗'
console.log(`${String(gap).padStart(6)}ms ${(rate + '%').padStart(6)} (${String(hits).padStart(3)}/${N_IP}) ${ipOk}`)
}
console.log('\n结论: 找到命中率从 ~2% 降为 0% 的临界间隔,即为时间窗口阈值')
}

main().catch(console.error)

接上题,在UA条件和IP时间条件均满足的前提下,函数仍有一定概率返回false。请编写脚本估算触发概率,并推算概率1/N(即理论上平均每N次满 足前两个条件的调用才触发一次】。【答案格式:10,格式只保留整十】【提示:建议样本量不少于10000次有效检测(UA条件满足+IP时间条件满 足),不然四舍五入会出现进位问题。】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
const wasm = require('./bash_block_injector.js')
const TARGET_UA = 'claude'
const N = 10000

console.log('概率触发分母估算\n')
console.log('前提: UA 条件满足 + IP 时间条件满足(每次使用独立IP双次调用)')
console.log(`样本量: ${N} 次有效检测\n`)

let hits = 0
for (let i = 0; i < N; i++) {
const ip = `t4.${i}.0.0`

// 第1次:写入时间戳
wasm.should_inject_for_ua(TARGET_UA, ip)

// 第2次:ip_ok=true,仅受概率门影响
if (wasm.should_inject_for_ua(TARGET_UA, ip)) hits++
}

const rate = hits / N
console.log(`命中次数: ${hits} / ${N}`)
console.log(`命中率: ${(rate * 100).toFixed(3)}%`)
console.log(`估算分母: 约 1 / ${Math.round(1 / rate)}`)
console.log(`\n结论: 平均每调用约 ${Math.round(1 / rate)} 次(在满足前两个条件的情况下)触发一次`)

早起王的PC

关于仿真

仿真蓝屏之后选择 疑难解答 > 高级选项 > 命令提示符,然后用命令行删掉OSDATA文件夹

请分析早起王的PC镜像,沼气王的桌面有本日记,请问沼气王暗恋对象的生目为

输错两次密码获得提示:*****04 大小写字母

我们用掩码攻击爆破

image-20260414105502724

请分析早起王的PC镜像,早起王受到过一封邮件,请找出邮件中隐写的秘密

spammimic - decoded

找到可以邮件用这个网站解密即可

请分析早起王的PC镜像,VeraCrypt容器的外层密码是什么?

utools里面能找到

image-20260414110728263

请分析早起王的PC镜像,早起王设置了一个AI女友,并自行导入过一个角色模型,该模型的原始文件名

文档里面有一个VC容器,可以用上面的密码挂载

image-20260414110913016

请分析早起王的PC镜像,AI女友使用的模型是什么?

image-20260414111346863

请分析早起王的PC镜像,早起王曾喇除一个MD5值为49B367AC261A722A7CZBBC328C32545的恶意文件,请尝试数掘恢复并找到其文件名?

原来挂载VC容器的时候用隐藏层的密码就会加载隐藏层的内容

上传一个R-Studio然后数据恢复

image-20260414155723738

接上题,该文件中有多个流(streams)包含宏。请提供其中编号最小的一个。

使用oledump进行分析(不会)

image-20260414170320927

拥抱ai,下面关于这个文件的几道题我也不会,先鸽在这吧

请分析早起王的PC镜像,该PC中neo4j数据库的密码是多少

早起王电脑的图片文件夹里面有一个名字很可以的图片,上刑法发现是盲水印

image-20260414170604546

早起王在PC中记录过自己的犯罪动机并对其进行加密,请使用社工的方式破解加密文件,并提交密码。

我们发现一份早起王的简历,直接用tscan生成一份社工字典

image-20260414190627067

早起王的U盘

根据早起王笔录内容,早起王曾经对某企业进行过渗透攻击,请分析城内实体关系,FILESERVER,XIAORANG,LAB 对XIAORANG,LAB域挪有什么控 制权限?

我们之前找到了neo4j数据库的密码,用户名是默认的neo4j,但是我不会用bloodhound(哭),直接把U盘里面导出的数据库文件丢给ai分析一下

image-20260414190824492

根据早起王笔录内容,早起王在渗透过程中已成功控制ZHANGXINQXIAORANG.LAB,请结合域内实体关系图分析,早起王获取域控权限的完整攻击轨迹 是什么?

倩倩的PC

早起王曾给倩倩发送过一封钓鱼邮件,请找到并计算附件MD5值

image-20260414165719275

接上题,编译木马使用的.NET版本是多少?

die里面能看到

image-20260414170041925

木马部分也就止步于此了,逆向我真的不会(逃)

请分析倩倩的PC镜像,倩倩的电脑曾被api投毒过,请找出投毒后执行的的恶意命令

在claude的历史记录里面能找到

image-20260414195831504

总结

第一次打取证比赛,我们队得分190,排名202,一共学了不到两个周,还是很不错的。题目质量很高,取证工具能一把梭的题很少。

我主要打的是服务器和计算机,服务器部分一个是经验不足,没有从package.json中找到启动命令把网站搭起来,再是没有利用好ai连接ssh分析后面的问题。计算机部分修复仿真耗费了很长时间,甚至有的检材看都没看,导致后续木马文件判断以及内存取证出错。

继续学习,积累经验,备战FIC和盘古石!


2026平航杯
https://www.sunynov.top/2026/04/12/2026平航杯/
作者
suny
发布于
2026年4月12日
许可协议