室友的Zip加密檔案探祕,Python解決Zip加密檔案探索祕密!

Python_sn發表於2020-12-22

之前在家裡的老電腦中,發現一個加密zip壓縮包,由於時隔太久忘記密碼了,依稀記得密碼是6位字母加數字,網上下載了很多破解密碼的軟體都沒有效果,於是想到自己用Python寫一個暴力破解密碼的指令碼。

Python有一個內建模組zipfile可以幹這個事情,測試一波,一個測試檔案,設定解壓密碼為123。

很多人學習python,不知道從何學起。
很多人學習python,掌握了基本語法過後,不知道在哪裡尋找案例上手。
很多已經做案例的人,卻不知道如何去學習更加高深的知識。
那麼針對這三類人,我給大家提供一個好的學習平臺,免費領取視訊教程,電子書籍,以及課程的原始碼!??¤
QQ群:232030553

import zipfile  
# 建立檔案控制程式碼  
file = zipfile.ZipFile("測試.zip", 'r')  
# 提取壓縮檔案中的內容,注意密碼必須是bytes格式,path表示提取到哪  
file.extractall(path='.', pwd='123'.encode('utf-8')) 

執行效果如下圖所示,提取成功。

好了開始破解老檔案的密碼,為了提高速度我加了多執行緒最初的程式碼:

import zipfile  
import itertools  
from concurrent.futures import ThreadPoolExecutor  
def extract(file, password):  
    if not flag: return  
    file.extractall(path='.', pwd=''.join(password).encode('utf-8'))  
def result(f):  
    exception = f.exception()  
    if not exception:  
        # 如果獲取不到異常說明破解成功  
        print('密碼為:', f.pwd)  
        global flag  
        flag = False  
if __name__ == '__main__':  
    # 建立一個標誌用於判斷密碼是否破解成功  
    flag = True  
    # 建立一個執行緒池  
    pool = ThreadPoolExecutor(100)  
    nums = [str(i) for i in range(10)]  
    chrs = [chr(i) for i in range(65, 91)]  
    # 生成數字+字母的6位數密碼  
    password_lst = itertools.permutations(nums + chrs, 6)  
    # 建立檔案控制程式碼  
    zfile = zipfile.ZipFile("加密檔案.zip", 'r')  
    for pwd in password_lst:  
        if not flag: break  
        f = pool.submit(extract, zfile, pwd)  
        f.pwd = pwd  
        f.pool = pool  
        f.add_done_callback(result) 

這個程式碼有個問題,跑一會兒記憶體就爆了!原因:ThreadPoolExecutor預設使用的是無界佇列,嘗試密碼的速度跟不上生產密碼的速度,會把生產任務無限新增到佇列中。導致記憶體被佔滿。記憶體直接飆到95:

然後程式奔潰:

看了一下原始碼發現ThreadPoolExecutor內部使用的是無界佇列,所以導致記憶體直接飆滿,重寫ThreadPoolExecutor類中的_work_queue屬性,將無界佇列改成有界佇列,這樣就不會出現記憶體爆滿的問題,看程式碼:

import queue  
from concurrent.futures import ThreadPoolExecutor  
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) # 設定佇列大小 

最後破解成功,如下圖所示。

相關文章