今天来研究以下zip的破解与伪加密

1.破解密码

当你不知道一个压缩包的密码但你又想解压它的时候该怎么办?能想到的确实只有多试硬破

只不过这不像一般的登录密码,错多了直接把你锁住

所以“多试”这个活我们就可以直接扔给电脑做

我们能做的就是尽可能搜集线索,例如“密码只有数字”,“密码有6位字符”之类这样的

这些线索可以大幅缩减穷举范围,让电脑少费很多功夫

不然64位的随机字符组成的密码足够电脑破几百万年

现在让我们做点破解密码的实验

hello.txt

如图所示,这是一个名为"hello.txt"的记事本,里面写着"lucky and happy!"(感叹号是英文字符)

用bandizip把它压缩成一个密码是114514的zip文件

接下来我们用Advanced Archive Password Recovery(AAPR)来破解它

1.暴力破解

直接选择暴力破解,勾选所有可以打印字符,长度设定1-10

口令长度=5这台电脑就花了大概十分钟,现在来到了6位长度,看到五小时我不想等了

这次我我把暴力范围选项框定在了所有数字里,结果这次我的电脑只花了12ms

总之暴力破解真的就是让电脑一个一个试,所以框定范围能够显著地减少时间

2.掩码爆破

使用这个方式的前提是你知道某一位或几位是什么字符并且你知道这个密码有几位字符

例如我设置掩码为“1?????4”,再在暴力范围选项里选中所有可打印字符

只花了1.3s就破出来了,掩码确实大幅减少了破解时间

3.字典爆破

这个方式吧,我觉得可能局限性比较大。一般能收录在爆破词典里的密码都不会太复杂,甚至有规律。例如AAPR里自带的english.dic里面真的就是英语单词,自然是爆破不成功的。

但我觉得如果说对方为了安全性整了很多复杂的密码,但他又记不住,于是写了份密码册,然后你能通过某种手段搞到对方的密码册,那确实可以做到字典爆破

4.Python脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

import zipfile
import time
import threading
startTime = time.time()
# 判断线程是否需要终止
flag = True


def extract(password, file):
try:
password = str(password)
file.extractall(path='.', pwd=password.encode('utf-8'))
print("the password is {}".format(password))
nowTime = time.time()
print("spend time is {}".format(nowTime-startTime))
global flag
# 成功解压其余线程终止
flag = False
except Exception as e:
print(e)


def do_main():
zfile = zipfile.ZipFile("path\\to\\you\\file", 'r') #这里选中你的zip
# 开始尝试
for number in range(100000, 999999): #为了省时间,就不从1开始了
if flag is True:
t = threading.Thread(target=extract, args=(number, zfile))
t.start()
t.join()


if __name__ == '__main__':
do_main()

得到输出

1
2
3
4
5
6
7
8
9
10
...
Bad password for file 'hello.txt'
Bad password for file 'hello.txt'
Bad password for file 'hello.txt'
Bad password for file 'hello.txt'
Bad password for file 'hello.txt'
Bad password for file 'hello.txt'
Bad password for file 'hello.txt'
the password is 114514
spend time is 23.434365034103394

确实破出来了

2.zip伪加密

1.16进制拆解

在实现这一步之前,我想我们需要学习十六进制下的zip文件结构

hello.zip

仍然使用wxMEdit来打开hello.zip(没有密码)

需要注意的是,zip的数据使用字节内顺读,字节外逆读的方式,这点对数量有关的数据很重要

如0x[AB CD]对应的数字不是0xABCD而是0xCDAB

zip

触摸板没法画得特别好

这里面有三对花括号,颜色为蓝绿红。这是zip文件的三个部分

压缩源文件数据区 核心目录 目录结束标志
local file header + file data + data descriptor central directory end of central directory record
1.压缩源文件数据区

数据区由一系列本地文件记录组成

这一段以0x[50 4B 03 04](顺)开头,标志其开始

local file header里面会记录一些概述信息,稍后列表详细解释

file data是文件的压缩数据。我们这里不深究其压缩算法

data descriptor不太重要,故这里不做探究(至少在文件里没有出现,并且网上没有太多人做解释)

Offset Bytes Description
0x00 4 标识段0x[50 4B 03 04]
0x04 2 解压文件所需版本,记录解压缩文件所需的最低支持的ZIP规范版本
0x06 2 通用位标记,[0000 0L0J 0000 0000],若J这位(hello.zip中为0)为1则说明文件被加密,若L这位(hello.zip中为0)为1则说明有数据描述部分,其他部分貌似不常见
0x08 2 压缩方式
0x0A 2 文件最后修改时间,使用MS-DOS格式编码的时间
0x0C 2 文件最后修改日期,使用MS-DOS格式编码的日期
0x0E 4 CRC-32校验码
0x12 4 压缩后的大小,单位为字节,hello.zip中为0x[12 00 00 00]=18字节,这里即hello.txt的原始大小
0x16 4 未压缩的大小,单位为字节,hello.zip中为0x[10 00 00 00]=16字节,这里为压缩包里hello.txt的大小
0x1A 2 文件名长度,单位为字节,hello.zip中为0x[09 00 00 00]=9字节
0x1C 2 扩展名长度,单位为字节,hello.zip中为0x[00 00 00 00]=0字节
0x1E 可变 文件名,hello.zip中此段对应hello.txt
0x27 可变 扩展区,一般情况下不使用

