Home » Tutorials » How to Brute Force Zip File Passwords in Python

How to Brute Force Zip File Passwords in Python

In our last article, we talked about breaking passwords with brute force. Today, we’re going to apply that method to zip files. We’ll start simple, focusing on passwords that use only lowercase letters. This keeps things faster, but I’ll show you how to tweak it for any password, no matter how complex. Let’s get cracking on those zip file passwords.

Table of Contents

Disclaimer

This content is for educational purposes only. Don’t use these methods on files or systems without explicit permission. Hacking without consent is illegal and unethical.

Necessary Libraries

Let’s get everything set up before we dive into the code. Make sure to install the tkinter and pyzipper libraries for the code to function properly:

$ pip install tk
$ pip install pyzipper

Imports

import tkinter as tk
from tkinter import filedialog, messagebox
import zipfile
import pyzipper
from threading import Thread

As per usual, we will start our script with the necessary imports:

  1. tkinter Library: We’ll begin with the tkinter library to create a graphical user interface (GUI). From tkinter, we specifically need the filedialog and messagebox modules. These allow us to choose files and use message boxes, respectively.
  2. Zipfile Module: Next, we import the zipfile module, which is essential for handling Zip files.
  3. PyZipper Module: After that, we’ll include the pyzipper module. This is important for working with AES-encrypted Zip files.
  4. Thread Class: Lastly, we import the Thread class. This enables us to run multiple tasks in parallel without interference.

Every import we add is like a key ingredient in our recipe, ensuring our code runs just right and zips along without a hitch.

ZipCrackerApp Class

Next, we define a class called ZipCrackerApp that inherits all the functionality of a regular tkinter application window. Then, we proceed to customize the class by creating an instance with the __init__() method.

After that, we initialize the main window. In other words, we prepare the main window for display using the super().__init__() method and also set its title. Next, we initialize the variables we’ll need and get ready to create widgets by calling the create_widgets() function.

class ZipCrackerApp(tk.Tk):
   def __init__(self):
       super().__init__()
       self.title("Zip File Brute Force")
       self.file_path = tk.StringVar()
       self.min_length = tk.IntVar()
       self.max_length = tk.IntVar()
       self.result_text = tk.StringVar()
       self.zip_type = tk.StringVar(value="standard")  # Default to standard zip

       self.create_widgets()

Creating GUI Widgets

Following that, we create the widgets to be arranged using the grid layout on the main window. These include labels for displaying text, entry fields for inputs, radio buttons for selecting the type of encryption to crack, and buttons. Each button will have a different name and will call a specific function.

   def create_widgets(self):
       # File Selection
       file_label = tk.Label(self, text="Select Zip File:")
       file_label.grid(row=0, column=0, padx=5, pady=5)
       file_entry = tk.Entry(self, textvariable=self.file_path, width=50)
       file_entry.grid(row=0, column=1, padx=5, pady=5)
       browse_button = tk.Button(self, text="Browse", command=self.browse_file)
       browse_button.grid(row=0, column=2, padx=5, pady=5)


       # Zip Type Selection
       zip_type_label = tk.Label(self, text="Zip File Type:")
       zip_type_label.grid(row=1, column=0, padx=5, pady=5)
       zip_type_standard = tk.Radiobutton(self, text="Standard Zip", variable=self.zip_type, value="standard")
       zip_type_standard.grid(row=1, column=1, padx=5, pady=5)
       zip_type_aes = tk.Radiobutton(self, text="AES Encrypted Zip", variable=self.zip_type, value="aes")
       zip_type_aes.grid(row=1, column=2, padx=5, pady=5)


       # Password Length
       min_length_label = tk.Label(self, text="Minimum Password Length:")
       min_length_label.grid(row=2, column=0, padx=5, pady=5)
       min_length_entry = tk.Entry(self, textvariable=self.min_length, width=10)
       min_length_entry.grid(row=2, column=1, padx=5, pady=5)
       max_length_label = tk.Label(self, text="Maximum Password Length:")
       max_length_label.grid(row=2, column=2, padx=5, pady=5)
       max_length_entry = tk.Entry(self, textvariable=self.max_length, width=10)
       max_length_entry.grid(row=2, column=3, padx=5, pady=5)


       # Result Label
       result_label = tk.Label(self, textvariable=self.result_text)
       result_label.grid(row=3, column=0, columnspan=4, padx=5, pady=5)


       # Start Button
       start_button = tk.Button(self, text="Start Brute Force", command=self.start_brute_force)
       start_button.grid(row=4, column=0, columnspan=4, padx=5, pady=5)

