
1. 从一道“看起来很简单”的题说起如果你刚开始接触CTFCapture The Flag网络安全夺旗赛大概率会在某个深夜被一道密码学题目卡住。题目描述只有一句话附件是一个txt文件打开一看里面是一串乱七八糟的字符或者一个Python脚本又或者是一张看起来像乱码的图片。你盯着屏幕心里想这到底是什么东西我最初接触CTF密码学方向的时候就是这种感觉。明明每个字母都认识连在一起就完全不知道从哪里下手。后来打得多了才慢慢摸清楚这类题目的套路——它们其实有非常清晰的分类和解题路径只是没有人把这条路径完整地讲给你听。这篇内容就是把我这些年做CTF密码学题目的经验整理出来从最基础的编码识别到古典密码的破解思路再到现代密码学中常见的攻击场景最后聊一聊工具链和实战心态。不管你是刚入门的新手还是已经做过几道题但总觉得不成体系应该都能从中找到对自己有用的东西。密码学在CTF里是一个很特殊的方向。它不像Web那样有直观的页面交互也不像Pwn那样需要深入理解内存布局。密码学题目往往就是给你一段密文、一个加密脚本或者一个交互接口让你想办法把明文搞出来。这个过程有点像解谜游戏需要你对编码、数学、算法都有一定的敏感度。2. CTF密码学题目到底在考什么2.1 密码学题目的核心分类很多人一开始会把CTF密码学和“加密解密”画等号其实这个理解太窄了。根据我打比赛和刷题的经验CTF密码学题目大致可以分成这么几类编码与解码类这类题目严格来说不算“密码学”但在CTF中经常被归到密码学方向。Base64、Base32、十六进制、URL编码、Unicode编码、摩斯电码、培根密码等等都属于这个范畴。它们的共同特点是没有密钥或者密钥是公开的你只需要识别出编码方式然后反向解码就行。古典密码类凯撒密码、维吉尼亚密码、栅栏密码、列移位密码、仿射密码、Playfair密码等。这类密码的特点是手工可解但需要你知道对应的破解方法。很多新手卡在这一步是因为不知道有在线工具或者不知道暴力破解的思路。现代密码学类AES、DES、RSA、椭圆曲线等。这类题目通常会给你加密脚本和密文你需要找到实现中的漏洞或者参数配置的问题来还原明文。RSA相关的题目在CTF中出现的频率极高因为它的数学结构清晰容易出题。哈希与摘要类MD5、SHA系列、HMAC等。这类题目往往涉及哈希长度扩展攻击、碰撞、彩虹表查询等。协议与随机数类伪随机数预测、密钥交换协议漏洞、填充预言攻击等。这类题目难度相对较高需要对密码学协议有较深的理解。2.2 为什么密码学题目让新手头疼我观察过很多刚入门的朋友他们在密码学题目上卡住的原因通常有这么几个第一个是不知道题目在考什么。拿到一串密文不知道是编码问题还是加密问题不知道应该先尝试Base64解码还是先分析频率。这种“不知道从哪下手”的感觉是最劝退的。第二个是工具使用不熟练。CTF密码学题目有很多常用的工具和在线平台比如CyberChef、dCode、各种Python库。不熟悉这些工具的话即使知道思路操作起来也很慢。第三个是数学基础薄弱。RSA题目涉及到模运算、欧拉函数、扩展欧几里得算法等数学知识。如果这些概念不熟悉看加密脚本就像看天书。第四个是缺乏系统性的解题框架。很多教程只讲某一道具体题目怎么解但没有告诉你遇到新题目时应该按照什么顺序去尝试。这就导致学了很多但遇到新题还是不会。2.3 建立解题框架的重要性我自己在刷了大量题目之后逐渐形成了一套“密码学题目排查流程”。这个流程不是什么高深的东西就是按照从简单到复杂的顺序依次尝试可能的解法。具体来说先看题目描述和附件类型判断是编码题还是加密题。如果是编码题用工具快速尝试常见编码。如果是加密题看是否给出了加密脚本。有脚本的话分析脚本逻辑找漏洞没有脚本的话根据密文特征判断加密类型。这个框架的价值在于它让你在面对陌生题目时有一个明确的起点而不是盲目地尝试。接下来我会把这个框架拆开详细讲每一步的具体操作。3. 编码识别与快速解码实战3.1 常见编码的特征与识别方法编码类题目是CTF密码学中最基础的部分也是新手最容易拿分的部分。关键在于快速识别编码类型。我整理了一个常见编码的特征对照表编码类型特征示例Base64由A-Z、a-z、0-9、、/组成末尾可能有SGVsbG8gV29ybGQBase32由A-Z和2-7组成末尾可能有JBSWY3DPEBLW64TMMQ十六进制由0-9和a-f组成长度通常为偶数48656c6c6fURL编码包含%后跟两个十六进制数字%48%65%6c%6c%6fUnicode包含\u或#x开头\u0048\u0065摩斯电码由点和划组成用空格分隔字母.... . .-.. .-.. ---培根密码由A和B组成每5个一组AABBA ABBAA识别编码类型的方法其实很简单看字符集。如果只有A-Z和2-7那大概率是Base32如果有大小写字母和数字还有和/那大概率是Base64。这个判断过程熟练之后就是几秒钟的事情。3.2 使用CyberChef进行编码链分析CyberChef是我最推荐的编码分析工具它是一个在浏览器中运行的开源工具支持数百种编码、加密、哈希操作。它的核心优势是“Recipe”功能——你可以把多个操作串联起来形成一个处理链。举个例子假设你拿到一串密文先Base64解码得到一串十六进制再十六进制转字符串得到一段摩斯电码最后摩斯解码得到明文。在CyberChef中你可以把这三个操作拖到Recipe区域一次性完成整个解码链。提示CyberChef的“Magic”功能可以自动尝试多种解码方式对于简单的多层编码题目非常实用。但不要过度依赖它复杂题目还是需要手动分析。我自己的习惯是拿到编码题先用Magic跑一遍如果Magic能直接出结果那说明题目比较简单。如果Magic跑不出来就手动分析每一层的特征逐步构建解码链。3.3 Python脚本批量解码技巧有些编码题目不是单层的而是多层嵌套甚至需要写脚本批量处理。比如题目给了一百行密文每行的编码方式可能不同这时候手动操作就不现实了。Python在这方面非常方便。比如处理Base64import base64 with open(cipher.txt, r) as f: lines f.readlines() for line in lines: try: decoded base64.b64decode(line.strip()).decode(utf-8) print(decoded) except: print(f解码失败: {line.strip()})对于十六进制转字符串cipher 48656c6c6f plain bytes.fromhex(cipher).decode(utf-8) print(plain)对于多层编码可以写一个递归函数自动尝试各种解码方式import base64 import binascii def auto_decode(data): for _ in range(10): # 最多尝试10层 try: data base64.b64decode(data).decode(utf-8) continue except: pass try: data bytes.fromhex(data).decode(utf-8) continue except: pass break return data这种脚本在比赛中能帮你节省大量时间。我的建议是平时就准备好一套常用的解码脚本模板比赛时直接改改就能用。3.4 编码题中的常见陷阱编码题虽然简单但也有一些坑需要注意大小写敏感Base64解码时大小写不同结果完全不同。有些题目会故意把大小写搞混让你以为是其他编码。填充字符Base64的填充有时候会被去掉解码时需要手动补上。补几个取决于字符串长度模4的余数。多层嵌套顺序多层编码的顺序很重要顺序错了就解不出来。一般来说先解外层再解内层但有时候需要根据特征判断。非标准编码有些题目会用变种的Base64比如换了字符表或者用了自定义的编码方式。这时候需要根据题目提示或者脚本逻辑来分析。4. 古典密码的破解思路与工具4.1 凯撒密码与暴力枚举凯撒密码是最经典的古典密码原理很简单把每个字母按照固定的偏移量移位。比如偏移量为3时A变成DB变成E以此类推。破解凯撒密码的方法就是暴力枚举所有25种可能的偏移量然后看哪个结果像明文。手动做的话很累但用Python就是几行代码def caesar_bruteforce(cipher): for shift in range(26): plain for c in cipher: if c.isalpha(): base ord(A) if c.isupper() else ord(a) plain chr((ord(c) - base - shift) % 26 base) else: plain c print(f偏移量{shift}: {plain}) caesar_bruteforce(KHOOR ZRUOG)运行结果中偏移量为3时输出“HELLO WORLD”这就是明文。注意有些凯撒密码的变种会对大小写分别处理或者只对字母移位而保留数字和符号。分析题目时要注意这些细节。4.2 维吉尼亚密码的破解逻辑维吉尼亚密码是凯撒密码的升级版它使用一个关键词来决定每个位置的偏移量。比如关键词是“KEY”那么第一个字母偏移K对应的值第二个偏移E第三个偏移Y然后循环。破解维吉尼亚密码的难点在于不知道关键词。常用的方法是卡西斯基测试Kasiski Examination和弗里德曼测试Friedman Test通过分析密文中重复出现的字母序列来推测关键词长度然后再用频率分析逐段破解。实际操作中我一般会先用在线工具比如dCode尝试自动破解。如果自动破解失败再手动分析。手动分析的基本步骤是找到密文中重复出现的三字母或更长的序列记录它们之间的距离。求这些距离的最大公约数猜测关键词长度。按照关键词长度把密文分成若干组每组用频率分析破解单个凯撒密码。组合各组结果还原明文。这个过程说起来简单但实际操作起来需要一定的耐心和经验。我的建议是先用工具跑一遍工具搞不定的再手动分析。4.3 栅栏密码与列移位密码栅栏密码Rail Fence Cipher是把明文按照Z字形排列后按行读取。列移位密码Columnar Transposition是把明文按行写入矩阵后按列读取列的顺序由关键词决定。这两类密码的破解思路都是尝试不同的栏数或列数然后看结果是否可读。栅栏密码的栏数通常不会太大暴力枚举2到10栏基本能覆盖大部分情况。def rail_fence_decode(cipher, rails): # 构建栅栏模式 pattern [] rail 0 direction 1 for i in range(len(cipher)): pattern.append(rail) rail direction if rail 0 or rail rails - 1: direction * -1 # 按行填充 result [] * len(cipher) idx 0 for r in range(rails): for i in range(len(cipher)): if pattern[i] r: result[i] cipher[idx] idx 1 return .join(result)列移位密码的破解稍微复杂一些需要尝试不同的列排列。如果关键词长度较短比如不超过6可以暴力枚举所有排列。如果关键词较长就需要结合频率分析来推测列的顺序。4.4 古典密码工具链推荐做古典密码题目有几个工具是我经常用的dCode一个在线工具网站支持几乎所有古典密码的加密解密和自动破解。它的自动破解功能对凯撒、维吉尼亚、栅栏等密码都很有效。CyberChef前面提到过它的优势是可以把多个操作串联起来适合处理多层加密的题目。Python的pycipher库这个库实现了多种古典密码可以直接调用。比如from pycipher import Caesar, Vigenere, Railfence # 凯撒解密 print(Caesar(3).decipher(KHOOR)) # 维吉尼亚解密 print(Vigenere(KEY).decipher(RIJVS)) # 栅栏解密 print(Railfence(3).decipher(HOLELWRD))Quipqiup一个在线频率分析工具对于单表替换密码的破解非常有效。你把密文粘贴进去它会自动尝试各种替换方案并给出可能的明文。这些工具的组合使用可以覆盖大部分古典密码题目。关键是要熟悉每个工具的适用场景遇到题目时能快速选择合适的工具。5. 现代密码学题目的攻击面分析5.1 RSA题目的常见漏洞类型RSA是CTF密码学中出现频率最高的现代密码算法。它的安全性基于大整数分解的困难性但在CTF题目中出题人往往会故意留下各种漏洞。我总结了几种常见的RSA漏洞类型小公钥指数攻击当公钥指数e很小通常是3且明文m也很小时密文c m^e mod n可能没有发生模运算直接对c开e次方就能得到m。即使发生了模运算如果m^e n也可以直接开方。共模攻击当两个公钥使用相同的模数n但不同的指数e1和e2且e1和e2互质时可以通过扩展欧几里得算法求出明文。低解密指数攻击当私钥指数d很小时可以使用Wiener攻击来恢复d。因数分解攻击当n的两个质因数p和q很接近时可以用费马分解法快速分解n。或者当n比较小时可以直接用工具分解。已知高位攻击当知道p或q的高位时可以使用Coppersmith方法恢复完整的p或q。这些漏洞类型对应的攻击脚本在网上都能找到关键是要能识别出题目属于哪种类型。一般来说题目会给出n、e、c的值你需要根据这些值的特征来判断攻击方式。5.2 分组密码模式与填充预言攻击AES和DES等分组密码在CTF中通常不会直接考算法本身的破解而是考加密模式的问题或者填充预言攻击。ECB模式ECB模式对相同的明文块产生相同的密文块这会泄露明文的模式信息。经典的攻击场景是“ECB字节翻转攻击”通过构造特定的输入来逐字节恢复明文。CBC模式CBC模式的第一个块使用IV初始化向量后续块使用前一个密文块作为IV。常见的攻击包括IV篡改、字节翻转、填充预言攻击等。填充预言攻击当服务器在解密后检查填充是否正确并根据结果返回不同的错误信息时攻击者可以通过构造密文并观察服务器的响应来逐字节解密。这个攻击在CTF中出现的频率很高值得花时间深入理解。提示理解这些攻击的关键是画图。把加密和解密的过程画出来标注每个块的输入输出然后思考如果修改某个块会发生什么。这比死记硬背攻击步骤有效得多。5.3 伪随机数预测与密钥恢复伪随机数生成器PRNG在密码学中扮演着重要角色。如果PRNG的实现有问题比如种子空间太小、状态可预测等就可能导致密钥被恢复。CTF中常见的PRNG题目包括线性同余生成器LCG如果知道连续的几个输出可以通过解线性方程组恢复参数进而预测后续输出。梅森旋转算法MT19937Python的random模块默认使用MT19937。如果获取了足够多的输出624个32位整数可以完全恢复内部状态从而预测所有后续输出。时间种子如果PRNG使用时间戳作为种子且时间范围已知可以暴力枚举种子来恢复密钥。这类题目的解题关键是理解PRNG的工作原理然后根据已知输出反推内部状态。Python的randcrack库可以自动完成MT19937的状态恢复非常方便。5.4 哈希长度扩展攻击原理与实操哈希长度扩展攻击是针对Merkle-Damgård结构的哈希函数如MD5、SHA-1、SHA-256的一种攻击方式。它的前提是你知道原始消息的哈希值但不知道原始消息本身同时你知道原始消息的长度。攻击的原理是Merkle-Damgård结构的哈希函数在处理消息时会把消息分成固定大小的块逐个处理。处理完最后一个块后输出的哈希值就是最终结果。如果我们在这个哈希值的基础上继续添加数据并计算新的哈希就相当于在原始消息后面追加了数据。具体操作步骤已知原始消息的哈希值H和原始消息长度L。构造填充使原始消息的长度对齐到块大小的整数倍。以H作为初始状态继续处理追加的数据。得到新的哈希值这个哈希值对应的消息是“原始消息 填充 追加数据”。在CTF中这类题目通常出现在Web方向的签名绕过场景中。密码学方向的话可能会让你实现这个攻击过程。Python的hashpumpy库可以自动完成这个计算。6. 密码学题目的工具链与实战心态6.1 必备工具与在线平台清单做CTF密码学题目有一套顺手的工具链非常重要。我把自己常用的工具整理成了一张表工具名称用途使用场景CyberChef编码解码、加密解密、数据分析编码题、多层加密题dCode古典密码自动破解凯撒、维吉尼亚、栅栏等Python pycryptodome现代密码学计算RSA、AES、哈希等SageMath数学计算、格攻击复杂RSA、椭圆曲线RsaCtfToolRSA自动攻击RSA题目快速尝试hashpumpy哈希长度扩展攻击哈希相关题目randcrackMT19937状态恢复PRNG预测题目Quipqiup频率分析单表替换密码这些工具不需要全部精通但至少要熟悉每个工具的用途和基本操作。我的建议是平时刷题时就有意识地使用这些工具形成肌肉记忆比赛时才能快速反应。6.2 解题思路的优先级排序面对一道密码学题目我通常按照以下优先级来尝试第一步看题目描述。题目描述中往往包含关键提示比如“小明喜欢用简单的密码”、“这是一个经典的加密方式”等。这些提示能帮你快速缩小范围。第二步识别编码。如果密文看起来像编码先用CyberChef的Magic功能跑一遍。大部分编码题在这一步就能解决。第三步分析加密脚本。如果题目给了加密脚本仔细阅读脚本逻辑。重点关注密钥是怎么生成的、有没有硬编码的密钥、随机数种子是什么、有没有明显的逻辑漏洞。第四步尝试已知攻击。根据密文和参数的特征判断属于哪种攻击类型。RSA题目可以用RsaCtfTool先跑一遍看看能不能自动出结果。第五步手动分析。如果自动工具搞不定就需要手动分析。这时候需要结合数学推导和编程实现逐步还原明文。这个优先级排序的核心思想是先用简单方法快速尝试不行再逐步深入。很多新手一上来就试图手动推导结果浪费了大量时间在简单题目上。6.3 从“做不出来”到“有思路”的转变我刚开始做CTF密码学题目时经常卡住。后来发现卡住的原因往往不是知识不够而是没有建立起题目特征和解题方法之间的映射关系。举个例子看到RSA题目中e3就应该立刻想到小公钥指数攻击看到两个密文用相同的n加密就应该想到共模攻击看到n的两个因子很接近就应该想到费马分解。这种映射关系需要通过大量练习来建立。我的建议是每做完一道题都总结一下这道题的特征和对应的解法。可以用一个表格来记录题目特征解法关键步骤e3密文较短小公钥指数攻击对c开三次方相同n不同e共模攻击扩展欧几里得算法n的两个因子接近费马分解平方差公式知道p的高位Coppersmith攻击格基约简这个表格积累得越多遇到新题目时反应就越快。我现在的表格已经有几十行覆盖了大部分常见题型。6.4 比赛中的时间分配与取舍CTF比赛中的时间管理也很重要。密码学题目难度差异很大简单的编码题可能几分钟就能解决复杂的RSA题目可能花几个小时也做不出来。我的策略是先快速浏览所有密码学题目把看起来简单的编码题、古典密码题先做掉确保拿到基础分。然后花时间攻克中等难度的题目RSA常见漏洞、分组密码攻击。最后如果还有时间再尝试高难度题目。注意不要在一道题上死磕太久。如果一道题卡了超过30分钟还没有明确思路建议先放一放去做其他题目。有时候换个脑子回来反而能想到新的思路。另外团队合作也很重要。如果队里有擅长数学的队友可以把RSA题目交给他如果自己更擅长编码分析就专注于编码题。合理分工能大幅提高效率。7. 一些踩过的坑和实用技巧7.1 编码题中的“套娃”陷阱我遇到过一道题密文经过Base64、十六进制、反转、凯撒移位、再Base64一共五层编码。这种“套娃”题目的坑在于你解到第三层时可能得到一个看起来像明文但实际上是下一层密文的东西容易误以为已经解完了。避免这个坑的方法是每解一层都检查结果的字符集特征。如果结果中包含大量不可打印字符说明可能解错了方向。如果结果是可读的英文但语义不通说明可能还有下一层。另外有些题目会在编码过程中加入干扰字符比如随机插入一些无关的字母或数字。这时候需要根据题目提示或者观察规律来去除干扰。7.2 RSA题目中的参数陷阱RSA题目中有几个容易踩的坑e和φ(n)不互质正常情况下e应该和φ(n)互质但有些题目故意让它们不互质这时候需要特殊处理不能直接求逆元。多组密文有些题目给出多组密文可能需要对每组分别解密也可能需要利用组之间的关系来解密。n相同但e不同这是共模攻击的典型场景但要注意e1和e2必须互质才能使用扩展欧几里得算法。密文是整数还是字节有些题目给出的密文是整数有些是字节串。处理方式不同整数需要转成字节才能得到明文。这些坑我在实战中都踩过每次踩坑后都会在笔记里记下来。现在遇到RSA题目我会先检查这些参数特征避免重复踩坑。7.3 分组密码攻击的实操细节分组密码攻击的实操中有几个细节需要注意字节翻转攻击中的偏移计算在CBC字节翻转攻击中你需要修改前一个密文块的特定字节来影响当前明文块的对应字节。偏移计算容易出错建议画图确认。填充预言攻击中的边界条件填充预言攻击需要精确控制填充长度最后一个字节的填充值决定了整个填充是否有效。构造密文时要注意边界条件。ECB模式中的块对齐ECB字节翻转攻击需要明文块对齐到16字节。如果明文长度不是16的倍数需要先通过填充使其对齐。这些细节在理论讲解中往往一笔带过但实际操作中很容易出错。我的建议是先在本地搭建环境测试确认攻击脚本正确后再用于比赛。7.4 保持好奇心和耐心最后说一点心态上的东西。CTF密码学题目有时候确实很折磨人一道题卡几个小时甚至几天都是正常的。但当你最终解出答案的那一刻那种成就感是其他方向很难比拟的。我的经验是遇到难题不要急躁先把已知信息整理清楚然后逐步缩小范围。有时候出去散个步回来思路就通了。另外多和队友交流别人的一句话可能就能点醒你。平时刷题时不要只追求做出来的数量更要注重理解每道题背后的原理。做不出来的题目看完Writeup后要自己复现一遍确保真正掌握了。这样积累下来你的密码学解题能力会有质的提升。密码学是一个需要长期积累的方向但入门并不难。从编码题开始逐步过渡到古典密码和现代密码保持好奇心和耐心你会发现CTF密码学其实很有意思。