【CTF misc python】加密zip和rar文件的枚举解密工具(python代码)

枚举解密有密码的压缩包应该是常见需求了。没有工具的情况下可以自己写一段py脚本来实现。

环境:Windows10,python3.7.6

文章目录

      • 仅支持ZIP的版本
      • 支持ZIP和RAR的版本
        • 安装
        • 代码解释
      • 参考链接

仅支持ZIP的版本

我稍微改了下参考链接1的代码,可以正确运行。 他的代码在解密基础上加了多线程,但是他的代码会打印很多个密码(第一个打印的就是真密码)。

我对多线程了解很少,但我认为我这段代码是对的(只要对flag变量的所有操作都是原子的),因为只有一个线程能找到密码,找到密码的线程等待cpu调度期间即使有其他线程执行done_callback,也无法进入if那块代码。

作者:hans774882968以及hans774882968

注意:

  1. 同时支持zip和rar的代码在下一小节。
  2. 使用的命令可以是python zip_pwd.pypython zip_pwd.py
  3. 这段代码如果找到了密码,也会把解压出的文件放在python文件所在文件夹下
  4. 参考链接2告诉我们,如果你想用WinRAR创建zip压缩文件,用来学习测试zip枚举解密,记得勾选ZIP传统加密。
import queue
import zipfile
import itertools
import sys
from concurrent.futures import ThreadPoolExecutor

# 创建一个标志用于判断密码是否破解成功
flag = True

def extract(file, password):
    if not flag: return
    file.extractall(path='.', pwd=''.join(password).encode('utf-8'))

def result(f):
    global flag
    exception = f.exception()
    if not exception and flag:
        # 如果获取不到异常说明破解成功
        print('密码为:', f.pwd)
        flag = False

class BoundedThreadPoolExecutor(ThreadPoolExecutor):
    def __init__(self, max_workers=None, thread_name_prefix=''):
        super().__init__(max_workers, thread_name_prefix)
        self._work_queue = queue.Queue(self._max_workers * 2) # 设置队列大小

def get_pwd_list():
    # 生成数字+字母的6位数密码
    # nums = [str(i) for i in range(10)]
    # chrs = [chr(i) for i in range(65, 91)]
    # return itertools.permutations(nums + chrs, 6)
    # 生成所有4位数
    return itertools.product(*[[str(j) for j in range(10)] for i in range(4)])

# https://cloud.tencent.com/developer/article/1806690
def main():
    fname = "shell-shell漏洞.zip"
    if len(sys.argv) > 1: fname = sys.argv[1]
    # 创建一个线程池
    pool = BoundedThreadPoolExecutor(100)
    password_lst = get_pwd_list()
    # 创建文件句柄
    zfile = zipfile.ZipFile(fname, 'r')
    for pd in password_lst:
        pwd = "".join(pd)
        if not flag: break
        f = pool.submit(extract, zfile, pwd)
        f.pwd = pwd
        f.pool = pool
        f.add_done_callback(result)

if __name__ == '__main__':
    main()

支持ZIP和RAR的版本

安装

首先pip install rarfile,然后要把unrar.exe加到环境变量PATH变量,否则python代码运行报错(根据官方文档,测试环境变量添加是否成功,只需要在powershell执行unrar -v)。注意,请添加一个文件夹,比如C:\Program Files\WinRAR\,而非一个exe文件!

代码解释

因为zip和rar的api用法差不多,所以一开始为了让代码的颜值高,写了抽象类的版本,线程池的使用方式类似于f = pool.submit(mgr.extract, pwd)f.add_done_callback(result),但是跑得比上一小节的代码慢不少。所以后面改回了面向过程的版本,代码比较丑。

注意:

  1. 跑zip的时候cpu使用率很正常,解得也很快。但跑rar的时候cpu飙升到100%,对于4位数密码似乎要解一分钟左右。所以最好还是去找工具
  2. 使用命令同上。
import queue
import zipfile
import rarfile
import itertools
import sys
import os
from concurrent.futures import ThreadPoolExecutor

# 创建一个标志用于判断密码是否破解成功
flag = True
fileType = ""
output_dir = ""
RAR_TYPE = ".rar"
ZIP_TYPE = ".zip"

def extract(file, password):
    if not flag: return
    if fileType == ZIP_TYPE:
        file.extractall(path=output_dir, pwd=''.join(password).encode('utf-8'))
    else:
        file.extractall(path=output_dir, pwd=''.join(password))

def result(f):
    global flag
    exception = f.exception()
    if not exception and flag:
        # 如果获取不到异常说明破解成功
        print('密码为:', f.pwd)
        flag = False

class BoundedThreadPoolExecutor(ThreadPoolExecutor):
    def __init__(self, max_workers=None, thread_name_prefix=''):
        super().__init__(max_workers, thread_name_prefix)
        self._work_queue = queue.Queue(self._max_workers * 2) # 设置队列大小

def get_pwd_list():
    # 生成数字+字母的6位数密码
    # nums = [str(i) for i in range(10)]
    # chrs = [chr(i) for i in range(65, 91)]
    # return itertools.permutations(nums + chrs, 6)
    # 生成所有4位数
    return itertools.product(*[[str(j) for j in range(10)] for i in range(4)])

# https://cloud.tencent.com/developer/article/1806690
def main():
    global file_dir,output_dir,fileType
    file_dir = "shell-shell漏洞.zip"
    if len(sys.argv) > 1: file_dir = sys.argv[1]
    output_dir = os.path.dirname(file_dir)
    ext_name = os.path.splitext(file_dir)[1].lower()
    if ext_name != ZIP_TYPE and ext_name != RAR_TYPE:
        raise Exception("Expect .zip or .rar file, but get \"%s\" file" % ext_name)
    fileType = ext_name
    # 创建一个线程池
    pool = BoundedThreadPoolExecutor(100)
    password_lst = get_pwd_list()
    # 创建文件句柄
    cfile = zipfile.ZipFile(file_dir, 'r') if fileType == ZIP_TYPE else rarfile.RarFile(file_dir)
    for pd in password_lst:
        pwd = "".join(pd)
        if not flag: break
        f = pool.submit(extract, cfile, pwd)
        f.pwd = pwd
        f.pool = pool
        f.add_done_callback(result)

if __name__ == '__main__':
    main()

参考链接

  1. python解压zip:https://cloud.tencent.com/developer/article/1806690
  2. zip需要勾选“ZIP传统加密”:https://blog.csdn.net/Tiny007/article/details/105121800

你可能感兴趣的:(web&CTF,python,网络安全)