Crafting a Brute Force Password Cracker
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:
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:
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):
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:
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:
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:
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.