Cracking Encrypted ZIP Files with Python and Solving Memory Exhaustion
This article walks through using Python's zipfile module to brute‑force an encrypted ZIP password, demonstrates a multithreaded approach that initially exhausts memory, and shows how replacing ThreadPoolExecutor's unbounded queue with a bounded one resolves the issue.
While cleaning an old computer, the author discovered an encrypted ZIP file with a forgotten six‑character alphanumeric password. Using Python's built‑in zipfile module, a simple script can extract a ZIP when the correct password is supplied.
import zipfile
# create file handle
file = zipfile.ZipFile("test.zip", 'r')
# extract with password (bytes)
file.extractall(path='.', pwd='123'.encode('utf-8'))The next step was to brute‑force the password. A multithreaded script using ThreadPoolExecutor and itertools.permutations generated all six‑character combinations of digits and uppercase letters.
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('Password is:', 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)]
password_lst = itertools.permutations(nums + chrs, 6)
zfile = zipfile.ZipFile("encrypted.zip", 'r')
for pwd in password_lst:
if not flag: break
f = pool.submit(extract, zfile, pwd)
f.pwd = pwd
f.add_done_callback(result)Running this code quickly filled memory because ThreadPoolExecutor uses an unbounded work queue; tasks were produced faster than they could be executed, causing the queue to grow without limit and memory usage to spike to 95 % before the process crashed.
To fix the problem, the author rewrote the executor to use a bounded queue by subclassing ThreadPoolExecutor and overriding its internal 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) # set queue sizeReplacing the original executor with BoundedThreadPoolExecutor prevented the memory overflow, and the password was eventually recovered, as shown in the final screenshot.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Python Crawling & Data Mining
Life's short, I code in Python. This channel shares Python web crawling, data mining, analysis, processing, visualization, automated testing, DevOps, big data, AI, cloud computing, machine learning tools, resources, news, technical articles, tutorial videos and learning materials. Join us!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
