CTF中ZIP真伪加密如何识别并提取明文密码?
在CTF比赛中,常出现“ZIP真伪加密”陷阱:文件看似启用密码保护(如`encrypted.zip`中文件头`0x01`标志置位、`central directory`显示`general purpose bit flag & 0x01 == 1`),但实际未加密——即**伪加密(Fake Encryption)**。其本质是篡改ZIP结构中某两处关键字段:① Local File Header 的 `general purpose bit flag` 被设为0x01(误导解压工具认为已加密);② Central Directory 中对应条目的同一标志位也被同步篡改,但**所有加密相关字段(如`file data`前无PKCS#5填充、无CRC校验绕过、压缩数据未混淆)均保持明文原始形态**。识别关键点:用`binwalk -e`或`xxd`检查`0x01`标志是否孤立存在;比对Local Header与Central Directory的flag一致性;若`file data`可直接`strings`/`hexdump`读出有效文本或常见密码特征(如`flag{...}`、`admin123`),即为伪加密。提取只需用`zip -F`修复或手动清零flag字节(偏移0x6处第2字节),再用`unzip -p`直取明文内容。
- 写回答
- 好问题 0 提建议
- 关注问题
- 邀请回答
-
1条回答 默认 最新
祁圆圆 2026-04-11 22:06关注```html一、ZIP伪加密现象:从表象到本质的认知跃迁
在CTF逆向与取证类赛题中,“
encrypted.zip”常是首个心理陷阱——文件名暗示强加密,但unzip提示“password required”,而strings encrypted.zip | grep -i flag却直接输出flag{z1p_f4k3_3ncr7pt10n_1s_n0t_r34l}。这揭示了ZIP格式设计中的一个关键安全盲区:**标志位可篡改,但加密逻辑不可绕过**。ZIP规范(APPNOTE-6.3.2)明确指出:general purpose bit flag & 0x01 == 1仅表示“使用传统PKWARE加密”,并不强制执行加密流程。攻击者利用该语义漏洞,仅翻转标志位而不加密数据,形成“视觉加密”。二、ZIP结构双源一致性校验:Local Header vs Central Directory
伪加密的判定核心在于两处标志位的同步篡改与数据真实性的割裂:
- Local File Header:偏移
0x06处2字节general purpose bit flag(小端序),第0比特(LSB)置1 → 值为0x01或0x09等含bit0=1的组合 - Central Directory Entry:对应文件条目中偏移
0x06同样位置,必须与Local Header完全一致
若二者一致且均为
0x01,但file data起始位置(Local Header后filename length + extra field length字节)紧接原始压缩流(如以0x1f 0x8b开头为gzip,或0x50 0x4b 0x03 0x04后直接明文ZIP子项),即构成伪加密铁证。三、技术验证四步法:自动化与手工交叉验证
步骤 命令/操作 预期现象(伪加密) ① 结构扫描 binwalk -e encrypted.zip输出 DECIMAL HEXADECIMAL DESCRIPTION含0 0x0 Zip archive data,且无加密警告② 十六进制定位 xxd encrypted.zip | head -20Local Header首4字节 50 4b 03 04后,0000000: 504b 0304 0a00 0000 0000 0000 0000 0000 PK............→ 第6字节(0-indexed)为0x0a(即0b00001010,bit0=0)?若为0x0b(0b00001011)则bit0=1③ 数据可读性测试 dd if=encrypted.zip bs=1 skip=$(($OFFSET+30)) | strings -n 4 | head -5输出大量ASCII文本、base64片段、或 flag{...}等CTF特征字符串④ CRC32比对 unzip -lv encrypted.zip | grep -E "(Name|CRC)"显示CRC值;用 zlib-flate -uncompress解压对应file data后计算CRC,与Central Directory中记录值一致 → 证明未加密四、修复与提取:三种生产级解决方案
针对已确认伪加密的ZIP,提供工业强度修复路径:
- zip -F 自动修复:
zip -F encrypted.zip --out fixed.zip && unzip -p fixed.zip | strings—— 利用Info-ZIP内置逻辑重写标志位 - 十六进制手动清零:用
hexedit encrypted.zip定位每个Local Header(50 4b 03 04)后第6字节,将其由0x01/0x09/0x11改为0x00/0x08/0x10(保持其他比特不变),再同理修改Central Directory对应位置 - Python脚本化批量处理:
import struct
with open('encrypted.zip','r+b') as f:
data = f.read()
for i in range(len(data)-4):
if data[i:i+4] == b'\x50\x4b\x03\x04':
# Local Header flag at offset i+6
if data[i+6] & 0x01:
f.seek(i+6)
f.write(bytes([data[i+6] & 0xfe]))
五、防御视角:如何构造真加密ZIP规避误判
作为出题人或红队工程师,需理解真加密ZIP的不可绕过特征:
- 加密后
file data前必有12字节PKCS#5 salt + 2字节checksum(0x0000起始) - CRC32字段在Central Directory中被置为
0x00000000(因加密后无法预计算) - 使用
7z a -p123456 encrypted.7z payload.txt生成的7z包不具此陷阱,但ZIP标准加密(-P)需zip -P pass file.txt且依赖OpenSSL兼容实现
六、深度溯源:ZIP规范与工具链信任边界分析
为何
unzip不校验加密真实性?因POSIX unzip实现遵循“最小假设原则”:仅解析标志位即触发密码交互,将解密责任移交用户。而binwalk的熵值分析(-E)可暴露伪加密——真实加密数据熵值≈7.99,而伪加密ZIP中压缩数据熵值仅≈6.2(LZ77冗余残留)。下图展示CTF典型ZIP解析决策流:graph TD A[输入ZIP文件] --> B{是否含0x504b0304} B -->|否| C[非ZIP格式] B -->|是| D[定位Local Header] D --> E[读取offset 0x06 flag] E --> F{flag & 0x01 == 1?} F -->|否| G[尝试直接解压] F -->|是| H[启动密码交互] H --> I{用户输入密码} I --> J[调用PKWARE解密引擎] J --> K{解密后CRC校验通过?} K -->|是| L[输出明文] K -->|否| M[报错“invalid password”] M --> N[但实际无需密码:伪加密]```本回答被题主选为最佳回答 , 对您是否有帮助呢?解决 无用评论 打赏 举报- Local File Header:偏移