misc总结(压缩文件篇)

ZIP文件

ZIP通常使用后缀名.zip,它的MIME格式为application/zip

文件结构分析

引用官方文档中对于一个标准zip文件组成部分的描述:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[local file header 1]
[file data 1]
[data descriptor 1]
.
.
.
[local file header n]
[file data n]
[data descriptor n]
[archive decryption header] (EFS)
[archive extra data record] (EFS)
[central directory]
[zip64 end of central directory record]
[zip64 end of central directory locator]
[end of central directory record]

为了演示结构,首先创建一个flag.txt,分别压缩成flag1.zip(无密码)flag2.zip(有密码)(使用的是winrar默认参数压缩)

推荐使用010 editor分析

先看flag1.zip

大致可以分为三个部分:local file header + file data + data descriptorcentral directory以及一个end of central directory record组成(对应图中的三种颜色)

文件头(Local file header)

字段名称 长度(byte) 说明
Local file header signature 4 文件头标识,固定值(50 4B 03 04)
Version needed to extract 2 解压文件所需的ZIP最低版本
General purpose bit flag 2 通用位标志,通常只需要考虑当bit 0为1时表示文件被加密
Compression method 2 压缩方式,当值为:0x0000时表示无压缩
Last mod file time 2 文件最后修改时间,以standard MS-DOS格式编码
Last mod file date 2 文件最后修改日期
CRC-32 4 未压缩数据的CRC32
Compressed size 4 压缩后的大小,单位为byte
Uncompressed size 4 未压缩的大小
File name length 2 文件名长度
Extra field length 2 扩展区域长度
File name N 文件名
Extra field N 扩展区域

文件数据(File data)

应将文件的压缩或存储数据紧随在文件头(Local File Header)后。如果文件已加密,则文件的加密头(encryption header)应放置在本地文件头(Local File Header)之后和文件数据之前。

对于.ZIP压缩文档中的每个文件,重复执行一系列的[文件头][加密头][文件数据][数据描述符]结构。

数据描述符(Data descriptor)

字段名称 长度(byte) 说明
Optional data descriptor signature 4 (可选的)数据描述符标识,固定值(50 4B 07 08)
CRC-32 4 未压缩数据的CRC32
Compressed size 4 压缩后的大小
Uncompressed size 4 未压缩的大小

如果设置了通用位标志的位3,则该描述符必须存在,它按字节对齐,紧随压缩数据的最后一个字节,仅在无法在输出的.ZIP文件中查找时(例如,当输出.ZIP文件是标准输出或不可搜索的设备时),才应使用此描述符

例如flag2.zip中的绿色部分

核心目录(Central directory)

Central directory包括File headerDigital signature

文件头:

字段名称 长度(byte) 说明
Central directory file header signature 4 中心目录文件头标识,固定值(50 4B 01 02)
Version made by 2 压缩所用的ZIP版本
Version needed to extract 2 解压文件所需的ZIP最低版本
General purpose bit flag 2 通用位标记
Compression method 2 压缩方法
Last mod file time 2 文件最后修改时间
Last mod file date 2 文件最后修改日期
CRC-32 4 未压缩数据的CRC32
Compressed size 4 压缩后的大小
Uncompressed size 4 未压缩的大小
File name length 2 文件名长度
Extra field length 2 扩展区域长度
File comment length 2 文件注释长度
Disk number start 2 文件开始位置所在的磁盘编号
Internal file attributes 2 内部文件属性
External file attributes 4 外部文件属性
Relative offset of local header 4 本地文件头的相对偏移
File name N 文件名
Extra field N 扩展区域
File comment N 文件注释

数字签名:
此区域不是必须的

字段名称 长度(byte) 说明
Header signature 4 头标识,固定值(50 4B 05 05)
Size of data 2 数据的大小
Signature data N 签名数据

目录结束标识(End of central directory record)

字段名称 长度(byte) 说明
End of central directory signature 4 中心目录结束标识,固定值(50 4B 05 06)
Number of this disk 2 当前磁盘编号
Number of the disk with the start of the central directory 2 中心目录开头所在的磁盘号
Total number of entries in the central directory on this disk 2 该磁盘上中心目录的条目总数
Total number of entries in the central directory 2 中心目录的条目总数
Size of the central directory 4 中心目录的大小
Offset of start of central directory with respect to the starting disk number 4 中心目录开始位置相对于压缩文档开始位置的偏移
.ZIP file comment length 2 .ZIP文件注释长度
.ZIP file comment N .ZIP文件注释

常见考点

伪加密

伪加密可以说是非常常见,基础的考点了,正如名字中的,它本身并没有加密,但是通过修改通用位标记,可以使得解压软件认为这个文件存在加密

