蓝桥杯网络安全赛道国赛WP
说明:以下内容由公众号原文抓取并转换为 Markdown,用于个人 blog 存档。
由于陕西赛区没有考点,所以去的是郑州轻工业大学
比赛当天正好碰上了轻工业大学作为河南事业编的考点,也是被人误认为了是来考编的(灬ºωº灬)
学校还是挺大的,西门外居然有一条小树林步道,像公园一样
可惜忘记拍几张赛场照了
解题过程
1.guard_vm
虚拟机架构分析 从主循环的 while 逻辑可以看出,这台 VM 采用的是 固定长度指令集(3字节一小节):
v6 (*v4) 是 Opcode(操作码)。
v7 和 v8 分别是 操作数 1 和 操作数 2。
VM 的主要操作区是 s 数组(即你的输入缓冲区),但它玩了一个很经典的内存偏移陷阱:
代码中频繁出现 s[v7 - 2] 和 s[v8 - 2]。
回顾变量分配:v12 分配在 [rsp+1Eh],而 s 缓冲区在 [rsp+20h]。
这意味着当 v7 为 0 或 1 时,s[v7 - 2] 也就是 s[-2] 和 s[-1],刚好越界访问到了 v12 的内存!所以 v12 实际上扮演了 VM 的临时寄存器(R0 和 R1)的角色,而 s[0...95] 既是内存空间,也可以通过 v7 >= 2 作为寄存器被操作。
❝
根据伪代码,我们可以总结出这套指令集:
0x10 (16): s[v7-2] = s[v8] -> 将输入字符串的第 v8 个字符加载到目标寄存器。
0x20 (32): s[v7-2] ^= v8 -> 寄存器与立即数 v8 进行异或。
0x30 (48): s[v7-2] += v8 -> 寄存器加上立即数 v8。
0x40 (64): assert(s[v7-2] == v8) -> 校验指令!比较寄存器的值与立即数,如果不等则失败(goto LABEL_22)。
0x50 (80): s[v7-2] = s[v8-2] -> 寄存器之间赋值(MOV)。
0x60 (96): s[v7-2] ^= s[v8-2] -> 寄存器之间异或。
0x70 (112): s[v7-2] += s[v8-2] -> 寄存器之间相加。
0xFF (-1): 退出 VM 执行。
根据逻辑写脚本
找到byte_404060双击进去按shift+E提取出数组
导出为txt
将数组放入脚本中,解出flag
脚本:
from z3 import *
enc_bytecode = [
0xB5, 0xA5, 0xA5, 0x85, 0xA5, 0x01, 0x95, 0xA5, 0xB8, 0xC5,
0xA5, 0xA4, 0xF5, 0xA4, 0xA5, 0xE5, 0xA5, 0x7A, 0xB5, 0xA5,
0xA4, 0x85, 0xA5, 0xA2, 0x95, 0xA5, 0x1B, 0xC5, 0xA5, 0xA4,
0xF5, 0xA4, 0xA5, 0xE5, 0xA5, 0x53, 0xB5, 0xA5, 0xA7, 0x85,
0xA5, 0xE2, 0x95, 0xA5, 0x9A, 0xC5, 0xA5, 0xA4, 0xF5, 0xA4,
0xA5, 0xE5, 0xA5, 0x36, 0xB5, 0xA5, 0xA6, 0x85, 0xA5, 0x9F,
0x95, 0xA5, 0x81, 0xC5, 0xA5, 0xA4, 0xF5, 0xA4, 0xA5, 0xE5,
0xA5, 0xB7, 0xB5, 0xA5, 0xA1, 0x85, 0xA5, 0x18, 0x95, 0xA5,
0xBE, 0xC5, 0xA5, 0xA4, 0xF5, 0xA4, 0xA5, 0xE5, 0xA5, 0x56,
0xB5, 0xA5, 0xA0, 0x85, 0xA5, 0x0B, 0x95, 0xA5, 0x1B, 0xC5,
0xA5, 0xA4, 0xF5, 0xA4, 0xA5, 0xE5, 0xA5, 0xDB, 0xB5, 0xA5,
0xA3, 0x85, 0xA5, 0x40, 0x95, 0xA5, 0x29, 0xC5, 0xA5, 0xA4,
0xF5, 0xA4, 0xA5, 0xE5, 0xA5, 0xCB, 0xB5, 0xA5, 0xA2, 0x85,
0xA5, 0xB2, 0x95, 0xA5, 0x3D, 0xC5, 0xA5, 0xA4, 0xF5, 0xA4,
0xA5, 0xE5, 0xA5, 0x75, 0xB5, 0xA5, 0xAD, 0x85, 0xA5, 0xC8,
0x95, 0xA5, 0xAC, 0xC5, 0xA5, 0xA4, 0xF5, 0xA4, 0xA5, 0xE5,
0xA5, 0x60, 0xB5, 0xA5, 0xAC, 0x85, 0xA5, 0xAD, 0x95, 0xA5,
0xBD, 0xC5, 0xA5, 0xA4, 0xF5, 0xA4, 0xA5, 0xE5, 0xA5, 0x30,
0xB5, 0xA5, 0xAF, 0x85, 0xA5, 0x9D, 0x95, 0xA5, 0x99, 0xC5,
0xA5, 0xA4, 0xF5, 0xA4, 0xA5, 0xE5, 0xA5, 0xA7, 0xB5, 0xA5,
0xAE, 0x85, 0xA5, 0x27, 0x95, 0xA5, 0x3E, 0xC5, 0xA5, 0xA4,
0xF5, 0xA4, 0xA5, 0xE5, 0xA5, 0xF2, 0xB5, 0xA5, 0xA9, 0x85,
0xA5, 0xA2, 0x95, 0xA5, 0x35, 0xC5, 0xA5, 0xA4, 0xF5, 0xA4,
0xA5, 0xE5, 0xA5, 0x07, 0xB5, 0xA5, 0xA8, 0x85, 0xA5, 0x96,
0x95, 0xA5, 0x1D, 0xC5, 0xA5, 0xA4, 0xF5, 0xA4, 0xA5, 0xE5,
0xA5, 0xD1, 0xB5, 0xA5, 0xAB, 0x85, 0xA5, 0x02, 0x95, 0xA5,
0x11, 0xC5, 0xA5, 0xA4, 0xF5, 0xA4, 0xA5, 0xE5, 0xA5, 0x97,
0xB5, 0xA5, 0xAA, 0x85, 0xA5, 0x29, 0x95, 0xA5, 0xC9, 0xC5,
0xA5, 0xA4, 0xF5, 0xA4, 0xA5, 0xE5, 0xA5, 0xBE, 0xB5, 0xA5,
0xB5, 0x85, 0xA5, 0x9C, 0x95, 0xA5, 0xD6, 0xC5, 0xA5, 0xA4,
0xF5, 0xA4, 0xA5, 0xE5, 0xA5, 0x71, 0xB5, 0xA5, 0xB4, 0x85,
0xA5, 0x32, 0x95, 0xA5, 0xED, 0xC5, 0xA5, 0xA4, 0xF5, 0xA4,
0xA5, 0xE5, 0xA5, 0x99, 0xB5, 0xA5, 0xB7, 0x85, 0xA5, 0x75,
0x95, 0xA5, 0x7A, 0xC5, 0xA5, 0xA4, 0xF5, 0xA4, 0xA5, 0xE5,
0xA5, 0x45, 0xB5, 0xA5, 0xB6, 0x85, 0xA5, 0xA7, 0x95, 0xA5,
0x66, 0xC5, 0xA5, 0xA4, 0xF5, 0xA4, 0xA5, 0xE5, 0xA5, 0xBC,
0xB5, 0xA5, 0xB1, 0x85, 0xA5, 0x6A, 0x95, 0xA5, 0x8C, 0xC5,
0xA5, 0xA4, 0xF5, 0xA4, 0xA5, 0xE5, 0xA5, 0x68, 0xB5, 0xA5,
0xB0, 0x85, 0xA5, 0x16, 0x95, 0xA5, 0xC8, 0xC5, 0xA5, 0xA4,
0xF5, 0xA4, 0xA5, 0xE5, 0xA5, 0x87, 0xB5, 0xA5, 0xB3, 0x85,
0xA5, 0xFD, 0x95, 0xA5, 0xED, 0xC5, 0xA5, 0xA4, 0xF5, 0xA4,
0xA5, 0xE5, 0xA5, 0x03, 0xB5, 0xA5, 0xB2, 0x85, 0xA5, 0x8D,
0x95, 0xA5, 0x9D, 0xC5, 0xA5, 0xA4, 0xF5, 0xA4, 0xA5, 0xE5,
0xA5, 0x3E, 0xB5, 0xA5, 0xBD, 0x85, 0xA5, 0x53, 0x95, 0xA5,
0x61, 0xC5, 0xA5, 0xA4, 0xF5, 0xA4, 0xA5, 0xE5, 0xA5, 0x66,
0xB5, 0xA5, 0xBC, 0x85, 0xA5, 0xF2, 0x95, 0xA5, 0xBE, 0xC5,
0xA5, 0xA4, 0xF5, 0xA4, 0xA5, 0xE5, 0xA5, 0x36, 0xB5, 0xA5,
0xBF, 0x85, 0xA5, 0xBD, 0x95, 0xA5, 0xC7, 0xC5, 0xA5, 0xA4,
0xF5, 0xA4, 0xA5, 0xE5, 0xA5, 0xBA, 0xB5, 0xA5, 0xBE, 0x85,
0xA5, 0xBC, 0x95, 0xA5, 0xF9, 0xC5, 0xA5, 0xA4, 0xF5, 0xA4,
0xA5, 0xE5, 0xA5, 0x6D, 0xB5, 0xA5, 0xB9, 0x85, 0xA5, 0x7C,
0x95, 0xA5, 0xFC, 0xC5, 0xA5, 0xA4, 0xF5, 0xA4, 0xA5, 0xE5,
0xA5, 0x20, 0xB5, 0xA5, 0xB8, 0x85, 0xA5, 0x3E, 0x95, 0xA5,
0xE1, 0xC5, 0xA5, 0xA4, 0xF5, 0xA4, 0xA5, 0xE5, 0xA5, 0xCF,
0xB5, 0xA5, 0xBB, 0x85, 0xA5, 0x6A, 0x95, 0xA5, 0xA9, 0xC5,
0xA5, 0xA4, 0xF5, 0xA4, 0xA5, 0xE5, 0xA5, 0xC8, 0xB5, 0xA5,
0xBA, 0x85, 0xA5, 0x1E, 0x95, 0xA5, 0xD3, 0xC5, 0xA5, 0xA4,
0xF5, 0xA4, 0xA5, 0xE5, 0xA5, 0x87, 0xB5, 0xA5, 0x85, 0x85,
0xA5, 0x2F, 0x95, 0xA5, 0x85, 0xC5, 0xA5, 0xA4, 0xF5, 0xA4,
0xA5, 0xE5, 0xA5, 0x54, 0xB5, 0xA5, 0x84, 0x85, 0xA5, 0x5F,
0x95, 0xA5, 0x48, 0xC5, 0xA5, 0xA4, 0xF5, 0xA4, 0xA5, 0xE5,
0xA5, 0xDC, 0xB5, 0xA5, 0x87, 0x85, 0xA5, 0xC4, 0x95, 0xA5,
0xB0, 0xC5, 0xA5, 0xA4, 0xF5, 0xA4, 0xA5, 0xE5, 0xA5, 0xB9,
0xB5, 0xA5, 0x86, 0x85, 0xA5, 0x2B, 0x95, 0xA5, 0xE9, 0xC5,
0xA5, 0xA4, 0xF5, 0xA4, 0xA5, 0xE5, 0xA5, 0xB3, 0xB5, 0xA5,
0x81, 0x85, 0xA5, 0x70, 0x95, 0xA5, 0x04, 0xC5, 0xA5, 0xA4,
0xF5, 0xA4, 0xA5, 0xE5, 0xA5, 0x30, 0xB5, 0xA5, 0x80, 0x85,
0xA5, 0x3A, 0x95, 0xA5, 0x46, 0xC5, 0xA5, 0xA4, 0xF5, 0xA4,
0xA5, 0xE5, 0xA5, 0xA2, 0xB5, 0xA5, 0x83, 0x85, 0xA5, 0x78,
0x95, 0xA5, 0xF8, 0xC5, 0xA5, 0xA4, 0xF5, 0xA4, 0xA5, 0xE5,
0xA5, 0xE8, 0xB5, 0xA5, 0x82, 0x85, 0xA5, 0x31, 0x95, 0xA5,
0x97, 0xC5, 0xA5, 0xA4, 0xF5, 0xA4, 0xA5, 0xE5, 0xA5, 0x3E,
0xB5, 0xA5, 0x8D, 0x85, 0xA5, 0x10, 0x95, 0xA5, 0xB7, 0xC5,
0xA5, 0xA4, 0xF5, 0xA4, 0xA5, 0xE5, 0xA5, 0xAA, 0xB5, 0xA5,
0x8C, 0x85, 0xA5, 0xA9, 0x95, 0xA5, 0x0F, 0xC5, 0xA5, 0xA4,
0xF5, 0xA4, 0xA5, 0xE5, 0xA5, 0xB1, 0x5A
]
bytecode = [x ^ 0xA5 for x in enc_bytecode]
mem = [BitVecVal(0, 8) for _ in range(2)] + [BitVec(f's_{i}', 8) for i in range(96)]
orig_mem = list(mem)
solver = Solver()
for i in range(96):
solver.add(orig_mem[2 + i] >= 32, orig_mem[2 + i] <= 126)
pc = 0
while pc < len(bytecode):
if bytecode[pc] == 0xFF:
break
op = bytecode[pc]
v7 = bytecode[pc + 1]
v8 = bytecode[pc + 2]
pc += 3
if op == 0x70: # s[v7 - 2] += s[v8 - 2]
mem[v7] = mem[v7] + mem[v8]
elif op == 0x60: # s[v7 - 2] ^= s[v8 - 2]
mem[v7] = mem[v7] ^ mem[v8]
elif op == 0x50: # s[v7 - 2] = s[v8 - 2]
mem[v7] = mem[v8]
elif op == 0x40: # assert s[v7 - 2] == v8
solver.add(mem[v7] == v8)
elif op == 0x30: # s[v7 - 2] += v8
mem[v7] = mem[v7] + v8
elif op == 0x10: # s[v7 - 2] = s[v8]
# v8 是基于 s 缓冲区的绝对索引,所以在我们的 mem 数组里需要加 2
mem[v7] = mem[v8 + 2]
elif op == 0x20: # s[v7 - 2] ^= v8
mem[v7] = mem[v7] ^ v8
else:
print(f"[-] 遇到未知指令: {hex(op)} 位于 pc={pc - 3}")
break
print("正在求解")
if solver.check() == sat:
model = solver.model()
flag = ""
for i in range(96):
val = model[orig_mem[2 + i]].as_long()
flag += chr(val)
print(f"[+] Flag: {flag}")
else:
print("无解 ")
flag{aa1a0c8b-51e7-4d1d-bb2b-04b9a1070007}
2.guard_vm
进入题目后查看源码,可以看到隐藏的接口:
进入后有镜像mirror的路径信息
进入后有路由,时间戳和签名
直接进入显示错误的签名:
直接把时间戳和签名用get传参进去就能得到flag:
flag{6344671a-da43-4b61-8868-468249fcf535}
这道题目还是比较基础的,一路跟着线索进去就能解出来。一开始还没发现,后面看到大家库库交才发现的这道题
3.packet_shift
题目附件是一个流量包,打开以后追踪udp流,然后在data里面是加密的base64编码,解密即可得到flag
flag{ba3c5544-ad6b-8c6c-a85f-fcfa688ef2ca}
也是一道点击就送的题目ლ(╹◡╹ლ)
4.tiny_lcg
-
分析 LCG 的状态
题目给出的 LCG 参数如下:
-
$modulus = 2^31
-
$a = 1103515245
-
$c = 12345
-
observed_high16(观察到的高16位)为:['32c4', '0fae', '4847', 'a861', '5e65', '3cbb']
由于模数为 $2^31,内部状态最多为 31 位。因此,“高 16 位”对应的是状态向右移 15 位(即state >> 15),剩下的低 15 位是未知的。
由于低 15 位只有 $2^15 = 32768 种可能,我们完全可以通过爆破第一个状态的低 15 位,并验证其后继状态是否与给出的连续 6 个observed_high16一致。
经爆破可以成功找到唯一的初始状态:425853846。
-
分析加密方式与得到 Flag
在消耗掉已知的 6 个状态后,LCG 就会开始生成加密 flag 的密钥流。通过假设 flag 以标准格式flag{开头,对比密文的前几个字节,我们发现每步生成的密钥流单字节恰好等于(state >> 16) & 0xff。
编写脚本得到flag
def decrypt():
modulus = 2 ** 31
a = 1103515245
c = 12345
observed_high16 = ['32c4', '0fae', '4847', 'a861', '5e65', '3cbb']
high16_ints = [int(x, 16) for x in observed_high16]
initial_state = None
for low15 in range(2 ** 15):
state = (high16_ints[0] << 15) + low15
success = True
curr = state
for h in high16_ints[1:]:
curr = (a * curr + c) % modulus
if (curr >> 15) != h:
success = False
break
if success:
initial_state = (high16_ints[0] << 15) + low15
break
print(f"LCG初始状态: {initial_state}")
curr = initial_state
for _ in range(6):
curr = (a * curr + c) % modulus
encrypted_flag_hex = 'f2a33c617cc9c9a3078ff1f6722b417408e776d786d71dee91d5fd0de46178129a4acd550eb248e40d17'
enc_bytes = bytes.fromhex(encrypted_flag_hex)
flag = []
for b in enc_bytes:
keystream_byte = (curr >> 16) & 0xff
flag.append(b ^ keystream_byte)
curr = (a * curr + c) % modulus
print(f"Flag: {bytes(flag).decode('utf-8')}")
if __name__ == '__main__':
decrypt()
flag{042df1ec-7fc9-4e59-b165-0b74d4e4a004}
5.lattice_receipt
题目给出:
p = a x^2 + b x + c_coeff
在常规的类似题目中,我们会利用 p是 n 的因子这一特性,构造 f(x) \equiv 0 \pmod p,并通过 SageMath 使用 Coppersmith 求小根。
但仔细观察数据大小:
-
模数的长度约 616 位十进制(约等于2048bit),所以素数应该在bit 左右。
-
题目给的参数、以及负数 c_coeff长度全是 616 位十进制(约等于2048bit)。
-
这意味着在这个二次等式中:
a x^2 + b x + c_coeff - p = 0
由于 c_coeff 是一个 约等于2048 bit 的巨大常数,而 p 仅仅只有约等于1024 bit。p 相对 c_coeff 来说微乎其微,就像是大海里的一滴水。
因此,这个方程的精确解(实数域上)和我们直接求解 a x^2 + b x + c_coeff = 0 的解,误差在 2^{-1024}级别。这就意味着,我们完全不需要依靠格基规约,直接用初中数学的求根公式配上 Python 的超高精度整数开方(math.isqrt),向下取整后就能拿到 x
利用 p 隐藏了二次方程真实的常数项,诱导选手使用针对模方程的 Coppersmith 方法。但由于 p的量级过小,未能对常数项的高位造成任何影响,导致我们可以通过实数域的求根公式直接进行爆破。
根据题目逻辑写出脚本进行解密:
import math
n = 422432255985666345175707878873003038880241656708576300391089572030365205385428773309944317112051730239661981299388069910214920159986890067009480148855875638533320996777051780031673934924775771235557032528663682106763463547247841724869996146393953643586330168374560207238777767562259451798630901150576176560042687262325672918008625272402037391080937589800032668748843954022622603841293022354297257102770775150935075070631385820897581557808436331191610366147254938105734984672741870481817476257597156085158682687495816982889298415057106134213108119873315428982799563183372828598446439392086043885895326237981723702435283453039006712333277231452527292548376380985675075729226782604794053840332602703076061815494976692659731112372142178157498885770461378868896590762819980632504850686472824151204921686440370963655919274823419651367865872693815227049667019757771916607260143050939021465284930540531372945425362238522719106419073035308713169125862703455379722967678393317040786535883203323681789612997023877990022762284900433425629650420094041249718400112232573221987347529011714338019472847516214132296612673381023293719915087117276306986746216348523997813526245644825627628604548413995500400450405914029227879987921544551694832638659027
e = 65537
c = 60898888462232256438527165809348433953419615323658584021775304587730495581389649761467973374572324340495374563109625332727734614150223818939286445850593269440821976874087327693623615976457874624674481247562751192246610156294752407807223206045105461805779571368267815364349769402361822623113201163933690727431310504215595140463620652480091997615055829603964921905380600066005190124206939365500957253702820812362821889263771697609776267383574233391438376506145616262935719074774982490473120910273172129087739306494722462739673078535815974625326956757309598306358238968224697337600606933356767536112749436335852245811384324832773253586590918557008021527646332062632678953499883066707051649064637783250128778056935354040884306355180060335528665002362523835217055672730624530684853120147879929605059296436109364765234570660497605798121489643104413530218617371726280935140677168179474289559912439473040210111655000776757200119853259167361318481644890534915161020602029431728086082931415369206881786302094125479749148981533395163553230715578200070598698753664986038662024679944160167967210051288074717072626353604652374226640328469622357177954478250964611332163117786071611940965409202117155875845836427903173062205560276501231771133856077
a = 29071680978624438902623659006153741278563223284523241815922958622882978164833227089951887416355354209342128902329797948981227884227555083297781826884629045500717196846170903767641856660949705627355338625952338074736342482331373997692892596259857441680060220300665838136545316460809436592417980502838428012513455352902149371522828021523699228818184760670656674902188002921667329252832676003894331358263700705116787423671972622267556353199556402780397489286988346404579166100198125555889200617088843506845546056485286730668239343423264727761869030185489131682544227691247103449683378698898090197160760543789986772369597
b = 18531760294708772531236774336215416431580845679627099835550723887544516213656630257215679141762522841243633575620189769209216451496627046917377549884714688492831624650508270532324005793139437276722093215647970841134610911025306173210951346493060595753150155449131273514479525731819531617906167256000327926014707437856849547090922637019460692096942804659787869274563074251633709565369599185952902357727537384108758293691460766388597323482218175751476578932448806754463193915041560528845140520139772983516538361902802132145590956564550861041826375007874116160492689670342165374981533215631515398271180372269082710159857
c_coeff = -370103082211399448643149445180794180887161464123813839818791896099210047226174849214440800868426511549395220264536653468709454879535385435745751339008960104169978346541283572360065171041995633563013693450470394284675805344869487594620148620261257283577219624306696704892061202397361361554004692328558117738295090759702436680012420520856077589384854707159396432274681001363336675048289432273719997058863351649161157850512395309085304620199304759501368602066880195241400110272096057055877040137745441251036451767029566381379408494183838399493046294419127070905127665848222661564667091896334501489387757688024520961005273563977738202283956988445113108873310143633731142970862057230294539256114534168240628540685229453726417585619469193676278380019947612041872788829303229359
def solve():
print("绕过格基规约")
print("计算二次方程判别式 (Discriminant) delta = b^2 - 4ac")
delta = b ** 2 - 4 * a * c_coeff
print("计算判别式的精确整数平方根")
sqrt_delta = math.isqrt(delta)
# 求解求根公式 x = (-b ± sqrt(delta)) // 2a
x1 = (-b + sqrt_delta) // (2 * a)
x2 = (-b - sqrt_delta) // (2 * a)
candidates = [x1 - 1, x1, x1 + 1, x2 - 1, x2, x2 + 1]
p = None
for x in candidates:
temp_p = a * x ** 2 + b * x + c_coeff
if temp_p > 1 and n % temp_p == 0:
p = temp_p
print(f"\nx: {x}")
print(f"恢复素数 p: {p}")
break
if not p:
print("未能找到有效的 p,请检查参数。")
return
print("\n计算私钥并解密票据")
q = n // p
phi = (p - 1) * (q - 1)
d = pow(e, -1, phi)
m = pow(c, d, n)
try:
from Crypto.Util.number import long_to_bytes
flag = long_to_bytes(m)
except ImportError:
flag = m.to_bytes((m.bit_length() + 7) // 8, byteorder='big')
print(f"\nFlag: {flag.decode('utf-8', errors='ignore')}")
if __name__ == '__main__':
solve()
flag{f9ab58c1db90ca755d59b02aff85c424}
题目描述:事件响应助手会拒绝直接读取敏感文件。要求通过“正常业务流程”触发被污染的检索链,并取得 flag。
尝试直接构造恶意语句执行失败:
失败原因:请求返回了报错,导致 JSON 解析失败(could not parse model output)。查看原始输出发现,LLM 幻觉出了一个不存在的命令,并且陷入了无限复读"/evidence/coredump.img"的 Token 循环。 这是因为目标模型SmolLM2-135M参数量极小,注意力机制非常脆弱。复杂的覆盖指令导致其在真实文档和伪造指令之间产生逻辑冲突,直接崩溃(Context Collapse)。
查看每一个evidence id,结合Policy文档发现只有 CRITICAL 级别才会触发 auto-remediation
INC-0471: Severity: MEDIUM (不触发)
INC-0472: Severity: CRITICAL * Remediation: verify_leaked_artifact_integrity /evidence/coredump.img
INC-0473: Severity: LOW (不触发)
所以漏洞点在INC-0472 它伪装成了一个合法的严重安全事件,而它的修复命令 verify_leaked_artifact_integrity 很可能就是攻击者提前埋在后端系统中用来读取 Flag 的后门脚本(或者它本身存在参数注入)。
查看INC-0472
直接输入能够精准匹配到 INC-0472 的正常关键词
构造正常的逻辑语句,即可得到flag:
Payload:
Plaintext
artifact verification
flag{9fc2df68-de21-474b-9e04-b15ffbce9107}
这道题还是很有意思的,一开始没有仔细看到题目是要按照正常的业务逻辑去触发污染链,一直构造恶意语句发现怎么绕都绕不过去,中途放弃了去做别的题目,后面发现交的人非常多就回来写了,仔细看了一遍题目也是来灵感了,直接输入INC-0472 能匹配到的关键词就能出flag了,还是非常有意思的(๑´ڡ`๑)
公众号后台回复lqb2026拿wp题目对应附件