当前最低功能版本定义如下:(压缩包记录的解压版本都是需要版本*10,如hello.zip中记录为0x[14 00]=20=2.0*10)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
1.0 – 默认值
1.1 – 文件是卷标
2.0 – 文件是一个文件夹(目录)
2.0 – 使用 Deflate 压缩来压缩文件
2.0 – 使用传统的 PKWARE 加密对文件进行加密
2.1 – 使用 Deflate64™ 压缩文件
2.5 – 使用 PKWARE DCL Implode 压缩文件
2.7 – 文件是补丁数据集
4.5 – 文件使用 ZIP64 格式扩展
4.6 – 使用 BZIP2 压缩文件压缩
5.0 – 文件使用 DES 加密
5.0 – 文件使用 3DES 加密
5.0 – 使用原始 RC2 加密对文件进行加密
5.0 – 使用 RC4 加密对文件进行加密
5.1 – 文件使用 AES 加密进行加密
5.1 – 使用更正的 RC2 加密对文件进行加密
5.2 – 使用更正的 RC2-64 加密对文件进行加密
6.1 – 使用非 OAEP 密钥包装对文件进行加密
6.2 – 中央目录加密

压缩方式编码如下,看看就好,不必细究,hello.zip中为0x[08 00]=8

1
2
3
4
5
6
7
8
9
10
11
12
13
0 – The file is stored (no compression)
1 – The file is Shrunk
2 – The file is Reduced with compression factor 1
3 – The file is Reduced with compression factor 2
4 – The file is Reduced with compression factor 3
5 – The file is Reduced with compression factor 4
6 – The file is Imploded
7 – Reserved for Tokenizing compression algorithm
8 – The file is Deflated
9 – Enhanced Deflating using Deflate64™
10 – PKWARE Data Compression Library Imploding
11 – Reserved by PKWARE
12 – File is compressed using BZIP2 algorithm

这张图是MS-DOS编码时间和日期的方式。查到的资料是这样,但实际上我发现hello.zip里的数据换不出正确的,但bandizip里能正确显示,暂且略过

MS-DOS
2.核心目录

核心目录由一系列文件记录组成,一个文件记录对应数据区的一个压缩文件记录

Offset(为方便查找,接续上表) Bytes Description
0x39 4 核心目录文件头标识0x[50 4B 01 02]
0x3D 2 压缩所用版本,同上
0x3F 2 解压所需版本,同上
0x41 2 通用位标记,同上
0x43 2 压缩方法,同上
0x45 2 文件最后修改时间
0x47 2 文件最后修改日期
0x49 4 CRC-32校验码
0x4D 4 压缩后大小
0x51 4 未压缩大小
0x55 2 文件名长度
0x57 2 扩展区长度,此处不同上,为0x[24 00]=36字节
0x59 2 文件注释长度
0x5B 2 文件开始位置的磁盘编号,此处为0x[00 00]
0x5D 2 内部文件属性
0x5F 4 外部文件属性
0x63 4 本地文件头的相对位移,记录对应数据内对应文件记录相对于压缩包起始的位置偏移量。hello.zip中为0x[00 00 00 00]因为一开始就是对应记录
0x67 可变 文件名,同样为hello.txt
0x70 可变 扩展区,此处长度为上面规定的36字节
此处无 可变 文件注释目录结束标志
3. 目录结束标志
Offset(为方便查找,接续上表) Bytes Description
0x94 4 核心目录结束标记0x[50 4B 05 06]
0x98 2 核心目录尾部位置所在磁盘编号,此处为0x[00 00]
0x9A 2 核心目录开始位置所在磁盘编号,此处为0x[00 00]
0x9C 2 该磁盘上记录的核心目录数量,此处为0x[01 00]
0x9E 2 zip压缩包中文件总数,此处为0x[01 00]
0xA0 4 整个核心目录大小,单位为字节,此处为0x[5B 00 00 00]=91字节,也就是图中绿花括号所含字节数
0xA4 4 核心目录开始位置相对位移,此处为0x[39 00 00 00],图中第3行第9个字节正式核心目录开始位置
0xA8 2 注释内容长度,此处为0x[00 00 00 00]
此处无 可变 注释内容

至此整个hello.zip就算粗略地分析完毕了,但到此为止也够用

2.通过wxMEdit实现伪加密

通过修改核心目录区的通用位标记就可以实现伪加密

在hello.zip里是0x41的位置,原本为0x[00 00]这里我们把它改成0x[01 00]后保存

再打开bandizip试图打开hello.txt,显示我们需要输入密码

需要输入密码

如此就实现了伪加密

那破除伪加密的方法之一就很显然

修改通用位标记

但也有其他方法,如

在 Mac OS 及部分 Linux(如 Kali ) 系统中,可以直接打开伪加密的 ZIP 压缩包

使用工具ZipCenOp.jar