一、zip文件格式格式分析
官方文档地址zip文件规范
Overall .ZIP file format:
[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]
1.1 文件头(Local file header)
Offset | Length | Description | 说明 | 备注 |
---|---|---|---|---|
0 | 4 | local file header signature | 文件头标识 | 0x04034b50 |
4 | 2 | version needed to extract | 解压文件所需版本 | |
6 | 2 | general purpose bit flag | 通用位标记 | Bit 0加密标志,Bit 3数据描述标志 |
8 | 2 | compression method | 压缩方式 | |
10 | 2 | last mod file time | 文件最后修改时间 | |
12 | 2 | last mod file date | 文件最后修改日期 | |
14 | 4 | crc-32 | CRC-32校验码 | |
18 | 4 | compressed size | 压缩后的大小 | |
22 | 4 | uncompressed size | 未压缩的大小 | |
26 | 2 | file name length | 文件名长度 | 假设文件名长度为n |
28 | 2 | extra field length | 扩展区长度 | 假设扩展区长度为m |
30 | n | file name | 文件名 | |
30+n | m | extra field | 扩展区 |
1.2 文件数据(File data)
紧跟在文件的本地头之后是文件的压缩或存储数据。
1.3 数据描述(Data descriptor)
数据描述只有在通用位标记的第3bit设为1时才会出现,紧接在压缩文件源数据后。数据描述只用在不能对输出的 ZIP 文件进行检索时使用。例如:在一个不能检索的驱动器(如:磁带机上)上的 ZIP 文件中。
Offset | Length | Description | 说明 | 备注 |
---|---|---|---|---|
0 | 4 | data descriptor signature | 数据描述标识 | 0x08074b50 |
4 | 4 | crc-32 | CRC-32校验码 | |
8 | 4 | compressed size | 压缩后的大小 | |
12 | 4 | uncompressed size | 未压缩的大小 |
1.4 文档解密头(Archive decryption header)
文档解密头在版本6.2中引入做为ZIP格式规范,用于支持核心目录加密功能的强加密规范。当核心目录结构加密时,此解密头将位于加密数据段之前。加密的数据段将包括文档额外数据记录以及加密的核心目录结构数据。如果核心目录结构已加密,此数据记录的起始位置由Zip64核心目录记录结尾中的字段核心目录开始位置确定。
1.5 文档额外数据记录(Archive extra data record)
文档额外数据记录在版本6.2中引入做为ZIP格式规范,用于支持核心目录加密功能的强加密规范。此记录在核心目录数据结构之前。此数据记录的大小包含在核心目录记录结束中的字段核心目录大小。如果核心目录结构是压缩但不是加密的,此数据记录起始位置由Zip64核心目录记录结尾中的字段核心目录开始位置确定。
Offset | Length | Description | 说明 | 备注 |
---|---|---|---|---|
0 | 4 | archive extra data signature | 0x08064b50 | |
4 | 4 | extra field length | 扩展区长度 | 假设扩展区长度为m |
8 | m | extra field data | 扩展区数据 |
1.6 核心目录(Central directory)
[file header 1]
.
.
.
[file header n]
[digital signature]
随着版本6.2中核心目录加密功能的引入,核心目录结构可以压缩和加密存储。虽然不是必需的,但随着加密核心目录结构,它将被压缩以提高存储效率。数字签名记录既不压缩也不加密。
(A)文件头(File header)
Offset | Length | Description | 说明 | 备注 |
---|---|---|---|---|
0 | 4 | central file header signature | 核心目录文件头标识 | 0x02014b50 |
4 | 2 | version made by | 压缩所用版本 | |
6 | 2 | version needed to extract | 解压所需版本 | |
8 | 2 | general purpose bit flag | 通用位标记 | |
10 | 2 | compression method | 压缩方法 | |
12 | 2 | last mod file time | 文件最后修改时间 | |
14 | 2 | last mod file date | 文件最后修改日期 | |
16 | 4 | crc-32 | CRC-32校验码 | |
20 | 4 | compressed size | 压缩后的大小 | |
24 | 4 | uncompressed size | 未压缩的大小 | |
28 | 2 | file name length | 文件名长度 | 假设文件名长度为n |
30 | 2 | extra field length | 扩展区长度 | 假设扩展区长度为m |
32 | 2 | file comment length | 文件注释长度 | 假设文件注释长度为k |
34 | 2 | disk number start | 文件开始位置的磁盘编号 | |
36 | 2 | internal file attributes | 内部文件属性 | |
38 | 4 | external file attributes | 外部文件属性 | |
42 | 4 | relative offset of local header | 本地文件头的相对位移 | |
46 | n | file name | 文件名 | |
46+n | m | extra field | 扩展区 | |
46+n+m | k | file comment | 文件注释 |
(B)数字签名(Digital signature)
Offset | Length | Description | 说明 | 备注 |
---|---|---|---|---|
0 | 4 | header signature | 头标识 | 0x05054b50 |
4 | 2 | size of data | 数据大小 | 假设数据大小为n |
6 | n | signature data | 标识数据 |
1.7 Zip64核心目录记录(Zip64 end of central directory record)
以下结构定义了Zip64核心目录记录结束的版本1。版本1是在本规范之前的版本中实现支持6.2版本ZIP64大文件功能。这个核心中心目录加密功能介绍作为强加密的一部分,在版本6.2中规范定义了此记录结构的版本2。
Offset | Length | Description | 说明 | 备注 |
---|---|---|---|---|
0 | 4 | zip64 end of central dir signature | 0x06064b50 | |
4 | 8 | size of zip64 end of central directory record | ||
12 | 2 | version made by | ||
14 | 2 | version needed to extract | ||
16 | 4 | number of this disk | ||
20 | 4 | number of the disk with the start of the central directory | ||
24 | 8 | total number of entries in the central directory on this disk | ||
32 | 8 | total number of entries in the central directory | ||
40 | 8 | size of the central directory | ||
48 | 8 | offset of start of central directory with respect to the starting disk number | ||
56 | zip64 extensible data sector |
1.8 Zip64核心目录位置(Zip64 end of central directory locator)
Offset | Length | Description | 说明 | 备注 |
---|---|---|---|---|
0 | 4 | zip64 end of central dir locator signature | 0x07064b50 | |
4 | 4 | number of the disk with the start of the zip64 end of central directory | ||
8 | 8 | relative offset of the zip64 end of central directory record | ||
16 | 4 | total number of disks |
1.9 核心目录结束(End of central directory record)
Offset | Length | Description | 说明 | 备注 |
---|---|---|---|---|
0 | 4 | end of central dir signature | 核心目录结束标记 | 0x06054b50 |
4 | 2 | number of this disk | 当前磁盘编号 | |
6 | 2 | number of the disk with the start of the central directory | 核心目录开始位置的磁盘编号 | |
8 | 2 | total number of entries in the central directory on this disk | 该磁盘上所记录的核心目录数量 | |
10 | 2 | total number of entries in the central directory | 核心目录结构总数 | |
12 | 4 | size of the central directory | 核心目录的大小 | |
16 | 4 | offset of start of central directory with respect to the starting disk number | 核心目录开始位置相对位移 | |
20 | 2 | .ZIP file comment length | 注释长度 | 假设注释长度为n |
22 | n | .ZIP file comment | 注释内容 |
二、实战分析
2.1 题目
题目名称:MISC600
题目描述:宇宙的一切的答案就是32
2.2 解题分析
日常binwalk分析图片,发现有32.txt文件,内容如下:
GUYDIQRQGMYDIMCBGAYDAOJQGAYDAMBQGQ7DIOJQIE7DON7FHBBEENK
GGQYTEMBQGAYDAMBQGYYDAMBQGAYDANJQGAYDAMBQGY6DERJXGQ6T
QNZUGE6TCNRVGE5EIQZXGJCTIOKEIZBDQRCCGMYTMMZRII7UIQKFIM7DE
RRZGA7TANCCGA6TAOBXIU5EEQRVIY7DCMRQGAYDAMBQGA6DAMBQGAYD
ANJQGRBDAMZQGQYECMBQGA5TAMBQGAYDANJTGQ5TAQJUG4BTQNZUIF
AUCNJRGIYDAMBQGAYDANRQGAYDAMBQGA7TAMBQGAYDANSDGJCTONB
XHA6TIMJXGE6DKMJYIRBTOMSFGQ5UIRSCHBCEEMRWGFBECQJSGRBTMQ
JWINBDGQRVGA7EEMBXGA5EGOBXGRAUCQJVGEZDAMBQGAYDAMBWGAY
DAMBQGA7TANCCGAZTANBQIEYDAMBZGAYDAMBQGAZTINRSGBATINZUGV
CDMMBQIMYTCMRQGAYDAMBQGA6DAMBQGAYDAMBVGAYDAMBQGA6DCM
SFG57DOOBXGQYTOMJWGUYTQRCDG5ZEKNBZIRDEEOCEII7DCNCBGAZTE
QJSGU6UERJSIY5TKMBUIIYDOMBYGQ7UINRQGBBTCMJSGAYDAMBQGAYD
MMBQGAYDAMBVGA7EEMBTGA7DAQJQGAYDSMBQGAYDAMBXIQ7DSMCBG
Q6TMNBSINBECRKFGEZDAMBQGAYDAMBWGAYDAMBQGAYDKMBQGAYDAM
BWG5ZEKNZUG55DONBRG5YTMNJRHBCEGNZSIU7DSRCGII5EIQRQHAYECM
BWGZDEMMBSIZDEKQZVGUYDIQRQG5YDQNRUGJBUEQKFIUYTEMBQGAYD
AMBQGYYDAMBQGAYDKMBUIIYDCMBSGE7DAMBQIEYDAMBZGAYDAMBQGA
7DINBZGBATINZXIU5EEQRVIY7DCMRQGAYDAMBQGA6DAMBQGAYDAMBVGA
YDAMBQGAYDAMBQGAYDAMBQGEYDAMRQGAYDAMBQGAYDAMBQGAYDA
MBWGYZEKNZUG55DONBVGA7EEMBRGAZDCNBQGAYECMBQGA5TAMBQGA
YDANJTGQ5TAQJUG4BTQNZUIFAUCNJRGIYDAMBQGAYDANRQGAYDAMBQG
A7TAMBQGAYDAMBQGAYDAMBQGAYDCMBQGIYDAMBQGAYDANBVGAYDAM
BQGA6EGMSFG57DOOBXGQ7TANCCGAYTAMRRGQYDAMCBGAYDAOJQGAY
DAMBQGM7DMMRQIE7DONBVIQ6DAMCDGEYTEMBQGAYDAMBQGYYDAMBQ
GAYDANJQGAYDAMBQGAYDAMBQGAYDAMBRGAYDEMBQGAYDAMBQHBATA
MBQGAYDANRRGJCTONBXHA6TINJQGRBDAMJQGIYTIMBQGBATAMBQHEYD
AMBQGAYDORBUHEYECNBXGY7DEQ7CIFCUKMJSGAYDAMBQGAYDMMBQG
AYDAMBQGUYDAMBQGAYDAMBQGAYDAMBQGAYTAMBSGAYDAMBQGAYEG
RRQGAYDAMBQGY6TERJXGQ6TQNZUGUYDIQRQGUYDMMBQGAYDAMBQGA
YDIMBQGA7DAMCDIMYDAMBQGAYDCNBQGEYDAMBQGAYDAMA=
观察字符包含大写字母和数字4-7,判断其为base32加密,解密后结果如下:
# 第一组 文件头+文件数据+数据描述(共69字节)
504B0304 0A00 0900 0000 4>49 0A>7 7\xe58BB5F4 12000000 06000000 0500 0000 6<2E74=874
1=1651:DC72E49DFB8DB31631B?DAEC>2F90
?04B0=08 7E:BB5F> 12000000 0<000000
# 第一组 文件头+文件数据+数据描述(共69字节)
504B0304 0A00 0;00 0000 534;0A47 \x03874AAA5 12000000 06000000 0?000000 6C2E7478=4
171<518DC72E4;DFB8DB261BAA24C6A6CB3B
50>B070: C874AAA5 12000000 06000000
# 第三组 文件头+文件数据+数据描述(共69字节)
?04B0304 0A00 0900 0000 3462 0A47 45D600C1 12000000 0<000000 0500 0000 <12E7~7874
1716518DC7rE49DFB8DB>14A032A25=BE2F;
504B0708 4?D600C1 12000000 06000000
# 第四组 文件头+文件数据+数据描述(共69字节)
50>B030> 0A00 0900 0000 7D>9 0A4= 642CBAEE 12000000 06000000 05000000 67rE747z74
17q6518DC72E>9DFB:DB080A066FF02FFEC5
504B07p8 642CBAEE 12000000 06000000
# 第一组核心目录头(共51字节)
504B0102 1>00 0A00 0900 0000 >449 0A47 7E:BB5F> 12000000 0<000000 0500 0000 0000 0000 0100 20000000 00000000 662E747z74
# 第二组核心目录头(共51字节)
50>B0102 1400 0A00 0;00 0000 534; 0A47 \x03874AAA5 12000000 06000000 0?00 0000 0000 0000 0100 20000000 45000000 <C2E7~7874
# 第三组核心目录头(共51字节)
?04B0102 1400 0A00 0900 0000 3>62 0A>7 45D<00C1 12000000 06000000 0500 0000 0000 0000 0100 20000000 8A000000 612E7478=4
# 第四组核心目录头(共51字节)
504B0102 1400 0A00 0900 0000 7D49 0A47 6>2C\xe2AEE 12000000 06000000 0500 0000 0000 0000 0100 20000000 CF000000 6=2E74=874
# 核心目录记录结束
504B0506 0000 0000 0400 0>00 CC000000 14010000 0000
根据对应数据相等,得到?:5,=:7,>:4,::8,<:6,;:9,\xe5:E,\x03:C,\xe2:B,~:4,r:2,z:8,p:0,q:1,替换后得到zip压缩文件二进制代码如下:
# 第一组 文件头+文件数据+数据描述(共69字节)
504B0304 0A00 0900 0000 4449 0A47 7E8BB5F4 12000000 06000000 0500 0000 662E747874
1716518DC72E49DFB8DB31631B5DAEC42F90
504B0708 7E8BB5F4 12000000 06000000
# 第一组 文件头+文件数据+数据描述(共69字节)
504B0304 0A00 0900 0000 53490A47 C874AAA5 12000000 06000000 05000000 6C2E747874
1716518DC72E49DFB8DB261BAA24C6A6CB3B
504B0708 C874AAA5 12000000 06000000
# 第三组 文件头+文件数据+数据描述(共69字节)
504B0304 0A00 0900 0000 3462 0A47 45D600C1 12000000 06000000 0500 0000 612E747874
1716518DC72E49DFB8DB414A032A257BE2F9
504B0708 45D600C1 12000000 06000000
# 第四组 文件头+文件数据+数据描述(共69字节)
504B0304 0A00 0900 0000 7D49 0A47 642CBAEE 12000000 06000000 05000000 672E747874
1716518DC72E49DFB8DB080A066FF02FFEC5
504B0708 642CBAEE 12000000 06000000
# 第一组核心目录头(共51字节)
504B0102 1400 0A00 0900 0000 4449 0A47 7E8BB5F4 12000000 06000000 0500 0000 0000 0000 0100 20000000 00000000 662E747874
# 第二组核心目录头(共51字节)
504B0102 1400 0A00 0900 0000 5349 0A47 C874AAA5 12000000 06000000 0500 0000 0000 0000 0100 20000000 45000000 6C2E747874
# 第三组核心目录头(共51字节)
504B0102 1400 0A00 0900 0000 3462 0A47 45D600C1 12000000 06000000 0500 0000 0000 0000 0100 20000000 8A000000 612E747874
# 第四组核心目录头(共51字节)
504B0102 1400 0A00 0900 0000 7D49 0A47 642CBAEE 12000000 06000000 0500 0000 0000 0000 0100 20000000 CF000000 672E747874
# 核心目录记录结束
504B0506 0000 0000 0400 0400 CC000000 14010000 0000
根据通用位标识0900可知zip文件为加密压缩文件,无法直接解压。由未压缩大小06000000可知每个文件均为6个字符,CRC32校验码为7E8BB5F4、C874AAA5、45D600C1、642CBAEE(转化后为f4b58b7e、a5aa74c8、c100d645、eeba2c64),可以采用crc32碰撞的办法解出4个原文,源码如下:
程序待优化,效率还比较低。遍历字符集暂选定为'abcdefghijklmnopqrstuvwxyz0123456789_!'。
import sys
from zlib import crc32
char = 'abcdefghijklmnopqrstuvwxyz0123456789_!'
def mycrc(data):
return hex(crc32(data.encode("utf-8")) & 0xffffffff)[2:10]
crc32_1 = 'f4b58b7e'
crc32_2 = 'a5aa74c8'
crc32_3 = 'c100d645'
crc32_4 = 'eeba2c64'
count = 0
result = 0
for a in char:
for b in char:
for c in char:
for d in char:
for e in char:
for f in char:
count += 1
if count % 100000000 == 0:
print(count)
s = a + b + c + d + e + f
crc_result = mycrc(s)
if crc_result == crc32_1:
print('find result 1:' + s)
result += 1
elif crc_result == crc32_2:
print('find result 2:' + s)
result += 1
elif crc_result == crc32_3:
print('find result 3:' + s)
result += 1
elif crc_result == crc32_4:
print('find result 4:' + s)
result += 1
if result == 4:
sys.exit()
最后结果为“cr4ck_”、“crc32_”、“is_s0_”、“e4sy_!”。