例题:BUU-zip伪加密

可以看到是需要密码的

010 editor查看,修改通用位标记0x0000

修改后可以直接解压了

暴力破解

使用工具(archpr)或者脚本(python)对压缩包进行暴力破解密码

基本可以分为纯暴力掩码字典

纯暴力:一般是弱口令或者纯数字

掩码:知道了密码的一部分,用掩码进行爆破。例如??ert??可以去匹配中间为ert的密码

字典:用题目中给出的或自己的弱口令字典去跑

CRC32碰撞

每个文件都有唯一的CRC32值,即使文件中有个一个bit发生了变化,CRC32值也会不同

CRC32爆破就是知道文件中一段数据的长度和文件的CRC32值,通过脚本程序,利用穷举法,与其CRC32对照,从而达到猜解数据的目的(通常只适用于较小的文本文件,文件太大穷举难度太大)

例题:BUU-zip

github脚本1
github脚本2

下载附件,解压得到68个压缩包,并且每个压缩文件里都有一个4个字节大小的名为data.txttxt文件,于是尝试用crc32碰撞还原出所有压缩包中的文件内容

得到一串base64编码后的字符串,解压后修复压缩包得到flag

明文攻击

明文攻击是一种较为高效的攻击手段,大致原理是当你不知道一个zip的密码,但是你有zip中的一个已知文件(文件大小要大于12Byte)时,因为同一个zip压缩包里的所有文件都是使用同一个加密密钥来加密的,所以可以用已知文件来找加密密钥,利用密钥来解锁其他加密文件。

注意:明文对应文件的加密算法需要是ZipCrypto Store(linux下可以用unzip -v等命令查看)

ZIP 明文攻击原理

例题:BUU-[ACTF新生赛2020]明文攻击

深入明文攻击-bkcrack

上个例子的明文攻击使用的是完整的文件,但是有时候没有文件,只知道加密文件的一部分字节数据(至少12个字节及偏移),这时候如果满足加密算法(ZipCrypto Store)条件,就可以使用深入明文攻击

例题:2022西湖论剑-take_the_zip_easy

已知算法为ZipCrypto Store,且有一个zip文件,就可以得知文件头为504B030414000000

echo -n "dasflow.pcapng" > plain.out
./bkcrack -C zipeasy.zip -c dasflow.zip -p plain.out -o 30 -x 0 504B030414000000

参数解释:

1
2
3
4
5
-C 加密压缩包
-c 提取的密文部分
-p 提取的明文部分
-o offset -p参数指定的明文在压缩包内目标文件的偏移量
-x 压缩包内目标文件的偏移地址 部分已知明文值

-o30是因为在zip格式中第三十位固定为压缩文件的名字

拿到key:2b7d78f3 0ebcabad a069728c,这个还不是真正的密码

通过key修改密码为easy,保存到easy.zip
./bkcrack -C zipeasy.zip -k 2b7d78f3 0ebcabad a069728c -U easy.zip easy

双密码

在启用 AES-256 模式生成受密码保护的 ZIP 存档时 ,如果密码太长,ZIP 格式会使用 PBKDF2 算法并对用户提供的密码进行 hash 处理。在这种情况下,这个新计算的 hash 将会成为文件的实际密码。太长是指超过 64 个字节(字符)。

例子:

Nev1r-G0nna-G2ve-Y8u-Up-N5v1r-G1nna-Let-Y4u-D1wn-N8v4r-G5nna-D0sert-You

对应的 sha1 值

706b4838613041714e62486364773847726d5370

将每两位转成 ASCII 码,就产生了另一个明文密码

pkH8a0AqNbHcdw8GrmSp

RAR文件

文件结构分析

RAR不同于ZIP,RAR是一种专利文件格式
2.0 版本前加密算法未公开,2.0 版本后使用AES算法加密

RAR 5.0签名和RAR4.x的签名不一样:

1
2
3
4
5
RAR 5.0 签名由8个字节组成:
0x52 0x61 0x72 0x21 0x1A 0x07 0x01 0x00

RAR 4.x 签名由7字节组成:
0x52 0x61 0x72 0x21 0x1A 0x07 0x00

因为rar是商业格式,所以不同软件不同版本所压缩出来的可能会有细微差别,可以参考010中的rar模板

本文以RAR4.x为例子,可以大致分为四部分

标记块(MARK_HEAD)

字段名称 长度(byte) 说明
HEAD_CRC 2 总是0x6152
HEAD_TYPE 1 0x72
HEAD_FLAGS 2 总是0x1A21
HEAD_SIZE 2 块大小 = 0x0007,即7个字节

所以这里标记块的大小固定是7个字节,且是一个固定的字节序列。标记块也称为Magic number。

