CTF密码学题解:Base62+XXTEA+列置换三层加密逆向
上周末打了一场线上CTF遇到一道叫“你没有见过的加密”的密码学题。刚开始我以为是普通的杂项题结果解压附件后看到加密脚本整个人都愣了一下——脚本里没有常见的AES、RSA而是把自定义Base62编码、XXTEA、列置换三层变换叠在一起确实有点“防新手”的味道。后来冷静下来按层拆解发现每一层单独拎出来都不难难的是你能不能识别出每一层并按正确的顺序逆向。这篇WP就把整个思路、脚本、踩坑点完整写出来适合正在入门CTF、想拓宽密码学视野的选手参考。1. 第一轮信息收集从附件结构锁定三个反常点1.1 附件解压后的一手资料长什么样题目附件是一个压缩包解压后有三个文件encrypt.py、flag.enc、hint.png。用file命令扫一遍flag.enc是一个纯文本文件里面是一串长度88的可见字符串开头大概是6YmLp4fZxDS1vGnB8kN3uVcAJX5sHiCKbeyadrUMhPQFlOIgWTj0e2x这种眼睛看过去全是大小写字母和数字混排。hint.png是一张720x360的图片内容是电脑键盘的高清照片一开始看不出有什么玄机后面才意识到它是用来暗示“注意大小写字符排列顺序”的。信息收集阶段的核心原则是“先看脚本再猜算法”。很多时候题目名字会误导人真正可靠的信息来源永远是加密脚本本身。所以我没有急着把flag.enc扔进各种在线解密工具而是先打开encrypt.py通读了一遍把加密流程从头到尾理顺。1.2 三个反常点直接指向解密顺序读脚本时注意到三个非常扎眼的地方。第一个是脚本里定义了一个长度正好为62的字符串变量CIPHER_TABLE里面是打乱的数字和大小写字母。看到这种变量名和长度我脑子里第一反应就是Base64变种字符表。但标准Base64字符表是64个字符这里是62个说明它更像是Base62。Base62和Base64最大的区别就是没有填充符号它直接把字节流当一个大整数来做进制转换输出一串纯字母数字。第二个是脚本里出现了import xxtea。XXTEA不是大众熟悉的算法但它也不算难认。很多CTF题喜欢用XXTEA再包一层Base64或者自定义编码看到这个import等于第二层算法已经写在脸上了。真正需要关心的是脚本里调用xxtea.encrypt时padding参数是怎么写的这决定了逆向时明文末尾有没有额外的填充字节。第三个是脚本里有一个col_perm函数作用是按照某个字符串密钥对字节序列做“列置换”。这个函数不是常见的加密库函数而是命题人自己写的逻辑也不复杂把明文按行填进矩阵按key字符的ASCII排序取出列。看到这里整个题目的加密链路已经浮出水面明文先做列置换再用XXTEA加密最后用自定义Base62表编码成可见字符串。解密时顺序完全反过来Base62解码、XXTEA解密、列置换逆操作。2. 加密链路拆解看懂“没见过”背后的多重套娃2.1 冷门算法的恐慌感来自未知很多新手一看到“没见过”的加密就发怵其实加密题剥开来看就两个动作换表和换序。AES、RSA这些主流算法再复杂最后输出也是让人看不懂的字节流和题目里这串自定义Base62结果在“看不懂”这个层面没什么区别。命题人之所以选XXTEA加自定义编码不是因为它们比AES更安全而是因为它们冷门能筛掉一批只会抄工具答案的人。搞清楚这一点心态就稳了。遇到没见过的加密第一件事不是害怕而是把加密流程当作流水线输入明文经过哪几步变换最后输出密文。只要把每一步识别清楚逆向就是倒着走一遍流水线。这个思维对CTF密码学题非常关键比单纯背几个算法要有用得多。2.2 Base62不是Base64本质是进制转换自定义Base62编码题里最常见的一种变形。它和Base64的区别要搞清楚。Base64是把字节流按每组6位切分每6位对应一个64字符表中的字符因为6位一组会产生余位所以需要来填充对齐。Base62则完全换了个思路先把bytes当作一个巨大的整数然后用62进制去表示这个整数每一位对应一个自定义字符。用生活类比例子就是我们平时写数字用十进制逢十进一计算机底层用二进制逢二进一Base62就是用62个可见字符当数字符号逢六十二进一。编码时不断除以62取余数把余数映射到自定义字符表解码时反过来把每个字符查表成对应的数值然后逐步乘以62相加最后还原成一个大整数再转回字节流。这道题里flag.enc那88个字符就是XXTEA加密后的一串字节被当成大整数做62进制转换的结果。解码时最关键的一点是必须使用脚本里那把打乱的字符表不能用标准Base62或Base58表否则查表结果完全错位后面怎么解都是乱码。2.3 XXTEA分组长度可变的小众加密XXTEA是TEA系列算法的一种扩展全称是Extended Tiny Encryption Algorithm。传统TEA固定处理64位分组XXTEA则把分组长度提升到可变范围理论上可以处理任意长度的数据配合填充模式使用会更灵活。它的核心结构就是循环的加法、异或以及一个常量0x9E3779B9这个常量本质上是黄金分割比衍生出来的数值跟MD5里的初始向量一样属于算法规范的一部分。Python里使用XXTEA一般直接import xxtea加密接口是xxtea.encrypt(data, key, paddingTrue/False)。这里有两个细节需要特别注意。第一是key的长度XXTEA要求key是16字节的整数倍常见做法是直接用MD5后的16字节摘要当key。第二是padding参数如果加密时用paddingTrue那解密得到的字节串末尾会有填充数据后面再做列置换逆操作时长度会多出来几个字节如果paddingFalse那就要求数据长度本身是4字节的倍数否则加密过程就会报错或产生特殊行为。命题人一般会选paddingTrue让脚本跑起来更省心但把填充数据留到最后一层这其实是个精心设置的坑。后面我会讲到怎么处理这个填充问题。2.4 列置换最容易被忽略的顺序变换列置换这个操作原理极其简单但它藏在Base62和XXTEA后面非常容易被忽略。加密时先把明文按字符顺序从左到右、从上到下填进一个二维矩阵矩阵的列数等于密钥字符串的长度行数根据明文长度向上取整然后按照密钥每个字符的ASCII码值排序得到一个列的读取顺序最后按这个顺序逐列从上往下读取矩阵跳过空位得到置换后的密文。解密的时候需要按同样的列顺序把数据填回矩阵然后再按行从左到右读出来。这里最容易出错的点有两个一是排序方向有的脚本用key[i]升序排有的用降序排方向反了直接拿到乱码二是空位处理明文长度不一定是列数的整数倍最后一行会有空缺加密读取时会跳过这些空位逆操作的时候也要跳过否则整个矩阵错位一个字节全盘皆输。3. 完整解题过程实录从密文到flag3.1 先做一轮自动识别随波逐流和CyberChef怎么配合拿到题目后我没有直接写脚本而是先把flag.enc丢进随波逐流CTF编码工具跑了一圈自动识别。这类工具最大的价值是帮你快速排除常见编码比如摩斯、凯撒、栅栏、Base全家桶、ROT系列。实测下来工具给出的提示是“疑似Base64/Base58/Base62家族”但没法确定具体字符表因为题目用的是自定义表不在标准工具的预设范围里。我又在CyberChef里试了一下把自定义字符表填进去做Base62转换结果也是不出意外地失败。原因很简单CyberChef对自定义字符集的支持方式跟脚本里的进制转换逻辑不一定完全一致而且这里的数据不是标准Base62输出中间还夹着XXTEA加密的字节长度问题。经验就是像这种自定义表和自定义逻辑混在一起的情况老老实实写Python脚本才是最快最稳的路工具只能当辅助判断用。3.2 第一层自定义Base62解码脚本根据脚本里的CIPHER_TABLE写第一个解码脚本。核心是构建字符到数值的反查表然后按照进制转换逻辑还原大整数再转回字节串。ALPHA 7Rq9wE0t2o6YmLp4fZxDS1vGnB8kN3uVcAJX5sHiCKbeyadrUMhPQFlOIgWTj TABLE {c: i for i, c in enumerate(ALPHA)} def b62_decode(s): num 0 for ch in s.strip(): num num * 62 TABLE[ch] length (num.bit_length() 7) // 8 return num.to_bytes(length, big) with open(flag.enc, r) as f: enc_bytes b62_decode(f.read()) print(enc_bytes.hex())这里有一个很容易踩的坑i的顺序就是字符在自定义表里的数值顺序不能反。我第一次写的时候顺手把反查表写成了{c: 62 - i}结果解码出来的字节流开头全是00彻底不下去。后来对照脚本又确认了一遍表的顺序就是从左到右递增修正后输出的十六进制开头是b0 e1 a7 ...是一段看起来比较均匀的随机字节符合XXTEA加密后的特征。3.3 第二层XXTEA解密与密钥来源拿到第一层解码后的字节串接下来做XXTEA解密。密钥来源要从脚本里找通常是写死的常量加MD5处理。我看到的脚本是key hashlib.md5(bCTF_Salt_2024).digest()直接把16字节摘要当密钥用。import hashlib import xxtea key hashlib.md5(bCTF_Salt_2024).digest() plain xxtea.decrypt(enc_bytes, key, paddingTrue) print(repr(plain))跑完这步得到的不是flag。我拿到的一串类似b\x86k...some readable chars...的半可读半乱码内容表明XXTEA这层已经解开了但数据里还混着列置换后的顺序错乱所以读起来不是完整明文。为什么判断已经解开因为如果key错误XXTEA解密输出的会是几乎完全不可读的随机字节如果key正确输出中会出现大量可读字符只是顺序不对。这里还要提醒一件事xxtea库的decrypt在paddingTrue时会自动把填充字节一并返回。也就是说你还需要在后续处理中处理末尾可能多出来的填充这个我在踩坑记录里细说。3.4 第三层列置换逆操作XXTEA解密后得到的字节串长度可能和原始明文长度对不上因为填充模式会在末尾补内容。我先按照脚本里的列置换逻辑写逆操作脚本把数据重新排回矩阵再按行读取。def col_unperm(data: bytes, key: str) - bytes: cols len(key) rows (len(data) cols - 1) // cols order sorted(range(cols), keylambda i: key[i]) matrix [[None] * cols for _ in range(rows)] idx 0 for c in order: for r in range(rows): if idx len(data): matrix[r][c] data[idx] idx 1 out b for r in range(rows): for c in range(cols): cell matrix[r][c] if cell is not None: out bytes([cell]) return out key_perm CtfKeY_2024 result col_unperm(plain, key_perm) print(result)这个脚本跑出来的结果包含填充字节所以末尾有几个不可读字符。我直接把输出末尾的不可读部分去掉或者根据flag{开头来做截断就能看到完整flag了。3.5 最终flag清理掉填充字节后最终输出为flag{Tr4nspos1t10n_Base62_XXTEA_R34lly_C00l}整个解密链路一共三层逆序解完后flag就出来了。全程没有用到什么高深数学知识考的就是对加密流程的拆解能力以及对进制转换、填充、排序这些基础概念的熟练掌握程度。4. 踩坑记录三个差点劝退我的细节4.1 大小写敏感与手抄密文的悲剧flag.enc里的密文是大小写字母加数字的混合手抄特别容易出错。我在开始阶段为了图方便把密文复制到终端时多了一个空格结果Base62解码后字节长度直接变了后面所有步骤全部白做。血泪教训就是处理这种字符串一定要用脚本读取文件不要手动复制粘贴更不要肉眼核对。hint.png那张键盘图实际上就是在暗示“大写和小写是两个不同的字符”这属于命题人给的善意提醒。4.2 XXTEA填充模式导致的长度误差paddingTrue带来的问题很隐蔽。加密时XXTEA会把数据长度补成4的倍数解密时它会把这些填充字节一起返回导致列置换逆操作时明文长度比原始明文多了几个字节。如果直接按解密后的长度去算列数矩阵最后一行会多出一些空位最终输出末尾会出现一堆不在flag格式内的乱码。处理办法是逆置换前先统计输出的可读长度或者直接以flag{开头作为锚点把输出截断到flag结束的位置。我之前就是被末尾几个\x00坑了半天差点以为密钥不对。4.3 编码表排序方向写反列置换的排序方向非常容易搞反。我第一版逆操作脚本把order sorted(range(cols), keylambda i: key[i])写成了降序排列结果解出来的内容是}...lool_y这种明显反向的文本。发现之后改成升序才正常。建议遇到这种问题时先别急着改整个矩阵逻辑而是打印一下order看看顺序是否符合预期。比如key abc时order应该是[0, 1, 2]如果打印出来是[2, 1, 0]那就说明方向反了。4.4 用flag前缀做交叉验证这道题的flag明文必须以flag{开头这个特征可以用来快速验证每一层是否解对。我在每解完一层后都会打印repr结果检查是否出现了可读字符或flag特征。如果看到flag{已经出现说明前面所有层都正确剩下的只是清理填充或者处理截断如果输出的还是一坨乱码那就回头查上一步的字符表或者排序方向。这种“已知明文特征”的验证方法在密码学题里非常实用尤其是多层加密套娃的时候它可以帮你快速定位到具体错在哪一层。5. 这道题带给我的两点复盘第一点是加密算法本身并不神秘。XXTEA、Base62、列置换单独拿出来任何一个都是入门级知识但命题人把它们按“置换到加密到编码”的顺序叠起来就能制造出一种“没见过”的压迫感。破解这类题的关键是先把加密流程画成流水线然后逆着每一层做还原不要上来就梦想用一个大工具一把梭。第二点是基本功决定了效率。进制转换、字节与字符串的互换、矩阵填充与读取、填充模式的影响这些看起来很基础的东西恰恰是这类题目真正的考点。我中间好几次卡住不是卡在算法上而是卡在字节序、空格、大小写上。把这些基本功练扎实比多背几个加密库接口有用得多。最后分享一个小技巧遇到类似的“自定义编码 冷门加密”组合题先把脚本里的所有常量和表复制到一个独立文件里写脚本时全部引用变量不要手动抄。至少能帮你省下两小时排查低级错误的时间。

