news 2026/4/25 14:36:18

BUUCTF [安洵杯 2019] 从碎片到密钥:一次多层编码的逆向追踪

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
BUUCTF [安洵杯 2019] 从碎片到密钥:一次多层编码的逆向追踪

1. 从碎片到密钥的逆向追踪之旅

第一次看到这个题目的时候,我整个人都是懵的。36个没有后缀的文件,一个加密的ZIP压缩包,这要怎么下手?但作为一个CTF老手,我知道越是看起来复杂的题目,往往隐藏着最直接的解题思路。这道来自安洵杯2019的题目,完美诠释了"从碎片到密钥"的逆向思维过程。

这道题的核心在于两个关键点:数据载体恢复和编码链逆向。简单来说,就是要先把零散的二维码碎片拼成完整的二维码,然后按照正确的顺序逆向解码多层加密的字符串。听起来容易,但实际操作中会遇到各种坑,比如文件类型识别错误、编码顺序搞反、解码工具选择不当等等。下面我就详细拆解整个解题过程,分享我在这个过程中踩过的坑和总结的经验。

2. 文件分析与碎片重组

2.1 初始文件分析

下载附件解压后,你会看到一个flag.zip压缩包和36个没有后缀的文件。我的第一反应是用file命令检查这些文件的类型,但如果你在Windows环境下,可以用010 Editor或者WinHex这类工具查看文件头。

file *

通过查看文件头,我发现这些无后缀文件都是JPEG格式,因为它们的文件头是FF D8 FF,文件尾是FF D9。这是JPEG文件的典型特征。这时候你需要批量给这些文件添加.jpg后缀。手动修改36个文件太麻烦,我写了个简单的Python脚本:

import os path = './' # 当前目录 for filename in os.listdir(path): if filename != 'flag.zip': os.rename(os.path.join(path, filename), os.path.join(path, filename + '.jpg'))

2.2 二维码碎片拼接

现在36个文件都变成了.jpg格式,打开一看,果然是二维码的碎片。这时候就需要把它们拼成一个完整的二维码。我试过用Photoshop手动拼接,但36个碎片实在太耗时。后来发现可以用ImageMagick的montage命令自动拼接:

montage *.jpg -tile 6x6 -geometry +0+0 qrcode.jpg

这个命令会把所有jpg文件按照6x6的网格排列,生成一个完整的二维码图片。参数说明:

  • -tile 6x6:指定排列方式为6行6列
  • -geometry +0+0:设置图片间距为0
  • qrcode.jpg:输出文件名

拼接完成后,用手机或二维码扫描工具扫描,就能得到加密字符串和加密顺序提示。

3. 多层编码逆向解析

3.1 理解编码链条

扫描二维码后,我们得到了两个关键信息:

  1. 加密字符串:GNATOMJVIQZUKNJXGRCTGNRTGI3EMNZTGNBTKRJWGI2UIMRRGNBDEQZWGI3DKMSFGNCDMRJTII3TMNBQGM4TERRTGEZTOMRXGQYDGOBWGI2DCNBY
  2. 加密顺序:base85 >> base64 >> base85 >> rot13 >> base16 >> base32

解密的关键在于逆向这个编码顺序。也就是说,我们需要按照base32 -> base16 -> rot13 -> base85 -> base64 -> base85的顺序逐步解码。

3.2 逐步解码过程

第一步:Base32解码

使用在线工具或Python的base64库进行解码:

import base64 encoded = "GNATOMJVIQZUKNJXGRCTGNRTGI3EMNZTGNBTKRJWGI2UIMRRGNBDEQZWGI3DKMSFGNCDMRJTII3TMNBQGM4TERRTGEZTOMRXGQYDGOBWGI2DCNBY" decoded = base64.b32decode(encoded).decode('utf-8') print(decoded)

解码结果:3A715D3E574E36326F733C5E625D213B2C62652E3D6E3B7640392F3137274038624148

第二步:Base16解码

Base16其实就是十六进制编码,可以用以下代码解码:

from binascii import unhexlify encoded = "3A715D3E574E36326F733C5E625D213B2C62652E3D6E3B7640392F3137274038624148" decoded = unhexlify(encoded).decode('utf-8') print(decoded)

解码结果::q]>WN62os<^b]!;,be.=n;v@9/17'@8bAH

第三步:ROT13解码

ROT13是一种简单的字母替换密码,把字母表中的字母移动13位:

