不放心在线服务的可以使用这个脚本暴力破解
import argparse
import datetime
from multiprocessing import Pool, cpu_count
import sys
import fnmatch
try:
from pypdf import PdfReader
except ImportError:
try:
from PyPDF2 import PdfReader
except ImportError:
print("缺少依赖!请先运行: pip install pypdf")
sys.exit(1)
def generate_dates(start_year, end_year):
start_date = datetime.date(start_year, 1, 1)
end_date = datetime.date(end_year, 12, 31)
delta = datetime.timedelta(days=1)
current = start_date
while current <= end_date:
yield current
current += delta
def format_date(d, fmt):
if fmt == "DD/MM/YYYY":
return d.strftime("%d/%m/%Y")
elif fmt == "D/M/YYYY":
return f"{d.day}/{d.month}/{d.year}"
elif fmt == "DDMMYYYY":
return d.strftime("%d%m%Y")
elif fmt == "YYYYMMDD":
return d.strftime("%Y%m%d")
elif fmt == "YYMMDD":
return d.strftime("%y%m%d")
elif fmt == "MM/DD/YYYY":
return d.strftime("%m/%d/%Y")
else:
return d.strftime("%d/%m/%Y")
def try_password(args):
file_path, password = args
try:
# 为了避免输出一大堆错误日志,我们禁用PdfReader内部的部分警告
reader = PdfReader(file_path, strict=False)
if reader.decrypt(password) != 0:
return password
except Exception:
pass
return None
def main():
parser = argparse.ArgumentParser(description="PDF 生日密码暴力破解工具")
parser.add_argument("file", help="PDF 文件路径")
parser.add_argument("--start-year", type=int, default=1900, help="起始年份,默认 1900")
parser.add_argument("--end-year", type=int, default=2026, help="结束年份,默认 2026")
parser.add_argument("--pattern", type=str, default="*", help="已知的模式。例如:??/05/199? 或 12/??/????")
parser.add_argument("--formats", type=str, nargs="+",
default=["DD/MM/YYYY", "DDMMYYYY", "D/M/YYYY", "YYYYMMDD"],
help="要尝试的日期格式,可以传入多个")
args = parser.parse_args()
print("正在生成可能的密码组合...")
candidates = []
for d in generate_dates(args.start_year, args.end_year):
for fmt in args.formats:
pwd = format_date(d, fmt)
if fnmatch.fnmatch(pwd, args.pattern):
candidates.append(pwd)
# 去重
candidates = list(set(candidates))
print(f"符合条件的候选密码总数: {len(candidates)}")
if len(candidates) == 0:
print("没有找到符合所给 --pattern 条件的候选密码。")
return
print(f"正在启动暴力破解任务 (使用 {cpu_count()} 核心多进程并行)...")
pool_args = [(args.file, pwd) for pwd in candidates]
chunksize = max(1, len(pool_args) // (cpu_count() * 4))
count = 0
total = len(candidates)
with Pool(processes=cpu_count()) as pool:
for result in pool.imap_unordered(try_password, pool_args, chunksize=chunksize):
count += 1
if count % 1000 == 0:
print(f"进度: {count} / {total} ...", end='\r')
if result:
print(f"\n\n===========================================")
print(f"[✅ 成功破解] 该 PDF 文件的密码是: {result}")
print(f"===========================================\n")
pool.terminate()
return
print(f"\n[❌ 破解失败] 在 {len(candidates)} 个候选密码中没有找到正确的密码。")
if __name__ == "__main__":
main()