init
This commit is contained in:
commit
f2d2aad260
165
part1.py
Normal file
165
part1.py
Normal file
@ -0,0 +1,165 @@
|
||||
import hashlib
|
||||
import itertools
|
||||
import time
|
||||
import string
|
||||
|
||||
# Define character set: 0-9, a-z, A-Z, and special symbols
|
||||
CHARACTERS = string.digits + string.ascii_lowercase + string.ascii_uppercase + '#$%^&*'
|
||||
|
||||
|
||||
def generate_sha256_hash(password):
|
||||
"""Generate SHA256 hash of a password."""
|
||||
return hashlib.sha256(password.encode()).hexdigest()
|
||||
|
||||
|
||||
def read_password_database(filename):
|
||||
"""
|
||||
Read password database from a text file.
|
||||
|
||||
Args:
|
||||
filename: Path to the file containing [username, hash] pairs
|
||||
|
||||
Returns:
|
||||
List of [username, hash] pairs
|
||||
"""
|
||||
database = []
|
||||
|
||||
try:
|
||||
with open(filename, 'r') as f:
|
||||
for line in f:
|
||||
line = line.strip()
|
||||
if line and line.startswith('[') and line.endswith(']'):
|
||||
# Remove brackets and split by comma
|
||||
content = line[1:-1]
|
||||
parts = content.split(',', 1) # Split only on first comma
|
||||
if len(parts) == 2:
|
||||
username = parts[0].strip()
|
||||
password_hash = parts[1].strip()
|
||||
database.append([username, password_hash])
|
||||
|
||||
print(f"Loaded {len(database)} accounts from {filename}")
|
||||
return database
|
||||
|
||||
except FileNotFoundError:
|
||||
print(f"Error: File '{filename}' not found.")
|
||||
return []
|
||||
except Exception as e:
|
||||
print(f"Error reading file: {e}")
|
||||
return []
|
||||
|
||||
|
||||
def dictionary_attack(password_database, N):
|
||||
"""
|
||||
Perform dictionary attack on password database.
|
||||
|
||||
Args:
|
||||
password_database: List of [username, hash] pairs
|
||||
N: Length of passwords to try
|
||||
|
||||
Returns:
|
||||
Dictionary mapping usernames to cracked passwords
|
||||
Time taken for the attack
|
||||
"""
|
||||
print(f"\n{'='*60}")
|
||||
print(f"Starting Dictionary Attack")
|
||||
print(f"Password length: {N}")
|
||||
print(f"Character set size: {len(CHARACTERS)}")
|
||||
print(f"Total possible passwords: {len(CHARACTERS)**N}")
|
||||
print(f"Number of accounts to crack: {len(password_database)}")
|
||||
print(f"{'='*60}\n")
|
||||
|
||||
# Create a dictionary of hash -> username for faster lookup
|
||||
hash_to_user = {entry[1]: entry[0] for entry in password_database}
|
||||
cracked_passwords = {}
|
||||
|
||||
start_time = time.time()
|
||||
attempts = 0
|
||||
|
||||
# Generate all possible passwords of length N
|
||||
for password_tuple in itertools.product(CHARACTERS, repeat=N):
|
||||
password = ''.join(password_tuple)
|
||||
attempts += 1
|
||||
|
||||
# Hash the password
|
||||
password_hash = generate_sha256_hash(password)
|
||||
|
||||
# Check if this hash matches any in the database
|
||||
if password_hash in hash_to_user:
|
||||
username = hash_to_user[password_hash]
|
||||
cracked_passwords[username] = password
|
||||
print(f"[+] Cracked! {username}: {password}")
|
||||
|
||||
# If all passwords are cracked, we can stop
|
||||
if len(cracked_passwords) == len(password_database):
|
||||
break
|
||||
|
||||
# Progress indicator (every 10000 attempts for small N, adjust as needed)
|
||||
if attempts % 10000 == 0:
|
||||
print(f"Tried {attempts} passwords...")
|
||||
|
||||
end_time = time.time()
|
||||
time_taken = end_time - start_time
|
||||
|
||||
print(f"\n{'='*60}")
|
||||
print(f"Attack Complete!")
|
||||
print(f"Time taken: {time_taken:.4f} seconds")
|
||||
print(f"Total attempts: {attempts}")
|
||||
print(f"Passwords cracked: {len(cracked_passwords)}/{len(password_database)}")
|
||||
print(f"{'='*60}\n")
|
||||
|
||||
return cracked_passwords, time_taken
|
||||
|
||||
|
||||
def main():
|
||||
"""Main function to run the dictionary attack demonstration."""
|
||||
print("Dictionary Attack on SHA256 Password Hashes")
|
||||
print("=" * 60)
|
||||
|
||||
# Get input file and password length from user
|
||||
filename = input("Enter password database filename: ")
|
||||
N = int(input("Enter password length N: "))
|
||||
|
||||
# Warn if N is too large
|
||||
if N > 4:
|
||||
total_passwords = len(CHARACTERS) ** N
|
||||
print(f"\nWarning: With N={N}, there are {total_passwords:,} possible passwords.")
|
||||
print("This may take a very long time!")
|
||||
confirm = input("Continue? (yes/no): ")
|
||||
if confirm.lower() != 'yes':
|
||||
print("Attack cancelled.")
|
||||
return
|
||||
|
||||
# Read password database from file
|
||||
print("\nReading password database...")
|
||||
password_database = read_password_database(filename)
|
||||
|
||||
if not password_database:
|
||||
print("No valid data found. Exiting.")
|
||||
return
|
||||
|
||||
print("\nPassword Database:")
|
||||
for username, password_hash in password_database:
|
||||
print(f"[{username}, {password_hash}]")
|
||||
|
||||
# Perform dictionary attack
|
||||
cracked_passwords, time_taken = dictionary_attack(password_database, N)
|
||||
|
||||
# Display results
|
||||
print("\nResults:")
|
||||
for username, password in cracked_passwords.items():
|
||||
print(f"{username}: {password}")
|
||||
|
||||
print(f"\nTotal time: {time_taken:.4f} seconds")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
174
part2.py
Normal file
174
part2.py
Normal file
@ -0,0 +1,174 @@
|
||||
import hashlib
|
||||
import itertools
|
||||
import time
|
||||
import string
|
||||
|
||||
# Define character set: 0-9, a-z, A-Z, and special symbols
|
||||
CHARACTERS = string.digits + string.ascii_lowercase + string.ascii_uppercase + '#$%^&*'
|
||||
|
||||
|
||||
def generate_salted_sha256_hash(password, salt_bytes):
|
||||
"""
|
||||
Generate SHA256 hash of a password concatenated with salt.
|
||||
|
||||
Args:
|
||||
password: The password string
|
||||
salt_bytes: The salt as bytes
|
||||
|
||||
Returns:
|
||||
SHA256 hash as hexadecimal string
|
||||
"""
|
||||
# Concatenate password bytes and salt bytes, then hash
|
||||
combined = password.encode() + salt_bytes
|
||||
return hashlib.sha256(combined).hexdigest()
|
||||
|
||||
|
||||
def read_salted_password_database(filename):
|
||||
"""
|
||||
Read salted password database from a text file.
|
||||
|
||||
Args:
|
||||
filename: Path to the file containing [username, salt, hash] entries
|
||||
|
||||
Returns:
|
||||
List of [username, salt, hash] entries
|
||||
"""
|
||||
database = []
|
||||
|
||||
try:
|
||||
with open(filename, 'r') as f:
|
||||
for line in f:
|
||||
line = line.strip()
|
||||
if line and line.startswith('[') and line.endswith(']'):
|
||||
# Remove brackets and split by comma
|
||||
content = line[1:-1]
|
||||
parts = content.split(',', 2) # Split into max 3 parts
|
||||
if len(parts) == 3:
|
||||
username = parts[0].strip()
|
||||
salt_hex = parts[1].strip()
|
||||
password_hash = parts[2].strip()
|
||||
# Convert salt from hex string to bytes
|
||||
salt_bytes = bytes.fromhex(salt_hex)
|
||||
database.append([username, salt_bytes, password_hash])
|
||||
|
||||
print(f"Loaded {len(database)} accounts from {filename}")
|
||||
return database
|
||||
|
||||
except FileNotFoundError:
|
||||
print(f"Error: File '{filename}' not found.")
|
||||
return []
|
||||
except Exception as e:
|
||||
print(f"Error reading file: {e}")
|
||||
return []
|
||||
|
||||
|
||||
def dictionary_attack_salted(password_database, N):
|
||||
"""
|
||||
Perform dictionary attack on salted password database.
|
||||
|
||||
Args:
|
||||
password_database: List of [username, salt, hash] entries
|
||||
N: Length of passwords to try
|
||||
|
||||
Returns:
|
||||
Dictionary mapping usernames to cracked passwords
|
||||
Time taken for the attack
|
||||
"""
|
||||
print(f"\n{'='*60}")
|
||||
print(f"Starting Dictionary Attack on Salted Hashes")
|
||||
print(f"Password length: {N}")
|
||||
print(f"Character set size: {len(CHARACTERS)}")
|
||||
print(f"Total possible passwords: {len(CHARACTERS)**N}")
|
||||
print(f"Number of accounts to crack: {len(password_database)}")
|
||||
print(f"{'='*60}\n")
|
||||
|
||||
cracked_passwords = {}
|
||||
start_time = time.time()
|
||||
attempts = 0
|
||||
|
||||
# For each user, we need to try all possible passwords with their specific salt
|
||||
for username, salt_bytes, stored_hash in password_database:
|
||||
print(f"Attacking {username} (salt: {salt_bytes.hex()})...")
|
||||
user_cracked = False
|
||||
user_attempts = 0
|
||||
|
||||
# Generate all possible passwords of length N
|
||||
for password_tuple in itertools.product(CHARACTERS, repeat=N):
|
||||
password = ''.join(password_tuple)
|
||||
user_attempts += 1
|
||||
attempts += 1
|
||||
|
||||
# Hash the password with this user's salt
|
||||
password_hash = generate_salted_sha256_hash(password, salt_bytes)
|
||||
|
||||
# Check if this hash matches the stored hash
|
||||
if password_hash == stored_hash:
|
||||
cracked_passwords[username] = password
|
||||
print(f"[+] Cracked! {username}: {password} (after {user_attempts} attempts)")
|
||||
user_cracked = True
|
||||
break
|
||||
|
||||
# Progress indicator for this user
|
||||
if user_attempts % 10000 == 0:
|
||||
print(f" Tried {user_attempts} passwords for {username}...")
|
||||
|
||||
if not user_cracked:
|
||||
print(f"[-] Failed to crack {username}")
|
||||
|
||||
end_time = time.time()
|
||||
time_taken = end_time - start_time
|
||||
|
||||
print(f"\n{'='*60}")
|
||||
print(f"Attack Complete!")
|
||||
print(f"Time taken: {time_taken:.4f} seconds")
|
||||
print(f"Total attempts: {attempts}")
|
||||
print(f"Passwords cracked: {len(cracked_passwords)}/{len(password_database)}")
|
||||
print(f"{'='*60}\n")
|
||||
|
||||
return cracked_passwords, time_taken
|
||||
|
||||
|
||||
def main():
|
||||
"""Main function to run the dictionary attack on salted passwords."""
|
||||
print("Dictionary Attack on Salted SHA256 Password Hashes")
|
||||
print("=" * 60)
|
||||
|
||||
# Get input file and password length from user
|
||||
filename = input("Enter password database filename: ")
|
||||
N = int(input("Enter password length N: "))
|
||||
|
||||
# Warn if N is too large
|
||||
if N > 4:
|
||||
total_passwords = len(CHARACTERS) ** N
|
||||
print(f"\nWarning: With N={N}, there are {total_passwords:,} possible passwords.")
|
||||
print("With salting, each user requires a separate full search!")
|
||||
confirm = input("Continue? (yes/no): ")
|
||||
if confirm.lower() != 'yes':
|
||||
print("Attack cancelled.")
|
||||
return
|
||||
|
||||
# Read password database from file
|
||||
print("\nReading password database...")
|
||||
password_database = read_salted_password_database(filename)
|
||||
|
||||
if not password_database:
|
||||
print("No valid data found. Exiting.")
|
||||
return
|
||||
|
||||
print("\nPassword Database:")
|
||||
for username, salt_bytes, password_hash in password_database:
|
||||
print(f"[{username}, {salt_bytes.hex()}, {password_hash}]")
|
||||
|
||||
# Perform dictionary attack
|
||||
cracked_passwords, time_taken = dictionary_attack_salted(password_database, N)
|
||||
|
||||
# Display results
|
||||
print("\nRecovered Passwords:")
|
||||
for username, password in cracked_passwords.items():
|
||||
print(f"{username}: {password}")
|
||||
|
||||
print(f"\nTotal time needed: {time_taken:.4f} seconds")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Loading…
x
Reference in New Issue
Block a user