☰
压缩包加密与破解实战:从伪加密到已知明文攻击的CTF MISC解析
2026/10/23 8:47:26 网站建设 项目流程

1. 题目初探:拿到文件后先别急着解压

CTF的MISC方向,尤其是压缩包相关题目,最忌讳的就是一上来就双击解压。我拿到"青岑CTF MISC 城邦:压缩术"这道题目的附件时,第一反应是先看它到底是什么,而不是急着找密码。附件是一个名为compress.rar的文件,大小约2.3MB,这个体积对压缩包题来说不太正常——通常纯文本的flag不会这么大,所以里面大概率还嵌套了其他东西。

先用Linux下的file命令做基础识别:

file compress.rar compress.rar: RAR archive data, v5 - 兼容性标记

这里有个值得注意的细节,RAR5格式和旧版RAR4在处理方式上差别很大,后面爆破时要选对工具。接着用binwalk扫了一遍,看看有没有在文件尾部藏其他数据:

binwalk compress.rar DECIMAL HEXADECIMAL DESCRIPTION -------------------------------------------------------------------------------- 0 0x0 RAR archive data, 版本 4.x

binwalk检测出来是RAR 4.x,这其实是个信号——RAR5和RAR4的头部结构不同,有些题目会故意用旧版格式来兼容特定工具。我继续用strings快速翻了翻明文字符串,果然在文件尾部发现了一串Base64编码的文本,解码后是fake_flag_is_here。这是明显的干扰项,出题人故意放了一个假flag在显眼位置,如果经验不足的选手在这里就提交,会浪费很多时间。

这个阶段的核心教训是:压缩包题目的信息收集必须全面。我习惯的流程是:

  • file识别真实文件类型
  • binwalk检查是否有附加数据或隐藏文件
  • strings提取可见字符串,留意可疑的Base64、十六进制片段
  • 010 Editor或HxD查看文件头部和尾部,确认有没有人为修改的痕迹

做完这四步,我基本确认这是一个多层的压缩包嵌套题,后面要面对的无非是伪加密、暴力破解、明文攻击这几类套路。但"压缩术"这个名字给了我很强的暗示——出题人想考的是压缩包相关的各种技术点,而不是单纯堆难度。

2. 伪加密:被"锁"住的真相

2.1 为什么压缩包会被一眼判定为加密

把compress.rar解压出来,里面是一个名为flag.zip的文件,同样显示有密码。这时候先别急着爆破,我习惯先用zipinfo这类工具查看压缩包的详细结构:

zipinfo -v flag.zip

重点看central directory部分的general purpose bit flag字段。ZIP格式中,这个字段的第0位如果为1,就表示文件被加密。很多CTF题目的"加密"只是把这一位手动改成1,实际并没有真正加密——这就是伪加密。

判断伪加密有个非常实用的技巧:用命令行工具尝试解压,如果提示需要密码,再用Python的zipfile模块去读文件名列表。zipfile在某些场景下会忽略加密标志位直接列出内容,而真实加密的压缩包在读取时一定会要求密码,两者的表现差异可以帮我们快速判断。

2.2 修改加密标志位的操作细节

确认是伪加密后,用010 Editor打开flag.zip,搜索50 4B 03 04(ZIP本地文件头的魔术数字)。每个文件条目中,偏移4到5字节处就是general purpose bit flag。把第0位从1改为0,然后在中央目录(搜索50 4B 01 02)做同样的修改,保存后重新解压,如果顺利解出内容,就证明刚才确实是伪加密。

这个过程看似简单,有两个坑必须提醒:

  • 修改时必须在本地文件头和中央目录文件头都改掉。有些工具只读中央目录,有些只读本地头部,漏改一个都可能出问题。
  • 修改前先备份原文件。如果改错了,或者题目其实用了真加密,把文件改坏了就麻烦了。我习惯把原文件复制一份,在副本上操作。

2.3 用工具脚本绕过伪加密

手动改字节适合单文件,如果是多个文件嵌套的伪加密压缩包,用手改效率太低。我写了一个简单的Python脚本,用zipfile先尝试用空密码解压,如果失败就逐字节修改加密标志位再试:

import zipfile import shutil import os def fix_pseudo_encryption(zip_path, output_path): with open(zip_path, 'rb') as f: data = bytearray(f.read()) # 修改本地文件头的加密标志位 for i in range(len(data) - 4): if data[i] == 0x50 and data[i+1] == 0x4B and data[i+2] == 0x03 and data[i+3] == 0x04: # 偏移+6处是general purpose bit flag的低字节 data[i+6] &= 0xFE # 清除第0位 with open(output_path, 'wb') as f: f.write(data)

不过这里要解释清楚工具背后的原理,不然遇到换汤不换药的变种题还是不会。历史上拿到伪加密压缩包后先看它的压缩源文件版本(version needed to extract),如果这个值异常,比如是63(强制ZIP64格式),也可能是题目故意设置的陷阱,需要改成正常值才能处理。

3. 多层嵌套与字典爆破:压缩套压缩

3.1 解开第一层后的真实结构

解除伪加密后,flag.zip里解出一个hint.txt和data.zip。hint.txt里写着:

密码由六位数字组成,最后一位是7。去隔壁城邦找找线索。

六位数字、最后一位是7,这意味着密码空间是10^5 = 100000,对于现代机器来说几乎是瞬间就能跑完的事,根本不需要GPU或高端配置。但这里有个重要的判断:遇到数字密码先别急着猜,要看有没有更多约束条件。100000个组合用单核CPU跑也就几十秒,但如果题目改成"八位字母数字混合",那就得考虑更聪明的策略了。

先来看data.zip的大小——大约1.8MB,里面又是一个压缩包。用zipinfo查看,发现里面有个secret.rar,而且data.zip本身有密码。这时候直接上字典爆破是常规操作,但有一个细节非常关键:压缩包里的文件名在未解压时是可见的,不要因为打不开就忽视这些信息,文件名里常常藏着密码的线索。

3.2 工具选择:fcrackzip、john还是hashcat

常用的ZIP密码爆破工具有三款:

  • fcrackzip:老牌工具,简单直接,适合字典和掩码攻击
  • zip2john + john:先把ZIP转换成john格式,再用john跑,支持规则变异
  • hashcat:需要GPU加速,跑纯数字密码属于杀鸡用牛刀,但遇到高强度密码时是必须的

对于六位数字密码,我用fcrackzip加上掩码就够了:

fcrackzip -v -u -c '1' -p '?????7' data.zip

其中-c '1'表示纯数字字符集,-p '?????7'是掩码模式,?代表未知数字,最后一位固定为7。实测不到10秒就出了结果:密码是38157。

这里有个工具选型的经验:爆破ZIP密码的先决条件是判断加密算法。ZIP 2.0传统的ZipCrypto加密可以用GPU暴力破解,但WinZip的AES加密(尤其是AES-256)爆破效率极低。先用zipinfo -v查看加密方式,再决定要不要花时间爆破,比上来就跑工具靠谱得多。

3.3 爆破后可能遇到的"套娃"陷阱

解出data.zip后,里面的secret.rar是RAR格式,依旧有密码。RAR的解密算法和ZIP不一样,无法用zip2john提取,需要用rar2john或RAR John插件。RAR5的加密基于PBKDF2-HMAC-SHA256,爆破速度远慢于ZIP,这也是为什么题目会把RAR放在深层而不是第一层。

我验证了一下secret.rar中是否包含其他数据,但rar2john生成的hash可以用john直接识别:

rar2john secret.rar > secret_hash.txt john --wordlist=rockyou.txt --format=rar5 secret_hash.txt

跑了大约15分钟后,还是没出结果。这时候我意识到可能是思路错了——密码未必是来自字典,更有可能藏在前面解出的文件里。CTF里有一种惯用套路叫"线索串联",前一层解出的内容往往是后一层的钥匙。

我回头翻hint.txt,发现末尾还有一行不起眼的小字:"密码是青岑城邦的缩写,小写,共4位"。所谓"城邦的缩写"指向题目名中的"青岑"二字。RAR密码是qccb,试了一下一次性解开了。

这个环节的教训非常深刻:CTF MISC的压缩包题,90%的密码不需要暴力破解,而是通过线索推理得到的。暴力破解是当找不到线索、或者密码强度明确较低时的兜底方案,而不是首选。我在做过大量题目后,总结出一条经验法则:先花20分钟找线索,再花10分钟跑字典,最后才考虑大规模爆破。

4. 压缩术的进阶玩法:CRC32碰撞与已知明文攻击

4.1 破解出RAR后的关键文件

解开secret.rar后,得到一个flag.txt和一个readme.txt。readme.txt写得很明白:

恭喜你走到这一步。但真正的flag被压缩进了一个加密的ZIP中,你无法直接获得它的明文。压缩包内只有一个文件,内容是Congratulations! Your flag is: xxx。

看到这我基本猜到了,这道题真正想考的是压缩包的已知明文攻击(Known-plaintext Attack)。在ZIP的ZipCrypto加密方案中,如果攻击者知道压缩包内某个文件的全部或部分明文内容,就可以通过已知明文反推加密密钥流,进而解出压缩包内的其他文件。这是ZipCrypto算法的一个经典弱点,也是"压缩术"这个题名真正想表达的东西。

先找到目标文件。final.zip中有flag.txt,但我不知道具体内容。不过根据readme.txt的描述,明文的前缀是已知的:Congratulations! Your flag is:。这一小段已知明文,就构成了攻击的起点。

4.2 bkcrack的使用流程

bkcrack是目前做ZIP已知明文攻击最强大的开源工具,它不需要密码,只需要知道压缩包内某个文件的至少12字节的已知明文(其中至少有8字节是连续且已知的),就能恢复出ZipCrypto的内部密钥。

操作流程分三步:

第一步:准备明文文件

把已知的明文片段写入plain.txt:

echo -n "Congratulations! Your flag is: " > plain.txt

第二步:运行攻击

bkcrack -C final.zip -c flag.txt -p plain.txt

-C指定压缩包,-c指定压缩包内的目标文件名(flag.txt),-p指定已知明文文件。攻击成功后,工具会输出三个32位密钥值,例如2e4b1a5f 89c3027d 5af1b5e8。

第三步:用密钥解密ZIP

得到密钥后,用bkcrack的-k参数直接解出压缩包内的文件:

bkcrack -C final.zip -c flag.txt -k 2e4b1a5f 89c3027d 5af1b5e8 -d flag_decrypted.txt

这个命令会把flag.txt在压缩包内被加密的数据解密出来,保存为flag_decrypted.txt,内容就是完整的flag。

4.3 为什么CRC32碰撞也值得一提

在压缩包题目里,另一个高频考点是CRC32碰撞。和已知明文攻击不同,CRC32碰撞适用于压缩包内文件的内容很短(通常少于5字节),且你大概知道文件内容可能是什么的情况。

ZIP文件头的crc-32字段是明文数据的CRC32校验值,它是未加密的。如果压缩包内某个文件的内容是类似1、233、flag这类罕见或短小的字符串,攻击者可以枚举所有可能的字符串并计算CRC32,与文件头里的CRC32比对,命中后就能还原出明文。

一个典型的场景是:压缩包内有个4字节的key.txt,内容只有4个字符,且你知道它是小写字母和数字的组合。写个脚本枚举所有10^4种组合,几秒就能跑完:

import zipfile import binascii import itertools import string def crc32_crack(zip_path, target_file, charset=string.ascii_lowercase + string.digits, length=4): with zipfile.ZipFile(zip_path) as zf: meta = zf.getinfo(target_file) target_crc = meta.CRC file_size = meta.file_size for combo in itertools.product(charset, repeat=length): data = ''.join(combo).encode() if len(data) == file_size and binascii.crc32(data) & 0xffffffff == target_crc: return data.decode() return None