Defining Functions

Now, let’s define the heart of our code – our Functions:

File Browsing Function

This part uses the filedialog so that the user will be able to select and view the ZIP file he or she wants to crack, and all this can be done when the user clicks the “Browse” button.

   def browse_file(self):
       file_path = filedialog.askopenfilename(filetypes=[("Zip files", "*.zip")])
       if file_path:
           self.file_path.set(file_path)

Brute Force Function

This function retrieves the user’s choices, including the zip file and the encryption type, from the input fields. Based on the selected zip file type, either standard or AES, it initializes a zip_file object. This kicks off the brute force attack, trying every possible password combination through the generate_passwords() function, within the user-specified password length range (minimum and maximum).

If the correct password is found, it will be displayed on the main window. Should the password remain unfound, a message indicating its absence will be shown instead. Additionally, any errors encountered during the process will trigger a pop-up alert, courtesy of messagebox.showerror().

   def brute_force(self):
       zip_file_path = self.file_path.get()
       min_length = self.min_length.get()
       max_length = self.max_length.get()


       try:
           if self.zip_type.get() == "aes":
               zip_file = pyzipper.AESZipFile(zip_file_path)
           else:
               zip_file = zipfile.ZipFile(zip_file_path, 'r')


           with zip_file:
               for length in range(min_length, max_length + 1):
                   for password in self.generate_passwords(length):
                       try:
                           if self.zip_type.get() == "aes":
                               zip_file.pwd = password.encode()
                               zip_file.extractall()
                           else:
                               zip_file.extractall(pwd=password.encode())
                           self.result_text.set(f"Password found: {password}")
                           return
                       except (RuntimeError, zipfile.BadZipFile):
                           pass
           self.result_text.set("Password not found.")
       except Exception as e:
           messagebox.showerror("Error", str(e))

Starting Brute Force Function

First up, this function checks if you’ve picked a real zip file and if the password lengths you’ve entered make sense. Got both those things right? Great! It then gets everything in order, pops up a message saying “Starting brute force“, and kicks off the brute_force() function in a new thread. This clever move makes sure our main window stays awake and doesn’t go into a frozen slumber.

Now, if things aren’t quite right with what you’ve entered, the function won’t leave you hanging. Instead, it’ll quickly show you an error message explaining what went wrong. This way, you know exactly what to fix to get things rolling.

   def start_brute_force(self):
       if not self.file_path.get():
           messagebox.showerror("Error", "Please select a ZIP file.")
           return
       if self.min_length.get() <= 0 or self.max_length.get() <= 0:
           messagebox.showerror("Error", "Password length should be greater than zero.")
           return
       if self.min_length.get() > self.max_length.get():
           messagebox.showerror("Error", "Minimum password length cannot be greater than maximum.")
           return

       self.result_text.set("Starting brute force...")
       Thread(target=self.brute_force).start()

Generating Passwords Function

