资讯动态

CTFshow CRYPTO1/2/3入门精讲:编码识别、古典密码与异或逆向

发布时间:2026/9/25 1:26:49 来源:尧图企业网站定制
1. 从三道入门密码题说起为什么CRYPTO1/2/3值得反复拆CTFshow的CRYPTO系列前三题在圈子里基本算是密码学方向的新手村三连。很多人第一次接触CTF的crypto分类就是从这三道题开始的。它们看起来简单但真正把每一道题的思路吃透能帮你建立起一套完整的密码题解题直觉——这种直觉比记住某个脚本重要得多。我见过太多人做这三道题的方式是搜题解、复制脚本、跑出flag、提交、下一题。这样做当然能拿分但等到CRYPTO4、CRYPTO5难度上来之后立刻卡住因为脑子里没有形成看到密文→判断加密方式→选择攻击手段的链路。这三道题的价值恰恰在于它们分别对应了密码学入门阶段最核心的三类问题编码与加密的区分、古典密码的识别与破解、简单数学关系下的逆向推导。这篇文章我会把CRYPTO1、2、3三道题从题目特征、识别思路、原理推导到脚本实现完整拆一遍重点不是给你一个能跑的脚本而是告诉你我在看到这类题目时脑子里在想什么。适合刚入门crypto方向、或者做了题但没完全理解原理的朋友。如果你已经能独立秒掉这三道题也可以看看我在每道题后面补充的延伸思考那些是真正区分新手和老手的地方。2. CRYPTO1当一串乱码摆在面前先别急着写脚本2.1 题目给出的信息长什么样CRYPTO1的典型形式是给你一段看起来像乱码的字符串比如一串大小写字母加数字的组合或者一段Base64风格的文本。题目本身几乎不给额外提示就一个附件或者一行密文。很多人第一反应是这是什么加密然后开始瞎试各种解密工具。这里有个关键认知CTF里的crypto题第一步永远是判断这到底是编码还是加密。编码是可逆的、无密钥的、公开规则的转换比如Base64、Hex、URL编码加密是需要密钥或者需要破解数学难题的。CRYPTO1这个难度级别大概率是编码问题而不是真正的加密。2.2 识别编码的三个观察点我判断一段文本是什么编码通常看三个地方字符集范围只含A-Za-z0-9/且长度是4的倍数基本就是Base64只含0-9A-Fa-f且长度为偶数是Hex含%后跟两位十六进制是URL编码。结尾特征Base64经常以或结尾做填充Base32用填充且字符集是大写字母加2-7。长度规律Base64编码后长度约为原文的4/3Hex是2倍。拿CRYPTO1常见的密文举例如果给你的是类似Y3Rmc2hvd3t...这样的串Y3R开头解码出来是ctf这几乎可以确定是Base64。因为ctfshow{这个flag格式的Base64编码开头是固定的这是经验积累出来的指纹。2.3 Base64解码的完整操作与原理Base64的原理是把每3个字节24位拆成4个6位的组每个6位值映射到一张64字符的表上。所以解码就是反过来每4个字符还原成3个字节。理解这个原理的意义在于当你遇到Base64变种比如换表、去掉填充、URL安全的Base64用-和_替代和/时你能自己改脚本而不是干瞪眼。Python里最直接的方式import base64 cipher Y3Rmc2hvd3t...省略... # 补全填充防止长度不对报错 cipher * (-len(cipher) % 4) plain base64.b64decode(cipher) print(plain.decode(utf-8, errorsignore))命令行下更快echo Y3Rmc2hvd3t...省略... | base64 -d注意如果解码出来还是乱码别急着放弃很可能这是套娃——Base64解出来是HexHex再转ASCII才是明文。CTF里多层编码非常常见CRYPTO1有时就会套两层。2.4 我在CRYPTO1上踩过的坑第一个坑是填充问题。有些题目的Base64故意去掉了结尾的直接b64decode会抛binascii.Error: Incorrect padding。解决办法就是上面那行cipher * (-len(cipher) % 4)这是我最常用的补填充写法比手动数长度靠谱。第二个坑是把编码当加密。有次我看到一串字符直接上了CyberChef的Magic功能结果它给我推荐了一堆错误的解密方式浪费了十几分钟。后来我养成习惯先用眼睛判断字符集再动手。CyberChef的Magic适合完全没头绪的时候兜底但不应该是第一选择。第三个坑是忽略字符集细节。比如一段文本里同时出现了和/那基本锁定标准Base64如果出现的是-和_那是URL-safe Base64Python里要用base64.urlsafe_b64decode。这两个函数不通用用错了就报错或者解出乱码。3. CRYPTO2古典密码的识别靠的是统计直觉3.1 从密文形态判断古典密码类型CRYPTO2通常是古典密码常见的有凯撒、栅栏、维吉尼亚、培根、摩斯这几类。判断依据主要是密文的长相密文特征可能的密码类型全是字母长度不变字母频率接近正常英文凯撒、仿射、维吉尼亚全是字母但字母顺序被打乱栅栏、列移位只有两种字符如A/B培根密码只有.和-或类似符号摩斯密码字母被替换成数字或其他符号替换密码、键盘密码CRYPTO2这个难度凯撒和栅栏出现的概率最高。凯撒密码的特点是字母频率分布和明文一致只是整体平移了。所以如果你把密文做个字母频率统计发现e对应的字母频率最高但位置不对那大概率是凯撒。3.2 凯撒密码的暴力破解思路凯撒密码只有25种可能的位移0位移不算所以最省事的办法就是全试一遍。但25个结果里怎么快速找到对的那个看有没有ctfshow{或者可读的英文单词。def caesar_bruteforce(cipher): for shift in range(26): result for ch in cipher: if ch.isalpha(): base ord(A) if ch.isupper() else ord(a) result chr((ord(ch) - base - shift) % 26 base) else: result ch print(fshift{shift}: {result}) caesar_bruteforce(密文放这里)跑出来一眼扫过去哪个像人话哪个就是答案。这里有个小技巧如果密文里保留了{}和_这些非字母字符那它们是不参与位移的脚本里要判断isalpha()否则会把flag格式破坏掉。3.3 栅栏密码的分栏逻辑栅栏密码是把明文按固定栏数分组后按列读出。比如明文ctfshow2栏加密先写成两行ctf和sho实际是按顺序分再按列读。破解的关键是枚举栏数因为栏数通常不会太大2到10之间。def rail_fence_decode(cipher, rails): # 构造栅栏的读取顺序 pattern list(range(rails)) list(range(rails-2, 0, -1)) cycle len(pattern) # 计算每个位置属于哪一行 rows [[] for _ in range(rails)] idx 0 for i in range(len(cipher)): rows[pattern[i % cycle]].append(cipher[i]) # 按行拼接后按原顺序读出 result [] row_idx [0] * rails for i in range(len(cipher)): r pattern[i % cycle] result.append(rows[r][row_idx[r]]) row_idx[r] 1 return .join(result) for r in range(2, 11): print(r, rail_fence_decode(密文, r))栅栏密码有个容易搞混的点加密时是按行写、按列读还是按列写、按行读不同资料定义不一样。我的经验是两种都试看哪个出明文。CTF题目不会在这上面为难你但你自己写脚本时要清楚自己实现的是哪一种。3.4 古典密码题的通用排查流程做了几十道古典密码题之后我总结出一个固定流程基本能覆盖CRYPTO2这个难度看字符集只有字母有数字有特殊符号先分类。数字母频率频率分布接近英文→凯撒/维吉尼亚分布均匀→可能是栅栏或替换。试凯撒全位移25个结果扫一遍找可读文本。试栅栏枚举栏数2到10栏全试。看是否有分组特征比如每5个字符一组可能是培根有.和-是摩斯。上工具兜底CyberChef、quipqiup在线频率分析作为最后手段。提示quipqiup这个网站在做单表替换密码时非常好用把密文粘进去它能自动做频率分析给出候选明文。但注意它需要联网比赛环境不一定能用所以核心方法还是要自己掌握。3.5 一个容易被忽略的细节大小写和空格古典密码题里大小写和空格的处理方式会直接影响解密结果。有些题目加密时把空格去掉了解密后你需要自己根据语义断句有些题目保留大小写那凯撒位移时大小写要分别处理。我遇到过一道题密文全大写我按小写处理结果解出来全是错的排查了半天才发现是大小写的问题。所以脚本里isupper()和islower()的判断一定要写对。4. CRYPTO3当题目开始涉及数学关系4.1 CRYPTO3的典型形态到了CRYPTO3题目通常不再是单纯的编码或古典密码而是开始涉及简单的数学运算。常见形式有给一个等式让你求未知数、给一段用异或加密的密文、或者简单的模运算。这个阶段是通往RSA等现代密码的过渡。异或XOR是CRYPTO3里出现频率最高的考点。原因很简单异或运算可逆a ^ b c则c ^ b a而且实现简单很适合出成入门题。4.2 异或加密的原理与破解异或的核心性质是自反性同一个值异或两次会还原。如果题目用单字节密钥对明文逐字节异或那破解方法就是枚举256个可能的密钥看哪个解出来是可读文本。def xor_bruteforce(cipher_bytes): for key in range(256): result bytes([b ^ key for b in cipher_bytes]) # 简单判断是否可打印 if all(32 c 127 for c in result): print(fkey{key}: {result.decode()}) # 假设密文是十六进制字符串 cipher_hex 1a2b3c... cipher_bytes bytes.fromhex(cipher_hex) xor_bruteforce(cipher_bytes)如果密钥是多字节的那就需要知道密钥长度。判断密钥长度有个经典方法把密文按可能的密钥长度分组对每组做重合指数分析。不过CRYPTO3这个难度密钥基本都是单字节或者题目会直接告诉你密钥。4.3 从异或到已知明文攻击异或题里有个非常实用的技巧叫已知明文攻击。因为flag格式是固定的ctfshow{如果你知道密文开头对应的明文直接异或就能得到密钥的前几个字节。cipher bytes.fromhex(密文hex) known bctfshow{ key bytes([c ^ k for c, k in zip(cipher, known)]) print(推测密钥:, key)这个方法在CTF里屡试不爽因为flag格式固定是出题人给我们的免费信息。很多看起来复杂的异或题用已知明文攻击几行代码就出来了。4.4 模运算题的解题思路如果CRYPTO3涉及模运算通常是这种形式给你a、b、m求满足a * x ≡ b (mod m)的x。这本质上是求模逆元的问题。求解模逆元用扩展欧几里得算法def egcd(a, b): if b 0: return a, 1, 0 g, x, y egcd(b, a % b) return g, y, x - (a // b) * y def mod_inverse(a, m): g, x, _ egcd(a, m) if g ! 1: return None # 逆元不存在 return x % m # 解 a * x ≡ b (mod m) a, b, m 3, 7, 11 inv mod_inverse(a, m) x (b * inv) % m print(x)Python 3.8之后其实有内置的pow(a, -1, m)直接求逆元但理解扩展欧几里得的原理对后面做RSA题至关重要所以我建议手写一遍。4.5 CRYPTO3阶段要建立的思维习惯做完CRYPTO3你应该建立起一个重要的思维习惯看到密文先问加密函数是什么然后想这个函数的逆运算是什么。异或的逆是异或本身模乘的逆是模逆元凯撒的逆是反向位移。所有密码题的本质都是找到加密函数的逆。这个思维习惯建立起来之后后面遇到RSA加密是模幂逆运算涉及模逆元和欧拉定理、AES对称加密逆运算需要密钥这些更复杂的题你就知道该往哪个方向思考了。5. 三道题串起来看一套可复用的crypto入门方法论5.1 从识别到破解的决策树把CRYPTO1、2、3的经验整合起来我实际做题时的决策流程是这样的看密文形态是纯编码Base64/Hex/URL还是需要密钥的加密纯编码直接解码注意多层套娃和填充问题。古典密码数字母频率试凯撒全位移试栅栏枚举栏数看分组特征。数学运算判断是异或还是模运算异或先试已知明文攻击模运算求逆元。都不像上CyberChef的Magic或者quipqiup兜底。这个决策树不是死的但它能保证你在没思路的时候有个系统性的排查方向而不是瞎试。5.2 工具链的取舍我常用的工具就三个Python脚本主力灵活、CyberChef在线适合快速试编码、quipqiup频率分析古典密码专用。工具不在多在于你知道什么时候用哪个。Python脚本是必须自己会写的因为比赛环境不一定有网而且很多题目需要定制化的处理逻辑现成工具覆盖不了。注意不要过度依赖在线工具。我见过有人做古典密码题第一反应是打开某个在线解密网站结果网站不支持题目用的变种卡了半天。自己写脚本虽然慢一点但可控性最强。5.3 新手最容易犯的三个错误第一个错误是跳过识别直接暴力。看到密文就上工具全试一遍效率极低。正确的做法是先花30秒判断类型再动手。第二个错误是不理解原理只记脚本。这样做的后果是题目稍微变一下就不会了。比如凯撒密码换成仿射密码y ax b如果你只记了凯撒的脚本仿射就得重新学但如果你理解了位移的本质仿射只是多了一个乘法系数思路是通的。第三个错误是忽略题目给的提示。CTF题目经常在描述里藏提示比如小明喜欢简单的东西可能暗示是简单替换古老的加密方式暗示古典密码。这些提示能帮你省很多时间。5.4 从这三道题往后该怎么练CRYPTO1/2/3做完之后下一步建议按这个顺序推进先练RSA的基础题小指数攻击、共模攻击、低加密指数广播这是crypto方向的核心再练流密码和分组密码的基础题最后接触椭圆曲线和格密码这些进阶内容。每做一道题养成写题解的习惯重点记录我是怎么识别出加密方式的和我卡在哪里、怎么突破的。这两点比记录脚本本身有价值得多。我自己就是靠积累这些识别经验从看到密文一脸懵到后来能快速判断出题人的意图。6. 一些实战中的碎碎念关于CRYPTO1我想再强调一次多层编码的问题。很多新手解出第一层Base64看到还是乱码就以为做错了其实那只是中间层。我的习惯是解一层看一眼如果结果还是看起来像编码的字符集就继续解直到出现可读文本或者flag格式。关于CRYPTO2频率分析是古典密码的万能钥匙。哪怕你判断不出具体是哪种密码先做频率统计总没错。英文里e出现频率最高约12.7%t次之a、o、i、n紧随其后。如果密文里某个字母频率明显偏高那它很可能对应明文的e。关于CRYPTO3已知明文攻击是异或题的杀手锏。只要flag格式固定你就有已知明文就能推出密钥。这个思路在后面做很多流密码题时都能复用。最后分享一个我自己的习惯每道题做完之后我会把密文、解题思路、脚本整理到一个本地笔记里按题型分类。做了几十道之后这个笔记就成了我自己的题解库遇到类似的题直接翻笔记比重新想快得多。CTFshow的CRYPTO系列题目质量不错很适合作为这个笔记库的起点。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