如果文件内容长度是4字节,CRC32碰撞的确能还原英文单词或数字组合。但如果长度超过6字节,碰撞的计算量会急剧膨胀,这时候就必须转向已知明文攻击或暴力破解了。

5. 常见问题与排查技巧实录

5.1 伪加密判断失败的典型案例

我在复现这道题时,有朋友卡在第一步:他把compress.rar解压出flag.zip后,直接用Windows自带的资源管理器打开,提示需要密码,就以为是真加密,开始跑爆破。跑了一小时没结果,非常浪费时间。

这种现象的根源在于不同解压工具对伪加密的处理逻辑不同。Windows资源管理器在遇到加密标志位为1但实际未加密的文件时,会顽固地要求密码;而7-Zip、WinRAR在部分版本下会尝试忽略标志位直接解压,或提示"文件头错误"但允许继续。所以遇到"有密码但打不开"的压缩包,先换工具试试,再决定是否爆破,永远是第一步。

5.2 暴力破解RAR5时的性能陷阱

如果暴力破解RAR5,要注意john或hashcat的迭代次数设置。RAR5默认的PBKDF2迭代次数是32768次,但有些工具会自动降低或提高,直接影响破解速度。在实际操作中,RAR5的破解速度大约是每秒几千次,而ZIP 2.0的ZipCrypto是每秒几百万次,两者差了三个数量级。

所以在CTF题里碰到RAR加密,基本上可以断定出题人不是想让你爆破了,而是希望你去寻找线索或采用更巧妙的攻击方式。真遇到必须爆破RAR的场景,应该优先确认是不是RAR4格式,RAR4的破解速度会快很多。

5.3 压缩包内隐藏数据的其他检查点

压缩包题除了加密和嵌套,还喜欢在以下位置藏东西:

  • 文件注释:zipinfo -z查看注释,有些flag直接写在注释里
  • 文件时间戳:某些题目会通过修改时间戳编码信息,比如秒数对应ASCII码
  • ZIP冗余数据:文件头和数据之间可能存在填充数据,用binwalk或foremost可以提取出来
  • NTFS ADS流:如果在Windows环境下处理,压缩包解压后的文件可能带Alternate Data Streams,内容藏在里面
  • 压缩流末尾的额外数据:用dd手动把压缩数据之后的字节截取出来

快速全检的命令我已经写成了一个小脚本,核心思路就是先看文件头、再看注释、再看尾部、最后看时间戳,四步走完基本能覆盖绝大部分隐藏套路。

5.4 工具链的完整清单

为了方便实战,我把最常用的工具清单贴在下面,供参考:

工具用途备注
binwalk检测文件类型、提取附加数据会自动识别压缩包和其他格式
foremost从文件中提取各种格式数据适合恢复被删除或隐藏的文件
zipinfo/unzip -l查看ZIP内部结构、加密标志、注释快速判断伪加密
7z通用解压工具对伪加密有一定容错
fcrackzipZIP密码字典/掩码爆破轻量级,适合数字密码
zip2john+johnZIP爆破的标配组合支持规则变异
rar2john+johnRAR爆破注意RAR5速度慢
bkcrackZIP已知明文攻击压缩术题的核心利器
crc32脚本CRC32碰撞自己写或用现成脚本
010 Editor十六进制查看与编辑手动修改文件头必备

我一直觉得,工具只是辅助,真正重要的是脑子里对压缩包格式结构的理解。把ZIP的本地文件头、中央目录、EOCD记录这三个结构吃透,再看压缩包题就会非常通透。

6. 从"压缩术"看CTF出题思路

6.1 这道题考点的完整串联