This one is responsible for creating passwords by trying different combinations of the lowercase English alphabets within the specified length by the user.

   def generate_passwords(self, length):
       for i in range(26 ** length):
           password = ""
           for j in range(length):
               password += chr(ord('a') + (i // (26 ** j)) % 26)
           yield password

Main Application Execution

Lastly, this block ensures that this script can only be run directly and not imported as a module in which case it will not function, while also making sure that the main window keeps running and is responsive to the user until he exits willingly.

if __name__ == "__main__":
   app = ZipCrackerApp()
   app.mainloop()

Example

Full Code

import tkinter as tk
from tkinter import filedialog, messagebox
import zipfile
import pyzipper
from threading import Thread


class ZipCrackerApp(tk.Tk):
   def __init__(self):
       super().__init__()
       self.title("Zip File Brute Force")
       self.file_path = tk.StringVar()
       self.min_length = tk.IntVar()
       self.max_length = tk.IntVar()
       self.result_text = tk.StringVar()
       self.zip_type = tk.StringVar(value="standard")  # Default to standard zip


       self.create_widgets()


   def create_widgets(self):
       # File Selection
       file_label = tk.Label(self, text="Select Zip File:")
       file_label.grid(row=0, column=0, padx=5, pady=5)
       file_entry = tk.Entry(self, textvariable=self.file_path, width=50)
       file_entry.grid(row=0, column=1, padx=5, pady=5)
       browse_button = tk.Button(self, text="Browse", command=self.browse_file)
       browse_button.grid(row=0, column=2, padx=5, pady=5)


       # Zip Type Selection
       zip_type_label = tk.Label(self, text="Zip File Type:")
       zip_type_label.grid(row=1, column=0, padx=5, pady=5)
       zip_type_standard = tk.Radiobutton(self, text="Standard Zip", variable=self.zip_type, value="standard")
       zip_type_standard.grid(row=1, column=1, padx=5, pady=5)
       zip_type_aes = tk.Radiobutton(self, text="AES Encrypted Zip", variable=self.zip_type, value="aes")
       zip_type_aes.grid(row=1, column=2, padx=5, pady=5)


       # Password Length
       min_length_label = tk.Label(self, text="Minimum Password Length:")
       min_length_label.grid(row=2, column=0, padx=5, pady=5)
       min_length_entry = tk.Entry(self, textvariable=self.min_length, width=10)
       min_length_entry.grid(row=2, column=1, padx=5, pady=5)
       max_length_label = tk.Label(self, text="Maximum Password Length:")
       max_length_label.grid(row=2, column=2, padx=5, pady=5)
       max_length_entry = tk.Entry(self, textvariable=self.max_length, width=10)
       max_length_entry.grid(row=2, column=3, padx=5, pady=5)


       # Result Label
       result_label = tk.Label(self, textvariable=self.result_text)
       result_label.grid(row=3, column=0, columnspan=4, padx=5, pady=5)


       # Start Button
       start_button = tk.Button(self, text="Start Brute Force", command=self.start_brute_force)
       start_button.grid(row=4, column=0, columnspan=4, padx=5, pady=5)


   def browse_file(self):
       file_path = filedialog.askopenfilename(filetypes=[("Zip files", "*.zip")])
       if file_path:
           self.file_path.set(file_path)


   def brute_force(self):
       zip_file_path = self.file_path.get()
       min_length = self.min_length.get()
       max_length = self.max_length.get()


       try:
           if self.zip_type.get() == "aes":
               zip_file = pyzipper.AESZipFile(zip_file_path)
           else:
               zip_file = zipfile.ZipFile(zip_file_path, 'r')


           with zip_file:
               for length in range(min_length, max_length + 1):
                   for password in self.generate_passwords(length):
                       try:
                           if self.zip_type.get() == "aes":
                               zip_file.pwd = password.encode()
                               zip_file.extractall()
                           else:
                               zip_file.extractall(pwd=password.encode())
                           self.result_text.set(f"Password found: {password}")
                           return
                       except (RuntimeError, zipfile.BadZipFile):
                           pass
           self.result_text.set("Password not found.")
       except Exception as e:
           messagebox.showerror("Error", str(e))


   def start_brute_force(self):
       if not self.file_path.get():
           messagebox.showerror("Error", "Please select a ZIP file.")
           return
       if self.min_length.get() <= 0 or self.max_length.get() <= 0:
           messagebox.showerror("Error", "Password length should be greater than zero.")
           return
       if self.min_length.get() > self.max_length.get():
           messagebox.showerror("Error", "Minimum password length cannot be greater than maximum.")
           return


       self.result_text.set("Starting brute force...")
       Thread(target=self.brute_force).start()


   def generate_passwords(self, length):
       for i in range(26 ** length):
           password = ""
           for j in range(length):
               password += chr(ord('a') + (i // (26 ** j)) % 26)
           yield password


if __name__ == "__main__":
   app = ZipCrackerApp()
   app.mainloop()

Summary

So, all in all, if you want to protect yourself from this attack, you should make your password as unique as possible by lengthening it and mixing symbols with digits with uppercase and lowercase characters.

Learn also: How to Generate Random Passwords in Python

Subscribe for Top Free Python Tutorials!

Receive the best directly.  Elevate Your Coding Journey!

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top
×