TE
题目分析
题目提供了一个 Python 脚本 task.py,其中包含以下关键信息:
生成了两个 512 位的素数
p和q,计算模数n = p * q。生成了两个随机的公钥指数
e1和e2。对同一个明文
flag使用不同的公钥指数e1和e2进行加密,得到两个密文c1和c2。
$$
c_1 \equiv m^{e_1} \pmod n
$$$$
c_2 \equiv m^{e_2} \pmod n
$$给出了
e1,e2,n,c1,c2的具体数值。
漏洞原理:共模攻击 (Common Modulus Attack)
当同一个明文 $m$ 使用相同的模数 $n$ 但不同的公钥指数 $e_1, e_2$ 进行加密时,如果 $e_1$ 和 $e_2$ 互素(即 $\gcd(e_1, e_2) = 1$),攻击者可以在不分解 $n$ 的情况下直接恢复明文 $m$。
原理如下:
根据扩展欧几里得算法(Extended Euclidean Algorithm),对于互素的 $e_1$ 和 $e_2$,一定存在整数 $s_1$ 和 $s_2$ 满足:
$$
s_1 e_1 + s_2 e_2 = 1
$$
利用模运算的性质:
$$
c_1^{s_1} \times c_2^{s_2} \equiv (m^{e_1})^{s_1} \times (m^{e_2})^{s_2} \pmod n
$$
$$
\equiv m^{e_1 s_1} \times m^{e_2 s_2} \pmod n
$$
$$
\equiv m^{e_1 s_1 + e_2 s_2} \pmod n
$$
$$
\equiv m^1 \pmod n
$$
$$
\equiv m \pmod n
$$
注意:由于 $s_1$ 和 $s_2$ 中必有一个为负数,计算 $c^s \pmod n$ 时,如果 $s < 0$,需要先计算 $c$ 的模逆元 $c^{-1} \pmod n$,然后计算
$$
(c^{-1})^{-s} \pmod n
$$
解题脚本
1 | from Crypto.Util.number import long_to_bytes |
运行结果
运行结果如下:
1 | gcd(e1, e2) = 1 |
Ez_RSA
题目分析:Wiener’s Attack
题目提供了一个 Python 脚本 193540_chall.py,其中给出了 RSA 的公钥参数 n, e 以及密文 c。
代码片段如下:
1 | p = getPrime(512) |
观察参数特点:
n是由两个 512 位的素数生成的,长度约为 1024 位。e是一个生成的 1019 位的素数。
漏洞点:
通常 RSA 的 e 选取较小的值(如 65537),但在本题中 e 非常大,接近模数 n 的大小。
根据 RSA 的密钥生成公式:
$$
ed \equiv 1 \pmod{\phi(n)} \implies ed - k\phi(n) = 1
$$
当 e 很大时,对应的私钥 d 往往很小。
如果满足 $d < \frac{1}{3}N^{\frac{1}{4}}$,我们可以利用 Wiener’s Attack(维纳攻击)来还原 d。维纳攻击的核心思想是 e/n 是 k/d 的一个最佳有理逼近,可以通过计算 e/n 的连分数渐近分数来尝试找到 d。
解题思路
- 提取题目中的
n,e,c。 - 编写脚本对
e/n进行连分数展开,生成一系列渐近分数。 - 遍历每一个渐近分数的分母作为潜在的私钥
d。 - 使用候选的
d计算潜在的\phi(n),进而解一元二次方程验证是否能分解n(或者直接尝试解密c并判断结果是否符合 Flag 格式)。 - 找到正确的
d后,计算
$$
m = c^d \pmod n
$$
得到明文。
解题脚本
1 | import math |
运行结果
运行上述脚本,成功解出私钥 d 并还原明文。
1 | d = 13381010831988668939315406679736078064417157389064253385691768500704978358617 |
Flag:
1 | SHCTF{e950ea87356fc62ce6323253a672680e} |
Stream
题目分析:LCG 流加密破解
题目提供了一个 Python 脚本 task.py,实现了一个基于线性同余生成器 (LCG) 的流加密算法。
加密流程如下:
- 生成参数:随机生成 LCG 的参数
m(63位),a(62位),c(62位),s_0(62位)。m强制为 63 位且最高位为 1。
- 生成密钥流:使用 LCG 公式
$$
x_{i+1} = (a \cdot x_i + c) \pmod m
$$
生成一串随机数。 - 加密:
- 将明文 $P$ 填充并按 8 字节分块。
- 每一块明文与对应的 LCG 状态值(密钥流)进行异或运算得到密文。
已知信息:
- 明文
P_known(48字节,即 6 个块)。 - 对应的密文
C_known。 - Flag 的密文
C_flag。
漏洞原理
LCG (Linear Congruential Generator) 是一种简单的伪随机数生成器,其安全性依赖于参数的保密性。但在已知部分输出序列的情况下,其参数很容易被破解。
攻击步骤:
恢复密钥流样本:
已知
$$
P_{known}
$$
和
$$
C_{known}
$$
,利用异或的性质
$$
A \oplus B = C \implies A \oplus C = B
$$
,我们可以直接恢复出前 6 个 LCG 的状态值:
$$
S_i = P_i \oplus C_i
$$
得到序列
$$
S_0, S_1, S_2, S_3, S_4, S_5
$$
。攻击模数 $m$:
由 LCG 定义:
$$
S_{i+1} \equiv a \cdot S_i + c \pmod m
$$$$
S_{i+2} \equiv a \cdot S_{i+1} + c \pmod m
$$两式相减消除 c:
$$
S_{i+2} - S_{i+1} \equiv a \cdot (S_{i+1} - S_i) \pmod m
$$
令
$$
D_i = S_{i+1} - S_i
$$
,则有:
$$
D_{i+1} \equiv a \cdot D_i \pmod m
$$
进而可以推导:
$$
D_{i+1} \cdot D_{i-1} \equiv a \cdot D_{i} \cdot D_{i-1} \equiv D_i^2 \pmod m
$$
即 m 必须整除
$$
(D_{i+1} \cdot D_{i-1} - D_i^2)
$$我们可以计算多个这样的行列式值
$$
T_i = D_{i+1} \cdot D_{i-1} - D_i^2
$$
,然后计算它们的最大公约数 (GCD),即可恢复 m。攻击乘数 a 和增量 c:
已知 m 后,利用关系
$$
D_{i+1} \equiv a \cdot D_i \pmod m
$$
,可求逆元得到 a:
$$
a \equiv D_{i+1} \cdot (D_i)^{-1} \pmod m
$$
求出 a 后,代入原方程求 c:
$$
c \equiv S_{i+1} - a \cdot S_i \pmod m
$$解密 Flag:
有了
$$
m, a, c
$$
和当前的最后一个状态
$$
S_5
$$
,我们就可以继续模拟 LCG 生成后续的密钥流,与C_flag异或即可还原 Flag。
解题脚本
1 | from functools import reduce |
运行结果
运行上述脚本,输出:
1 | [+] Recovered 6 states |
Flag:SHCTF{LLLLLLLLLLLLLLLCCCCCGGGGGGGGG_TGY%JgWOmAM6V5n55w3m*jcPJZjHO8E1VvzrGjT84tXS332D&o4GZe8%KKzEyAngmwwx9bp5dv_O4dPpOvMy1^hM}
evan
题目给了一张png图片,用binwalk扫了一下发现有个zip文件。
然后再用foremost提取了zip文件,发现需要密码。
在010editor里打开zip文件,发现有个文件叫flag.txt,猜测密码可能在这个文件里。
并且发现zip文件是伪加密的,数据区:504b030414000600,目录区:504b0102140014000900。
所以可以直接把数据区和目录区的加密标志去掉,改成正常的zip文件。
修改后就可以直接解压了,flag.txt的内容就是flag。
flag: SHCTF{Evan_1s_s0_h4nds0me!}
not_eight_length
题目分析
题目提供了一个 Python 脚本 task.py 以及输出的参数 n, e, c。
1. 加密逻辑分析
查看 task.py 中的关键代码:
1 | p = getPrime(512) |
这里 p 是一个 512 位的随机质数,而 q 是 p 之后的第二个质数。这意味着 p 和 q 非常接近。
在 RSA 算法中,如果两个因子 p 和 q 非常接近,那么它们的乘积 n 的平方根
$$
\sqrt{n}
$$
将非常接近这两个因子。具体来说,
$$
p \approx \sqrt{n}
$$
这种情况下,n 容易受到 Fermat 分解法 或简单的 平方根附近的线性搜索 攻击。
2. 解密逻辑
解密过程分为三步:
- 分解 n:计算
root = isqrt(n),然后在root附近向下搜索找到 p。 - RSA 解密:利用找到的 p 和 q 计算私钥 d,然后解密密文 c 得到明文整数 m。
- 解码明文:这是本题的 tricky 之处。
- 常规的
long_to_bytes(8位/字节) 无法得到有意义的字符串。 - 题目名称 “not_eight_length” 和提示 “并不是所有的题目都是8位哦” 暗示并非 8-bit编码。
- 将解密后的整数 $m$ 转换为二进制,发现其长度为 301 位。
- 尝试不同的位长,发现 $301 = 43 \times 7$,即每 7 位代表一个字符。
- 将二进制按照 7 位一组进行切割并转换为 ASCII 字符,即可得到 flag。
- 常规的
解题脚本 (solve.py)
1 | from math import isqrt |
Flag
运行脚本输出:
1 | Flag: SHCTF{99f4a238-9bd5-498a-b8ea-5cd243a36a19} |
古典也颇有韵味啊
题目信息
- 题目名称:古典也颇有韵味啊
- 密文:
bcin!guy zeui wh! wwps ce yryz ysex:wpurt{wc@xdii_u2frmt_cwkg_ktani0} - encode_key:
ABBAAABBABBAABABAABBABAAAAABBAAABAAABBAAAABAABAAAAAABAA - 提示:“你是维吉尼亚还是维多利亚?倒是有点共同点”
解题步骤
1. 分析 encode_key (培根密码)
观察 encode_key,它由字符 ‘A’ 和 ‘B’ 组成,且长度为 55。这符合 培根密码 (Bacon Cipher) 的特征,即每 5 个字符代表一个字母。
将 encode_key 分组如下:
1 | ABBAA ABBAB BAABA BAABB ABAAA AABBA AABAA ABBAA AABAA BAABA AABAA |
使用经典的培根密码表(I/J 合并,U/V 合并)进行映射:
ABBAA→ nABBAB→ oBAABA→ tBAABB→ v (在一些表中 u/v 共享)ABAAA→ iAABBA→ gAABAA→ eABBAA→ nAABAA→ eBAABA→ r (注:标准表中 BAABA 对应 T,但结合上下文,此处应理解为单词 Vigenere)AABAA→ e
解码得到的字符串为:notvigenere。
2. 识别加密算法 (Autokey Vigenere)
解析出的密钥是 notvigenere(意为“不是维吉尼亚”)。
题目提示“你是维吉尼亚还是维多利亚?”,且我们得到了“不是维吉尼亚”的暗示。这指向了 自动密钥密码 (Autokey Cipher)。
Autokey Vigenere 与普通 Vigenere 的区别在于:密钥用完后,它不会循环使用密钥,而是接上明文消息本身作为后续的密钥流。
3. 解密
使用 notvigenere 作为初始密钥,对密文进行 Autokey Vigenere 解密。
解密逻辑:
- 第 1 个字符:
c_1解密用k_1-> 得到p_1 - 第 2 个字符:
c_2解密用k_2-> 得到p_2
… - 当初始密钥用尽后,第 n 个字符的解密密钥变为
p_{n-len(key)}(即之前解密出的明文)。
解密脚本 (Python):
1 | def autokey_vigenere_decrypt(ciphertext, key): |
4. 结果
运行脚本得到的明文为:
1 | oops!you made it! here is your flag:shctf{cl@ssic_c2ypto_also_crypt0} |
Final Flag
1 | SHCTF{cl@ssic_c2ypto_also_crypt0} |
不止二维码
题目给了一个二维码图片,直接用QR-Resercher扫描,是一个假的flag,把图片拉到stegesolve里切换不同图层,发现还有三个二维码,用QR-Resercher扫描。