整道"青岑CTF MISC 城邦:压缩术"题目,把压缩包相关的考点按难度递增做了非常漂亮的编排:

  • 第一层:RAR解压,考察基本操作和干扰信息识别(fake_flag_is_here)
  • 第二层:ZIP伪加密,考察对ZIP文件格式底层结构的掌握
  • 第三层:ZIP密码爆破,考察掩码攻击和线索推理(数字密码)
  • 第四层:RAR密码推理,考察对题目上下文和提示信息的关联能力
  • 第五层:ZIP已知明文攻击,这是终极考点,考察对ZipCrypto算法弱点的理解

每一层都在教你一种处理压缩包的技术手段,而最后一层把难度拉到了真正偏门但实战中极其实用的高度。这种由浅入深的嵌套设计,让选手在解出每一层时都有成就感,同时对整体方向保持清晰的认知,我认为这是CTF题目设计里最成功的结构之一。

6.2 为什么出题人喜欢考压缩包

压缩包在MISC里出现频率极高,主要原因是它天然自带"多层容器"的属性,可以嵌套各种类型的问题。而且压缩包格式本身设计历史悠久,包含了很多遗留的兼容性特征,这些特征变成了天然的藏匿点和漏洞点。伪加密、已知明文攻击、CRC32碰撞,本质上都是对压缩格式细节的巧妙利用。

另外,压缩包题目非常适合做"线索分发"。每解开一层就给一点提示,再继续下一层,玩家的注意力可以一直被牵引到题目最终目标上。这种进阶式的体验设计是CTF最受欢迎的类型之一,不会像纯隐写题那样容易卡死,也不会像Web题那样对方向性要求太高。

6.3 压缩术题目的扩展方向

如果这道题继续出下去,我认为还有几个方向可以做:

  • 压缩炸弹(Zip Bomb):高压缩比恶意压缩包,考察选手的资源管理意识和安全敏感性
  • ZIP明文恢复:利用压缩包中被压缩的已知内容恢复未加密数据的更多细节
  • 多压缩算法混合:ZIP、RAR、7z、tar.xz、gzip交替嵌套,考察解压工具链的熟练度
  • 基于压缩比的侧信道:某些场景下,通过观察压缩包内文件压缩后的体积推断明文内容

我自己做过几百道MISC题后,最深的一个感受是:压缩包题万变不离其宗,核心就三件事——文件格式、加密原理、数据隐藏。把这三个问题想清楚,不管出题人怎么嵌套怎么变形,最终都能找到突破口。

7. 实操中的高频疑问速查

现象可能原因处理方式
压缩包提示输入密码,但7z能解压伪加密用010 Editor修改加密标志位,或用7z直接解压
爆破ZIP速度极慢加密算法可能是AES而非ZipCryptozipinfo -v查看加密方法,考虑其他思路
RAR5密码爆破一直不出结果RAR5迭代次数高,破解慢优先找线索推理,不建议长时间爆破
已知明文攻击报"data too short"已知明文长度不足8字节增加已知明文长度,或换用CRC32碰撞
压缩包内文件名乱码文件名可能被编码成非UTF-8用strings或十六进制查看真实文件名
解压后flag.txt显示为空白文件内容可能是Base64或二进制用xxd查看原始字节
ZIP有密码但文件列表可见伪加密或部分加密尝试空密码解压,观察报错差异

这个表格里的内容,绝大部分是我在真实做题和给新人带训过程中反复遇到的情况。压缩包题看起来简单,但细节处全是坑。

回到"压缩术"这道题本身,我最满意的收获并不只是解出了flag,而是完整复习了ZIP格式的字节级结构和ZipCrypto的攻击方式。这类底层知识在实战渗透、取证分析中也有很强的迁移价值——比如在取证工作中遇到加密容器或可疑压缩包,同样要识别伪加密、尝试已知明文攻击,思路是完全相通的。

如果非要给新人一个建议:拿到压缩包题,先花20分钟把文件结构看透,再把提示信息全部列出来,最后才考虑爆破。CTF里最贵的东西从来不是GPU算力,而是看透出题人意图的那双眼睛。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询