import codecs encoded = ":q]>WN62os<^b]!;,be.=a;i@9/17'@8oNU" decoded = codecs.encode(encoded, 'rot13') print(decoded)

解码结果::d]>JA62bf<^o]!;,or.=a;i@9/17'@8oNU

第四步:Base85解码

Base85有几种变体,这里需要使用ASCII85编码标准:

import base64 encoded = "PCtvdWU4VFJnQUByYy4mK1lraTA=" decoded = base64.a85decode(encoded).decode('utf-8') print(decoded)

解码结果:<+oue8TRgA@rc.&+Yki0

第五步:Base64解码

encoded = "<+oue8TRgA@rc.&+Yki0" decoded = base64.b64decode(encoded).decode('utf-8') print(decoded)

解码结果:ThisIsSecret!233

4. 实战经验与技巧

4.1 常见问题排查

在实际操作中,有几个容易出错的地方需要特别注意:

  1. Base85编码变体问题:不同的Base85实现可能有细微差别,如果解码失败,可以尝试ASCII85、Z85等变体。

  2. 编码顺序错误:一定要严格按照逆向顺序解码,顺序错了结果肯定不对。我一开始就犯了这个错误,把base32和base16的顺序搞反了。

  3. 字符集问题:在不同解码步骤之间,可能会遇到字符集转换问题,特别是在处理非ASCII字符时。

4.2 自动化脚本编写

为了提高效率,我后来写了一个完整的自动化解码脚本:

import base64 import codecs from binascii import unhexlify def decode_all(encoded): # Base32 step1 = base64.b32decode(encoded).decode('utf-8') print(f"Base32: {step1}") # Base16 step2 = unhexlify(step1).decode('utf-8') print(f"Base16: {step2}") # ROT13 step3 = codecs.encode(step2, 'rot13') print(f"ROT13: {step3}") # Base85 (ASCII85) step4 = base64.a85decode(step3.encode()).decode('utf-8') print(f"Base85: {step4}") # Base64 step5 = base64.b64decode(step4).decode('utf-8') print(f"Base64: {step5}") # Final Base85 step6 = base64.a85decode(step5.encode()).decode('utf-8') print(f"Final: {step6}") return step6 encoded_str = "GNATOMJVIQZUKNJXGRCTGNRTGI3EMNZTGNBTKRJWGI2UIMRRGNBDEQZWGI3DKMSFGNCDMRJTII3TMNBQGM4TERRTGEZTOMRXGQYDGOBWGI2DCNBY" password = decode_all(encoded_str)

这个脚本可以一次性完成所有解码步骤,大大提高了效率。特别是在比赛时间紧张的情况下,这种自动化工具非常有用。

5. 总结与延伸思考

通过这道题目,我深刻体会到CTF比赛中数据恢复和编码分析的重要性。在实际工作中,这种技能也同样有用,比如分析恶意软件、逆向工程、数据取证等场景。

有几个关键点值得牢记:

  1. 文件头分析是识别未知文件类型的基础技能
  2. 多层编码需要严格按照逆向顺序解码
  3. 自动化脚本可以显著提高解题效率
  4. 不同编码标准可能有细微差别,要注意区分

这道题目的flag最终是flag{Qr_Is_MeAn1nGfuL},但比flag更重要的是解题过程中积累的经验。下次遇到类似的题目,你就知道该怎么一步步拆解了。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/25 14:28:20

ICode Python竞赛入门:从变量循环到列表操作,通关1级训练场核心技巧

1. ICode竞赛Python入门&#xff1a;为什么从变量和循环开始&#xff1f; 我刚接触ICode竞赛时&#xff0c;发现1级训练场的题目看似简单&#xff0c;但想要快速通关并不容易。这些题目大多围绕变量、循环和列表这三个核心概念展开&#xff0c;这其实反映了编程学习的一个基本规…

作者头像 李华
网站建设 2026/4/25 14:28:19

SGP.31 eIM配置实战:从零关联到安全移除的物联网eSIM管理全流程

1. 初识SGP.31与eIM配置&#xff1a;物联网设备的"身份证管家" 当你拿到一台全新的物联网设备时&#xff0c;它就像刚出生的婴儿——虽然硬件齐全&#xff0c;但还没有"身份证明"。在物联网世界里&#xff0c;这个身份就是eSIM&#xff08;嵌入式SIM卡&…

作者头像 李华