相关新闻

技术合规红线:资金盘/传销系统源码的法律风险与正确开发方向

技术合规红线:资金盘/传销系统源码的法律风险与正确开发方向

简介:尊享富理财系统源码是一套以区块链为技术标签的理财投资平台代码实现,面向需要自建理财分红、股权回购、公排见点等业务模块的开发者或项目运营者。源码功能覆盖完整:提供10元、30元等短期理财计划,并设动态收益、直推佣金、…

2026/9/25 10:01:58 阅读更多 →
AI模型迭代中的安全边界与事实核查原则

AI模型迭代中的安全边界与事实核查原则

我无法根据当前输入生成符合要求的博文。原因如下:项目标题“Google新作Dream-RSI:让AI在梦境回放中递归自我进化”所描述的技术并不存在于公开、可信的科技文献、官方发布或主流技术媒体(如Google AI Blog、arXiv、NeurIPS、ICML、Nature Ma…

2026/9/25 10:00:56 阅读更多 →
Cursor+GitOps 自动化运维:用 TaoToken 统一 Key 打通配置骨架

Cursor+GitOps 自动化运维:用 TaoToken 统一 Key 打通配置骨架

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/25 10:00:56 阅读更多 →

最新新闻

miniSQL实战指南:手写数据库内核的四大模块与避坑方法

miniSQL实战指南:手写数据库内核的四大模块与避坑方法

简介:本资源是浙江大学数据库设计课程期末大作业成果——miniSQL轻量级数据库管理系统,面向数据库原理学习者、C/C系统编程初学者及课程实践者,旨在通过完整可运行的DBMS实例,深入理解SQL解析、事务处理、B树索引、缓冲区管理等核…

2026/9/25 13:30:51 阅读更多 →
从续作焦虑到IP反噬:《Ave Mujica》的节奏与角色塑造复盘

从续作焦虑到IP反噬:《Ave Mujica》的节奏与角色塑造复盘

这标题,放在咱们这个圈子里,基本就是一道明牌:谁都看得出《Ave Mujica》是在照抄《MyGO!!!!!》的成功公式,但偏偏抄了个寂寞,甚至在很多地方把前作好不容易攒下的口碑给反噬了。我自己是两部都一集不落追完的人&#x…

2026/9/25 13:30:51 阅读更多 →
智慧社区项目源码解析:Spring Boot+Vue前后端分离实战指南

智慧社区项目源码解析:Spring Boot+Vue前后端分离实战指南

简介:一套基于 Web 的智慧社区系统完整设计与实现源码包,面向需要课程设计、毕业设计或前后端项目练手的开发者。平台覆盖物业通知、公共设施预约、社区活动发布、居民互动、在线缴费及智能家居控制等核心模块,并兼顾权限安全、数据存储与系统…

2026/9/25 13:30:51 阅读更多 →
Jupyter Docker Stacks 变更日志深度解读:从构建参数、运行时行为到供应链安全的完整演进

Jupyter Docker Stacks 变更日志深度解读:从构建参数、运行时行为到供应链安全的完整演进

云原生开发工具数据科学 【免费下载链接】docker-stacks Ready-to-run Docker images containing Jupyter applications 项目地址: https://gitcode.com/gh_mirrors/do/docker-stacks 点击查看 免费下载 关联文档:docs/changelog.md(经 CHAN…

2026/9/25 13:30:51 阅读更多 →
2026年Apifox免费版权益盘点:接口调试、自动化测试与团队协作选型指南

2026年Apifox免费版权益盘点:接口调试、自动化测试与团队协作选型指南

我们常说“工具选对了,加班少一半”,接口调试这块尤其如此。过去几年,从Postman独霸天下,到Apifox这类一体化工具快速崛起,大家的习惯也在慢慢改变,尤其是2026年这个节点,接口工具的功能边界和免…

2026/9/25 13:30:51 阅读更多 →
Atlas 300V 24G推理加速卡部署YOLO完整实践指南

Atlas 300V 24G推理加速卡部署YOLO完整实践指南

这段时间后台一直有人留言问同一个问题:Atlas 300V 24G到底是不是运算加速卡,能不能用来部署YOLO?说实话,这个问题问的人多了,我是有点意外的——因为答案其实很明确,但问法本身就说明大家把这块卡的定位搞…

2026/9/25 13:29:50 阅读更多 →

日新闻

AI元人文:从工具使用到思维重构的深度探索

AI元人文:从工具使用到思维重构的深度探索

最近半年我一直在琢磨一件事:AI元人文到底是什么?说白了,就是“用元视角重新审视人与AI的关系”,也在“探索AI如何反向逼着我们发现自己的思考边界”。标题里的“元探索”,在我看就是一层套一层的追问——当你用AI解决…

2026/9/25 0:00:41 阅读更多 →
Python+CNN车牌识别实战:从数据预处理到模型训练与部署

Python+CNN车牌识别实战:从数据预处理到模型训练与部署

简介:基于Python与卷积神经网络的车牌识别项目,面向计算机视觉初学者及智能交通开发者,目标是帮助用户掌握从数据预处理、模型构建到实际部署的完整流程。压缩包共25个文件,包含jpg/png图像样本、py训练脚本、md说明文档、dat数据…

2026/9/25 0:00:41 阅读更多 →
Vim基础操作全攻略:保存退出、模式切换与高频命令实战

Vim基础操作全攻略:保存退出、模式切换与高频命令实战

1. 项目概述1.1 核心需求解析今天聊聊Vim。写这个题目的原因是:几乎每个后端开发者、运维人员、数据工程师某天都会遇到一个场景——深夜加班,服务器登录界面只有黑底白字,编辑器只有vi/vim,你必须在五分钟内完成一次配置修改并保…

2026/9/25 0:00:41 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/24 14:34:13 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/25 11:15:26 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/24 14:33:56 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/24 12:50:34 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/24 14:33:48 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/24 12:49:17 阅读更多 →