CTFCrypto实战:精选题目Writeup与完整复现

admin 2026-09-06 04:36:00 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 这篇文章系统梳理了CTF中密码学题型的分类与解题思路,涵盖古典密码的统计破解方法、现代密码算法的常见实现漏洞利用,以及协议侧信道攻击等,并通过栅栏密码、Vigenère、babyxor和babyaes四个具体题目展示了从密文到明文的完整解题流程,对CTF参赛者具有实用参考价值。 综合评分: 85 文章分类: CTF,漏洞分析,安全工具


CTF Crypto实战:精选题目Writeup与完整复现

原创

小话安全 小话安全

小话安全

2026年9月3日 16:16 山东

在小说阅读器读本章

去阅读

在公众号小说中沉浸阅读

CTF中的Crypto(密码学)题型花样繁多,但核心都是考察你识别密码体制、发现薄弱环节、逆向还原信息的能力。下面我梳理了CTF中Crypto的常见题型,方便你快速建立知识框架。

🏛️ 古典密码:语言与统计的博弈

古典密码是CTF中的基础题,通常出现率很高,是新手必须拿下的送分题。它们的安全性主要依赖“人看不出规律”,因此解题核心是利用语言统计特征和格式约束进行破解。

  • 编码类:本质是格式转换,并非严格加密。典型例子有:

  • Base64:由 A-Za-z0-9+/ 组成,常以 = 结尾。

  • Hex:仅由 0-9a-f 组成。

  • URL编码:特征为 % 后跟两个十六进制字符。

  • 此外还有摩斯密码、猪圈密码、培根密码等。

  • 替换密码:将明文中的字母按规则替换成其他字母。

  • 凯撒密码:最简单的移位密码,尝试所有25种偏移即可爆破。

  • ROT13:凯撒密码的一种特例,偏移量为13。

  • 维吉尼亚密码:使用一个重复的关键词进行多表替换。破解关键是先确定密钥长度(可用Kasiski测试或重合指数法),然后对每组进行频率分析。

  • 单表替换密码:建立一个一对一的替换表。解法是利用词频分析或利用已知明文(如flag{)进行约束求解。

  • 置换密码:不改变字母本身,只改变字母的位置。

  • 栅栏密码:将明文按“Z”字形排列后按行读取。解法是尝试不同的栅栏层数。

  • 列移位密码:按列写入,按行读出。解法是尝试不同的列数和排列顺序。

⚙️ 现代密码:算法与实现的缺陷

现代密码算法(如AES、RSA)本身通常是安全的,CTF题目更多是考察算法在具体实现或参数选择上的漏洞。

  • 对称加密:加解密使用相同密钥。

  • ECB模式:相同的明文块会生成相同的密文块。漏洞是可以通过替换密文块来篡改明文,且无需知道密钥。

  • CBC模式:常见漏洞包括Padding Oracle攻击,利用服务器对填充错误的反馈来逐字节恢复明文;以及IV比特翻转攻击,通过修改IV来改变第一个明文分组。

  • AES:重点考察其不同工作模式的缺陷。

  • RC4:一种流密码。最大的漏洞是密钥重用,如果两次加密使用了相同的密钥流,可以通过两次密文异或得到明文的异或值。

  • 非对称加密:加解密使用不同的公钥和私钥。

  • 模数分解:当模数 n 较小时,可直接用工具(如factordb)分解得到 p 和 q

  • 低加密指数攻击:当公钥指数 e 很小(如e=3)时,若明文 m 也较小,则 c = m^e < n,直接对密文 c 开 e 次方即可。

  • 低解密指数攻击:当私钥指数 d 较小时,可使用Wiener攻击。

  • 共模攻击:同一明文 m,使用相同的模数 n 但不同的公钥指数 e1e2 加密。当 e1 和 e2 互质时,可通过扩展欧几里得算法恢复明文。

  • 素数选取不当:如果 p 和 q 非常接近,可使用费马分解法;如果 p-1 或 q-1 只有小质因子,可使用Pollard’s p-1分解法。

  • RSA:CTF中的绝对核心。常见攻击点都围绕着数学上的“偷懒”或“疏忽”:

  • 哈希函数:将任意长度的数据映射为固定长度的摘要。

  • 常见考点:MD5和SHA-1的碰撞攻击(找到两个不同消息但哈希值相同);以及简单的破解,即查询在线彩虹表或使用字典攻击。

  • 随机数:密码学中随机数的质量至关重要。

  • 常见考点:LCG(线性同余生成器)和MT19937(梅森旋转算法)等伪随机数生成器(PRNG)的种子恢复或预测。如果随机数种子被重用或可被预测,整个加密体系将崩溃。

🕵️‍♂️ 协议与实现漏洞:利用“信息泄露”

这类题目不直接考数学或算法,而是考察你能否敏锐地捕捉到系统在交互过程中泄露的“蛛丝马迹”。

  • 侧信道攻击:利用密码系统运行时产生的物理或时间信息来破解密钥。

  • 时间攻击:通过比较不同输入的解密时间来推断密钥或明文信息。

  • Padding Oracle攻击:属于利用错误回显的侧信道攻击。

  • 协议设计缺陷:利用密钥交换、签名验证等流程中的逻辑漏洞。例如,服务端在签名或解密前对用户输入缺乏校验,导致攻击者可以伪造数据。

🧩 综合与新兴题型:边界在不断拓展

随着密码学的发展,CTF的题型也在不断更新。

  • 椭圆曲线密码(ECC):基于椭圆曲线数学的一种非对称加密,相比RSA有密钥更短的优势。考点包括无效曲线攻击、ECDSA签名中随机数k重用等。
  • 后量子密码:随着量子计算的发展,一些能抵抗量子计算攻击的算法开始出现,如基于格的密码(LWE问题)。
  • 密码学与其它方向结合:Crypto题目常与Misc(杂项)、Web、Reverse等方向结合,例如将flag隐藏在图片中(隐写术)、或通过Web接口进行Padding Oracle攻击。

题目一 栅栏密码

题目二  Vigenère

pqcq{qc_m1kt4_njn_5slp0b_lkyacx_gcdy1ud4_g3nv5x0}

当然可以!下面详细解释如何获得密钥。


1. 密文与格式

密文:

pqcq{qc_m1kt4_njn_5slp0b_lkyacx_gcdy1ud4_g3nv5x0}

通常 CTF flag 的格式为 flag{…},所以明文开头很可能是:

flag{

2. 已知明文攻击(Known Plaintext Attack)

因为 flag{ 是已知的,我们可以用它与密文开头的 pqcq{ 逐字符比较,推导出加密所用的密钥流(Vigenère 密钥的循环)。

Vigenère 加密规则(仅对字母生效):

  • 密文字母 = (明文字母 + 密钥字母) mod 26
  • 其他字符(数字、下划线、花括号等)保持原样。

于是我们从第一个字母开始:

| 位置 | 明文字母 | 密文字母 | 偏移量(密文 – 明文 mod 26) | 对应密钥字母 | | — | — | — | — | — | | 1 | f (5) | p (15) | 15 – 5 = 10 | k (10) | | 2 | l (11) | q (16) | 16 – 11 = 5 | f (5) | | 3 | a (0) | c (2) | 2 – 0 = 2 | c (2) | | 4 | g (6) | q (16) | 16 – 6 = 10 | k (10) |

得到的偏移序列是10, 5, 2, 10,即字母 k, f, c, k。

因为 Vigenère 密钥是循环使用的,前四个字符对应的密钥应为 k, f, c, k,这意味着密钥周期为 3,实际密钥为 kfc(第 4 个字符回到第一个密钥字母 k)。


3. 验证密钥

用密钥 kfc 对整个密文进行解密(仅作用于字母,其余字符不变):

  • 对每个字母 cipher,计算 plain = (cipher - key) mod 26

解密后得到:

flag{la_c1fr4_del_5ign0r_giovan_batt1st4_b3ll5s0}

完全符合语法和含义(“la cifra del signor Giovan Battista Bellaso” 是 Vigenère 密码的历史背景)。


题目三 babyxor

from&nbsp;secret&nbsp;import&nbsp;*
ciphertext = []
for&nbsp;f&nbsp;in&nbsp;flag:&nbsp; &nbsp; ciphertext.append(f ^ key)
print(bytes(ciphertext).hex())# e9e3eee8f4f7bffdd0bebad0fcf6e2e2bcfbfdf6d0eee1ebd0eabbf5f6aeaeaeaeaeaef2

爆破脚本

#from secret import *
#ciphertext = []
#for f in flag:&nbsp; &nbsp;&nbsp;#ciphertext.append(f ^ key)
#print(bytes(ciphertext).hex())# e9e3eee8f4f7bffdd0bebad0fcf6e2e2bcfbfdf6d0eee1ebd0eabbf5f6aeaeaeaeaeaef2
import&nbsp;binascii
def&nbsp;single_byte_xor_bruteforce(hex_str):&nbsp; &nbsp;&nbsp;"""&nbsp; &nbsp; 对十六进制密文进行单字节异或暴力破解。&nbsp; &nbsp; 参数: hex_str - 十六进制字符串(如 "e9e3...")&nbsp; &nbsp; 返回: 所有候选明文的列表,每个元素为 (密钥, 明文)&nbsp; &nbsp; """&nbsp; &nbsp;&nbsp;# 将十六进制转换为字节&nbsp; &nbsp;&nbsp;try:&nbsp; &nbsp; &nbsp; &nbsp; cipher =&nbsp;bytes.fromhex(hex_str.strip())&nbsp; &nbsp;&nbsp;except&nbsp;ValueError:&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print("无效的十六进制字符串")&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;[]
&nbsp; &nbsp; candidates = []
&nbsp; &nbsp;&nbsp;for&nbsp;key&nbsp;in&nbsp;range(256):&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# 对每个字节异或 key&nbsp; &nbsp; &nbsp; &nbsp; plain =&nbsp;bytes([b ^ key&nbsp;for&nbsp;b&nbsp;in&nbsp;cipher])
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# 检查是否全部为可打印 ASCII(空格 ~ 波浪号)或常见控制字符&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# 可以根据需求放宽条件,例如允许换行、回车等&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;all(0x20&nbsp;<= c <=&nbsp;0x7e&nbsp;or&nbsp;c&nbsp;in&nbsp;(0x0a,&nbsp;0x0d)&nbsp;for&nbsp;c&nbsp;in&nbsp;plain):&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; candidates.append((key, plain.decode('ascii', errors='ignore')))
&nbsp; &nbsp;&nbsp;return&nbsp;candidates
if&nbsp;__name__ ==&nbsp;"__main__":&nbsp; &nbsp;&nbsp;# 示例密文(来自题目)&nbsp; &nbsp; hex_data =&nbsp;"e9e3eee8f4f7bffdd0bebad0fcf6e2e2bcfbfdf6d0eee1ebd0eabbf5f6aeaeaeaeaeaef2"
&nbsp; &nbsp; results = single_byte_xor_bruteforce(hex_data)
&nbsp; &nbsp;&nbsp;if&nbsp;not&nbsp;results:&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print("未找到完全可打印的候选明文。")&nbsp; &nbsp;&nbsp;else:&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"找到&nbsp;{len(results)}&nbsp;个候选密钥:")&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;for&nbsp;key, text&nbsp;in&nbsp;results:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"密钥 0x{key:02X}&nbsp;({key}) ->&nbsp;{text}")

题目四 babyaes

from&nbsp;Crypto.Cipher&nbsp;import&nbsp;AESimport&nbsp;osiv = os.urandom(16)key = os.urandom(16)my_aes = AES.new(key, AES.MODE_CBC, iv)flag =&nbsp;open('flag.txt',&nbsp;'rb').read()flag += (16&nbsp;-&nbsp;len(flag) %&nbsp;16) *&nbsp;b'\x00'c = my_aes.encrypt(flag)print(c)print(iv)print(key)
'''b'C4:\x86Q$\xb0\xd1\x1b\xa9L\x00\xad\xa3\xff\x96 hJ\x1b~\x1c\xd1y\x87A\xfe0\xe2\xfb\xc7\xb7\x7f^\xc8\x9aP\xdaX\xc6\xdf\x17l=K\x95\xd07'b'\xd1\xdf\x8f)\x08w\xde\xf9yX%\xca[\xcb\x18\x80'b'\xa4\xa6M\xab{\xf6\x97\x94>hK\x9bBe]F''''

解密脚本

from&nbsp;Crypto.Cipher import AES
# 从输出中复制的密文、IV 和密钥(注意转义)c = b'C4:\x86Q$\xb0\xd1\x1b\xa9L\x00\xad\xa3\xff\x96 hJ\x1b~\x1c\xd1y\x87A\xfe0\xe2\xfb\xc7\xb7\x7f^\xc8\x9aP\xdaX\xc6\xdf\x17l=K\x95\xd07'iv = b'\xd1\xdf\x8f)\x08w\xde\xf9yX%\xca[\xcb\x18\x80'key = b'\xa4\xa6M\xab{\xf6\x97\x94>hK\x9bBe]F'
# 创建 AES CBC 解密器aes = AES.new(key, AES.MODE_CBC, iv)
# 解密plaintext_padded = aes.decrypt(c)
# 去掉零填充(加密时末尾补了 \x00)plaintext = plaintext_padded.rstrip(b'\x00')
# 输出结果print(plaintext.decode('utf-8', errors='ignore'))

免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:小话安全 小话安全 小话安全《CTF Crypto实战:精选题目Writeup与完整复现》

评论:0   参与:  0