压缩文件头(MAIN_HEAD)

字段名称 长度(byte) 说明
HEAD_CRC 2 HEAD_TYPE到RESERVED2的CRC
HEAD_TYPE 1 0x73
HEAD_FLAGS 2 位标记
HEAD_SIZE 2 压缩文件头总大小(包括压缩文件注释)
RESERVED1 2 保留
RESERVED2 4 保留

对于压缩文件头里的位标记,如果它的第9位(从左到右)被置1(则位标记应为0x0080),块头被加密,也就是通常所说的加密文件名,打开这样加密的RAR文件时,需要先输入密码才能看到压缩包内的文件列表

文件头(FILE_HEAD)

字段名称 长度(byte) 说明
HEAD_CRC 2 从HEAD_TYPE到FILE_NAME的CRC
HEAD_TYPE 1 0x74
HEAD_FLAGS 2 位标记
HEAD_SIZE 2 文件头的全部大小(包含文件名和注释)
PACK_SIZE 4 已压缩文件大小
UNP_SIZE 4 未压缩文件大小
HOST_OS 1 保存压缩文件使用的操作系统
FILE_CRC 4 文件CRC
FTIME 4 MS DOS标准格式的日期和时间
UNP_VER 1 解压文件所需要最低RAR版本,版本编码方法:10 * 主版本 + 副版本。
METHOD 1 压缩方式
NAME_SIZE 2 文件名大小
ATTR 4 文件属性
HIGH_PACK_SIZE 4 可选值,已压缩文件大小64位值的高4字节。只HEAD_FLAGS中的0x100位被设置才存在。
HIGH_UNP_SIZE 4 可选值,未压缩文件大小64位值的高4字节。只有HEAD_FLAGS中的0x100位被设置才存在。
FILE_NAME NAME_SIZE 文件名 - NAME_SIZE字节大小字符串
SALT 8 可选值,如果(HEAD_FLAGS & 0x400)!= 0,则存在
EXT_TIME 可变大小 可选值,扩展时间区域,如果(HEAD_FLAGS & 0x1000)!= 0,则存在

在这个块中,存在两个CRC值,一个是文件头块中从块类型到文件名的校验,后一个则是压缩包中所含文件的CRC校验,解压时,会计算解压后生成文件的CRC值,如果等于这里的CRC,则解压完成,如果不同,则报错中断。

结尾块(ENDARC_HEAD)

字段名称 长度(byte) 说明
HEAD_CRC 2 从HEAD_TYPE 到HEAD_SIZE 的CRC校验值
HEAD_TYPE 1 0x7B
HEAD_FLAGS 2 位标记
HEAD_SIZE 2 结尾块大小

与标记块类似的是,结尾块也是一个固定字节串的块,依次是C4 3D 7B 00 40 07 00

常见考点

暴力破解

比如:

rar2john先提取hash
$rar5$16$6385fa42c4d3cb1318e1ea71c1dcbfa3$15$cc4e558d99f6c846eb0fc54073e2293c$8$03d8cf03ed478602

hashcat爆破密码
hashcat -m 13000 -a 3 $rar5$16$6385fa42c4d3cb1318e1ea71c1dcbfa3$15$cc4e558d99f6c846eb0fc54073e2293c$8$03d8cf03ed478602 ?u?u?u?u?u?u

伪加密

rar在伪加密状态下会显示压缩包已损坏或压缩格式未知,所以很容易判断rar是否是伪加密

修改FILE_HEAD中的HEAD_FLAGS即可

例题:BUU-[VNCTF 2021]冰冰好像藏着秘密

一打开就是一堆报错

修改第24字节为80即可正常打开

其他

Zipbomb

压缩包炸弹,利用压缩算法的特性,做到仅仅几kb和仅mb的压缩包文件,解压出来GB,甚至PB级的数据

python脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import os.path
import zipfile
import re

dir_path='C:\\Users\\19307\\Desktop\\11aa\\a'
files= os.listdir(dir_path)
newfiles = files[::-1]
print(newfiles)

for file in newfiles:
position = dir_path+'\\'+ file
print (position)
z = zipfile.ZipFile(position, 'r')
for filename in z.namelist():
bytes = z.read(filename)
if b'Zmxh' in bytes or b'flag' in bytes:
print(filename)

例题:BUU-DASCTF Sept X ZipBomb

参考
ZIP文件格式分析
ZIP官方文档 - APPNOTE-6.3.6.TXT
RAR文件格式分析
RAR-wiki


misc总结(压缩文件篇)
https://www.dr0n.top/posts/ff5ac082/
作者
dr0n
发布于
2022年7月2日
更新于
2024年6月15日
许可协议