Python暴力破解zip

在这个压缩包泛滥的时代,加密的压缩包更是数不剩数,然而当人们下载下来时发现压缩包被加密了,瞬间感到绝望。
人们想进办法去查看加密压缩包里面的东西,最后都是无功而返。
本文将带领大家如何用python暴力破解zip密码。

正文

目前我们已知的破解zip的方式只有“Known plaintext attack”和“暴力破解”。
“Known plaintext attack”的最大缺点是有比较大的局限性。
“暴力破解”需要密码字典去破解,遇到复杂度教高的密码时破解时间变得非常长。

配置环境

安装python(必须)

作用:脚本运行环境 到python官网下载相应平台的最新版本,一路安装即可。 安装步骤可以参考廖雪峰老师的教程

知识点

  • zipfile 的使用方法
  • argparse 的使用方法

zipfile模块使用

zipfile模块是python中自带的模块,用于提供对zip文件的创建、读取、写入、追加、解压、以及列出zip文件列表的工具。
这里面我们运用到的是zipfile模块的extractall方法来解压zip文件。
这里我们先来看看extractall方法的方法说明:ZipFile.extractall([path[, members[, pwd]]])

参数说明

  • path 必填,指定解压后文件的存储位置。
  • members 选填,默认值为zip文档内的所有文件名称列表,也可以自己设置,选择要解压的文件名称。
  • pwd 必填,指定Zip文件的解压密码或者密码字典。

接下来我们来看看如何用zipfile模块去解压一个带密码的zip文件

首先创建一个文件 hello.txt文件把他压缩成zip文件,设置密码为123456

touch hello.txt
zip -r hello.zip hello.txt -P 1314

现在我们的准备工作就完成了,我们来看一下Demo吧!

# -*- coding:utf-8 -*-
import zipfile # 引入zipfile模块

try:
    with zipfile.ZipFile('hello.zip') as zFile: # 创建ZipFile对象指定需要解压的zip文件
    	# 解压文件
		zFile.extractall(path='./',pwd=b'123456')
		print('Extract the Zip file successfully!')
except:
	print('Extract the Zip file failed!')

可以看到我们解压成功了!是不是觉得很简单?

argparse模块

argparse是python中很好用的一个命令行解析模块,使用它我们可以很方便的创建用户友好型命令行程序。而且argparse会自动生成帮助信息和错误信息。
argparse的使用方法:

  • 我们首先导入argparse模块,通过argparse.ArgumentParser方法获取解析器对象。
  • description是在我们输出命令行参数帮助显示时起到描述作用。
  • add_argument方法用来添加我们需要解析的参数,我们先添加一个-n参数,dest想当与存储命令参数值的变量,type便是我们输入参数的类型,help是来说明参数的。

下面是一个argparse模块的demo:

# -*- coding:utf-8 -*-
import argparse # 引入argparse模块

parse = argparse.ArgumentParser(description = 'Regards to your name.')
parse.add_argument('-n', dest='m_name',type=str,help='your name')
options = parse.parse_args()

print('Hello', options.m_name)

运行结果如下

代码实现

到了这里相信大家已经对这两个关键模块有所了解那么接下来是用代码实现如何暴力破解zip包已经密码字典的制作

暴力破解代码

import zipfile
import argparse
import os
from os.path import *

def tryZipPwd(zipFile, password, savePath):
    try:
        zipFile.extractall(path=savePath, pwd=password.encode('utf-8'))
        print('[+] Zip File decompression success,password: %s' % (password))
        return True
    except:
        print('[-] Zip File decompression failed,password: %s' % (password))
        return False


def main():
    # 这里用描述创建了ArgumentParser对象
    parser = argparse.ArgumentParser(description='Brute Crack Zip')
    # 添加-H命令dest可以理解为咱们解析时获取-H参数后面值的变量名,help是这个命令的帮助信息
    parser.add_argument('-f', dest='zFile', type=str, help='The zip file path.')
    parser.add_argument('-w', dest='pwdFile', type =str, help='Password dictionary file.')
    zFilePath = None
    pwdFilePath = None
    try:
        options = parser.parse_args()
        zFilePath = options.zFile
        pwdFilePath = options.pwdFile
    except:
        print(parser.parse_args(['-h']))
        exit(0)

    if zFilePath == None or pwdFilePath == None:
        print(parser.parse_args(['-h']))
        exit(0)

    with zipfile.ZipFile(zFilePath) as zFile:
        with open(pwdFilePath) as f:
            for pwd in f.readlines():
                p,f = split(zFilePath)
                dirName = f.split('.')[0]
                dirPath = join(p, dirName)
                try:
                    os.mkdir(dirPath)
                except:
                    pass
                ok = tryZipPwd(zFile, pwd.strip('\n'), dirPath)
                if ok:
                    break
if __name__ == '__main__':
    main()

复杂度较低纯数字的密码字典代码

import itertools as its
words = "1234568790"
r =its.product(words,repeat=4) # repeat为要生成密码长度位数
dic = open("pass.txt","a")
for i in r:
    dic.write("".join(i))
    dic.write("".join("\n"))
dic.close()

复杂度较高的密码字典代码


# -*- coding:utf-8 -*-

import random
class Dictor():
    CSet=' abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789~!@#$%^&*()_-+=/*<>:;\'"[]{}|'
    def __init__(self,minlen,maxlen):
        if maxlen>minlen:
            self.__minlen=minlen
            self.__maxlen=maxlen
        else:
            self.__minlen=maxlen
            self.__maxlen=minlen
    def __iter__(self):
        return self
    def __next__(self):
        ret=''
        for i in range(0,random.randrange(self.__minlen,self.__maxlen+1)):
            ret+=random.choice(Dictor.CSet)
        return ret
if __name__=='__main__':
    dic = open("pass.txt","a")
    # 需要生成密码的位数
	for str in Dictor(6,16):
		dic.write("".join(str))
		dic.write("".join("\n"))
	dic.close()

最后效果图如下: