|
#!/usr/bin/env python3 |
|
|
|
import itertools |
|
import subprocess |
|
import sys |
|
import os |
|
|
|
def unlock_volume(volume_id, passphrase): |
|
"""Tries to unlock the volume using the provided passphrase.""" |
|
try: |
|
# Run the diskutil command to attempt to unlock the volume |
|
result = subprocess.run( |
|
['diskutil', 'apfs', 'unlockVolume', volume_id, '-stdinpassphrase'], |
|
input=passphrase.encode(), |
|
stdout=subprocess.PIPE, |
|
stderr=subprocess.PIPE |
|
) |
|
|
|
# Print output for debugging purposes |
|
print(f"DiskUtil stdout: {result.stdout.decode().strip()}") |
|
print(f"DiskUtil stderr: {result.stderr.decode().strip()}") |
|
|
|
# Return True if the unlock was successful (stdout contains success message) |
|
return result.returncode == 0 and "Unlocked" in result.stdout.decode() |
|
except subprocess.CalledProcessError as e: |
|
print(f"Error: {e}") |
|
return False |
|
|
|
def load_words(file_path): |
|
"""Loads the dictionary words from the file.""" |
|
with open(file_path, 'r') as f: |
|
return [line.strip() for line in f] |
|
|
|
def load_attempted_passwords(log_file): |
|
"""Loads passwords that have already been attempted from used.txt.""" |
|
if not os.path.exists(log_file): |
|
return set() # If log file doesn't exist, return an empty set |
|
|
|
with open(log_file, 'r') as f: |
|
return set(line.strip() for line in f) |
|
|
|
def main(volume_id, dictionary_file, log_file, max_combination_length=2): |
|
# Load dictionary words |
|
words = load_words(dictionary_file) |
|
|
|
# Load previously attempted passwords |
|
attempted_passwords = load_attempted_passwords(log_file) |
|
|
|
# Open log file to append newly tried passwords |
|
with open(log_file, "a") as log_file_obj: |
|
# Generate combinations of words (up to the specified max length) |
|
for combination_length in range(1, max_combination_length + 1): |
|
for combination in itertools.product(words, repeat=combination_length): |
|
passphrase = ''.join(combination) # No spaces between words |
|
|
|
# Skip passwords that have already been attempted |
|
if passphrase in attempted_passwords: |
|
continue |
|
|
|
# Log the used passphrase |
|
log_file_obj.write(passphrase + '\n') |
|
log_file_obj.flush() |
|
|
|
print(f"Trying passphrase: {passphrase}") |
|
|
|
# Try unlocking the volume |
|
if unlock_volume(volume_id, passphrase): |
|
print(f"Success! Passphrase: {passphrase}") |
|
return # Stop on success |
|
|
|
print("No valid passphrase found.") |
|
|
|
if __name__ == "__main__": |
|
if len(sys.argv) != 2: |
|
print(f"Usage: {sys.argv[0]} <volume_id>") |
|
sys.exit(1) |
|
|
|
volume_id = sys.argv[1] # e.g., "disk2s1" |
|
|
|
# Assuming list.txt and used.txt are always in the current working directory |
|
dictionary_file = os.path.join(os.getcwd(), 'list.txt') |
|
log_file = os.path.join(os.getcwd(), 'used.txt') |
|
|
|
# Adjust the max_combination_length if you want to try more words in combinations |
|
main(volume_id, dictionary_file, log_file, max_combination_length=5) |