|
#!/usr/bin/env python3 |
|
import os |
|
from datetime import datetime |
|
from typing import Optional |
|
import argparse |
|
|
|
import pikepdf |
|
from tqdm import tqdm |
|
|
|
|
|
# Generate a list of passwords of every date in MMddyyyy format |
|
def dates_between_years(start_year: int = 2000, end_year: int = 2020) -> list: |
|
passwords = [ |
|
str(i).zfill(2) + str(j).zfill(2) + str(k).zfill(4) |
|
for i in range(1, 13) |
|
for j in range(1, 32) |
|
for k in range(start_year, end_year) |
|
] |
|
return passwords |
|
|
|
|
|
def crack_pdf( |
|
pdf_file: str, passwords: list, save_unencrypted: bool = False |
|
) -> Optional[str]: |
|
# Check if pdf_file is a valid file |
|
if not os.path.isfile(pdf_file): |
|
print("[-] File does not exist") |
|
return None |
|
|
|
# Loop through all passwords in the list |
|
for password in tqdm(passwords, "Decrypting PDF", unit=" passwords"): |
|
try: |
|
# Try to open the pdf file with the password |
|
with pikepdf.open(pdf_file, password=password) as pdf: |
|
# Password decrypted successfully, break out of the loop |
|
if save_unencrypted: |
|
pdf.save(f"{pdf_file}.decrypted") |
|
|
|
return password |
|
except pikepdf._qpdf.PasswordError: |
|
# Password was incorrect, continue to the next password |
|
continue |
|
except pikepdf._qpdf.PdfError: |
|
# File is not a valid pdf file, break out of the loop |
|
print("[-] File is not a valid pdf file") |
|
break |
|
return None |
|
|
|
|
|
def get_args() -> argparse.Namespace: |
|
parser = argparse.ArgumentParser( |
|
description="Crack PDF files using a wordlist of dates" |
|
) |
|
parser.add_argument( |
|
"pdf_file", |
|
type=str, |
|
help="PDF file to crack", |
|
metavar="PDF_FILE", |
|
) |
|
parser.add_argument( |
|
"--save", |
|
action="store_true", |
|
help="Save decrypted PDF file", |
|
) |
|
parser.add_argument( |
|
"--wordlist", |
|
type=str, |
|
help="Wordlist of dates to crack", |
|
metavar="WORDLIST", |
|
) |
|
parser.add_argument( |
|
"--start-year", |
|
type=int, |
|
help="Start year of dates to crack", |
|
metavar="START_YEAR", |
|
) |
|
parser.add_argument( |
|
"--end-year", |
|
type=int, |
|
help="End year of dates to crack", |
|
metavar="END_YEAR", |
|
default=datetime.now().year, |
|
) |
|
return parser.parse_args() |
|
|
|
|
|
def main(): |
|
args = get_args() |
|
|
|
passwords = [] |
|
if args.wordlist: |
|
passwords = [line.strip() for line in open(args.wordlist)] |
|
if args.start_year: |
|
passwords.extend(dates_between_years(args.start_year, args.end_year)) |
|
|
|
correct_password = crack_pdf(args.pdf_file, passwords) |
|
if correct_password: |
|
print("[+] Password found:", correct_password) |
|
else: |
|
print("[-] Password not found") |
|
|
|
|
|
if __name__ == "__main__": |
|
main() |