得到以下内容:FLAG_PART_1: SHCTF{55a23d24-FLAG_PART_2: ABBB/AABBB/AAAAA/BBBBB/ABBBBA/BBBBA/B/AABBB/ABBBFLAG_PART_3: MkZkbDg3ZlY3ZEQxalNGenQyZUFYT3E0NmRrTXFV
PART1是明文
PART2是莫斯电码,A代表划,B代表点,解码后得到:b705-4e7b (莫尔斯电码 B705-4E7B,统一转化为小写以匹配上下文)
PART3是Base混合多重解码:[ 解码4次 ] Base64 -> Base62 -> Base58 -> Base32混合解码结果:-942e-bdd}
flag: SHCTF{55a23d24-b705-4e7b-942e-bdd}
滴答滴答
题目给了一个音频文件,打开来听发现是SSTV(Slow Scan Television,慢扫描电视)信号。
安装虚拟声卡 Virtual Audio Cable,使用SSTV解码软件 MMSSTV 进行解码。
1 | #使用步骤: |
解码后得到一张图片,flag就在图片上。
flag: SHCTF{Radio_is_just_too_much_fun!}
薇薇安的美照
题目给了一张jpg照片,用010editor打开,发现文件尾有base64编码的字符串。
base64: MV84Xzc0XzlwXzdfOTJfMTZfNV8xOF84Xzc=
解码后得到:1_8_74_20_7_92_16_5_18_8_7,这是一个数字序列。
结合题目所提的:学了一天化学的Zero,决定去打打绝区零里,flag格式:SHCTF{**}记得flag是大写的呢
将这些数字按照元素周期表的原子序数对应的元素符号,得到flag:SHCTF{H_O_W_CA_N_U_S_B_AR_O_N}
提问前请先搜索
认真阅读
flag: SHCTF{dO_nOT_r3lY_0n_A1}
奇怪的数据
题目给了一个txt文件,观察后发现是图像的像素数据,且每个括号有三个数字,分别代表RGB三个通道的值。
将这些数据转换成图像,得到一张二维码图片。
解密脚本如下:
1 | import numpy as np |
运行脚本后,发现当重塑为 410 行, 410 列时,生成的图片是一个清晰的二维码。扫码得到base64:U0hDVEZ7VGgzX1F1ZXN0MW9uNV9BcmVfVG9vX0QxZmZpY3UxdCEhISF9
base64解码后得到flag:SHCTF{Th3_Quest1on5_Are_Too_D1fficu1t!!!!}
Office
题目分析
题目提供了一个 flag.docx 文件。由于 Word 文档本质上是 ZIP 压缩格式,我们可以解压或直接查看其内部结构来寻找线索。
解题步骤
1. 探索文件结构
查看 flag.docx 的内部文件,在 word/theme/ 目录下发现了一个非标准文件 alphabet。
读取 word/theme/alphabet 内容:
1 | +/0-6a-zA-Z7-9= |
这看起来像是一个压缩或简写的自定义 Base64 索引表。将其按照范围展开后如下:
1 | +/0123456abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ789 |
正好组成了 64 个字符,符合 Base64 编码表的特征。
2. 提取加密文本
查看 Word 文档的正文内容(位于 word/document.xml),提取出其中的文本:
1 | lRy1m2qYkmewkTqDrneCoTCQoUiFqm7zqoeRoT7DqDCAqm7QsTqRuT3PqjWUt5e7 |
3. 编写解密脚本
利用 Python 的 maketrans 和 translate 方法,将使用自定义码表的密文映射回标准 Base64 码表,然后进行标准解码。
1 | import base64 |
4. 获取 Flag
运行解密脚本得到最终 Flag:
1 | SHCTF{MS_Office_is_the_best_office_software.wps} |
hash1
题目分析
题目提供了一个 Python 脚本 hash1.py 和一个运行在 challenge.shc.tf:31800 的远程环境。
查看 hash1.py 的关键逻辑:
1 | msg = input(f"Give me both different apples (hex(apple1), hex(apple2)) : ") |
程序的逻辑非常明确:
- 要求用户输入两个用逗号分隔的字符串。
- 将这两个字符串作为十六进制解码为字节串
apple1和apple2。 - 检查 1:
apple1不能等于apple2(原文不同)。 - 检查 2:
hashlib.md5(apple1)必须等于hashlib.md5(apple2)(哈希值相同)。 - 如果满足上述条件,输出 flag。
漏洞原理
这道题利用的是 MD5 哈希碰撞(MD5 Collision)。MD5 是一种通过产生 128 位(16 字节)哈希值来验证数据完整性的算法。然而,MD5 已经被证明是不安全的,因为它容易受到碰撞攻击——即找到两个不同的输入数据,它们产生完全相同的 MD5 哈希值。
本题就是一个标准的验证 MD5 碰撞的题目。
解题过程
我们需要找到两个不同的 Hex 字符串,它们的 MD5 值相等。这些字符串在网络上有很多公开的例子(例如通过 fastcoll 工具生成的)。
这里选用一组经典的 MD5 碰撞数据:
- 数据 1 (Hex):
4dc968ff0ee35c209572d4777b721587d36fa7b21bdc56b74a3dc0783e7b9518afbfa200a8284bf36e8e4b55b35f427593d849676da0d1555d8360fb5f07fea2 - 数据 2 (Hex):
4dc968ff0ee35c209572d4777b721587d36fa7b21bdc56b74a3dc0783e7b9518afbfa202a8284bf36e8e4b55b35f427593d849676da0d1d55d8360fb5f07fea2
我们可以简单验证一下:
- 这两段数据在中间的几位上有所不同(
...a200a8...vs...a202a8...)。 - 它们的 MD5 哈希值都是
008ee33a9d58b51cfeb425b0959121c9。
Exploit 脚本 (solve.py)
1 | import socket |
Flag
运行脚本后,成功获取 Flag:
1 | SHCTF{CoN9ra7U14Tl0ns_BO7h_h45h1_@PPL3s_4re_VerY_d31iCIOUS_IoL} |
Hash2
题目分析
题目提供了一个 Python 脚本 hash2.py,要求用户输入两个 hex 编码的字符串(apple1 和 apple2)。
服务端会对这两个字符串进行以下检查:
- 长度限制:长度必须大于 16 字节。
1
2if len(apple1) <= 16 or len(apple1) <= 16: # 注意:原题这里可能有笔误,但意图是检查长度
print(f"Both apples are too small") - 字符集限制(前缀):两个字符串的前 16 个字节必须全部在
string.ascii_letters + string.digits(即大小写字母和数字)范围内。1
2elif not all(ch in table for ch in apple1[:16]) or not all(ch in table for ch in apple2[:16]):
print(f"No, both apples are too ordinary") - 内容差异:两个字符串不能完全相同。
1
2elif apple1 == apple2:
print(f"Oh snap, both apples are exactly the same") - 哈希碰撞:两个字符串的 MD5 哈希值必须相同。
1
2elif hash_apple1 != hash_apple2:
print(f"Oh no, they taste different")
如果满足所有条件,即可获得 Flag。
解题思路
这是一个典型的 MD5 前缀碰撞(Chosen-Prefix Collision) 问题。我们需要构造两个不同的字节序列,使它们拥有相同的 MD5 哈希值,并且都以满足特定条件(字母数字)的前缀开头。
手动构造 MD5 碰撞极其困难,通常使用 Marc Stevens 开发的工具 fastcoll。fastcoll 允许我们指定一个共同的前缀(Initial Value/State),然后它会生成两个不同的后缀块(128字节),使得拼接后的两个完整数据的 MD5 哈希值相同。
攻击步骤
- 构造前缀:我们需要一个长度为 16 字节且全是字母数字的字符串。例如:
0123456789abcdef。 - 生成碰撞:使用
fastcoll基于该前缀生成两个碰撞文件。 - 提交 Payload:读取生成的文件内容,转换为 Hex 字符串提交给服务器。
复现过程
1. 准备前缀文件
创建一个名为 prefix.txt 的文件,写入 16 字节的合法前缀。
1 | echo -n "0123456789abcdef" > prefix.txt |
2. 使用 fastcoll 生成碰撞
下载 fastcoll 工具并在终端运行:
1 | ./fastcoll -p prefix.txt -o col1.bin col2.bin |
该命令会生成 col1.bin 和 col2.bin。这两个文件的结构如下:
- 前 16 字节:是我们指定的
0123456789abcdef(满足条件2)。 - 后续 128 字节:由 fastcoll 生成的碰撞块。
- 总长度:144 字节(满足条件1:> 16)。
- 差异性:fastcoll 保证两个文件内容不同(满足条件3)。
- 哈希值:MD5 算法的特性保证两个文件哈希相同(满足条件4)。
3. Exploitation 脚本
编写 Python 脚本自动读取并发送 Payload:
1 | import socket |
运行脚本即可获得 Flag。
椭圆曲线
题目分析
题目给出了两个文件:task.py(加密脚本)和 data.json(泄露的数据)。
1. 代码逻辑分析
在 task.py 中,有两个主要的函数涉及 flag (secret_data) 的处理:
ver_length函数:1
2
3
4
5
6def ver_length(secret_data):
p = getPrime(256)
secret = bytes_to_long(secret_data)
start = secret - 19 * p
end = secret + 21 * p
return start, end这个函数生成了一个 256 位的随机质数
p,然后根据secret(flag 的整数形式)计算了start和end。init函数:1
2
3
4
5
6
7def init(secret_data, msg1, msg2):
# ... (标准的 ECDSA 签名过程)
k = random.getrandbits(order.bit_length())
# ...
signature1 = priv_key.sign(hash1, k)
signature2 = priv_key.sign(hash2, k)
return signature1, signature2, k, secret这里使用 ECDSA 对两个消息进行了签名,并且复用了随机数 k。这通常是一个严重的 ECDSA 漏洞(Nonce Reuse Attack),可以通过两个签名恢复密钥。
2. 漏洞选择
虽然题目通过 init 函数故意展示了一个 ECDSA 随机数复用的漏洞,但我们仔细观察 ver_length 函数,会发现一个更简单、更直接的代数漏洞。
ver_length 泄露了 start 和 end,它们与 secret 和 p 满足以下线性关系:
$$
\begin{cases}
start = secret - 19 \times p \
end = secret + 21 \times p
\end{cases}
$$
这是一个简单的二元一次方程组,我们可以直接解出 p 和 secret,而完全不需要处理复杂的椭圆曲线数学。
解题思路
消去 secret:
用第二个方程减去第一个方程:
$$
end - start = (secret + 21p) - (secret - 19p)
$$
$$
end - start = 21p + 19p = 40p
$$求解 p:
$$
p = \frac{end - start}{40}
$$恢复 secret (flag):
将求得的p代入任意一个方程:
$$
secret = start + 19 \times p
$$将整数转换为 flag 字符串。
解题脚本 (Solve Script)
1 | import json |
运行结果
运行上述脚本,直接得到 Flag:
1 | [+] Recovered Flag: SHCTF{205436e5-d598-4859-a237-d3f40e7ed45b} |
总结
这就是所谓的 “Crypto” 中常见的障眼法。题目虽然给出了显眼的 ECDSA 环境和 Nonce Reuse 漏洞,但 flag 的泄露其实通过非常基础的代数运算就能完成。在做题时,优先检查最简单的数学关系往往能事半功倍。
资源平权!
题目分析
这道CTF misc题目给的ZIP包使用了ZipCrypto(传统的老式ZIP加密方式)
- flag.exe 是加密的(ZipCrypto + Store方式,加密标记为+)
- 资源使用说明.txt 是明文存储(Store,无加密)
解题步骤
用 bkcrack 工具进行已知明文攻击
准备已知明文(plain)
flag.exe 未加密时的开头几乎一定是这样(前几十字节):
前2字节:4D 5A(即MZ)
通常前几十字节是标准的DOS stub(很多编译器生成的都一样)
最保险的前12–16字节示例(十六进制):4D 5A 90 00 03 00 00 00 04 00 00 00 FF FF 00 00,可以创建一个纯文本文件plain_head.bin,用十六进制编辑器(如HxD、010 Editor、ImHex)填入上面内容(或更多字节),保存为二进制文件。
如果有标准的hello world.exe或其他PE文件,可以直接截取它的前几十字节作为plain(只要和目标exe的编译环境类似就行)。运行 bkcrack 破解内部密钥
打开命令行(cmd/PowerShell/Terminal),进入bkcrack所在目录,执行类似下面命令:1
.\bkcrack.exe -C "SHCTF2026_资源平价!.zip" -c flag.exe -p plain_head.bin -o 0
参数解释:
-C:加密的ZIP文件名(带路径也行)
-c:要攻击的加密文件在ZIP里的名字(这里是 flag.exe)
-p:你准备的已知明文文件(二进制格式)
-o 0:明文相对于文件开头的偏移(通常从0开始,因为PE头就是开头)

密钥:601010514cba82cb48eac20c用恢复的密钥直接解密文件
找到密钥后,运行:1
.\bkcrack.exe -C "SHCTF2026_资源平价!.zip" -c flag.exe -k xxxx xxxx xxxx -d decrypted_flag.exe
-k 后面填刚才得到的3个密钥
-d 指定解密后输出的文件名

解密出来的 decrypted_flag.exe 就是明文exe了!运行 decrypted_flag.exe 获取 Flag
双击运行 decrypted_flag.exe,或者在命令行中执行它,输出 Flag:1
2Hello and welcome,CTFer!
The flag is: SHCTF{002c158f-b4d2-4e14-bbbb-b5141bca8cb9}