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