今回はZIPとかPDFのパスワードを
総当たりで開けに行くやつのご紹介です

解説動画はこちら




ファイルにパスワード掛かっていて開けられないよーーー
どうにかならない?

そんな時ありますよね!!!!

そんな時はプログラムで突破すればいい

今回は
ZIPやPDFのパスワードを破るプログラム
についての解説です。


 
ライブラリのインストール

Google Colab上で
ZIPやPDFを扱うのに必要な
ライブラリのインストールです。
pip install pyzipper
pip install pypdf
pip install reportlab



パスワード付きファイルの用意

パスワード付きのZIP , PDFファイルを
作成しておきます。

今回のパスワードは
a12
として
PDFファイルや
ZIP用のファイルを先に作っておきます。

lock_password = "a12"

from reportlab.pdfgen import canvas
from PIL import Image

# PDFを作成
pdf_filename = "original.pdf"
c = canvas.Canvas(pdf_filename)
c.drawString(100, 750, "Hello, this is a sample PDF file.")
c.drawString(100, 730, "This PDF was created using Python and reportlab.")
c.save()

# ZIP用の内包ファイルを用意
with open("secret.txt","w") as _w:
    _w.write("This is a secret message")

Image.new("RGB", (100, 100), (255, 255, 255)).save("image.png")


パスワード付きのZIPファイルを作るコード
import pyzipper

# パスワード付きzipファイルを作成する
def create_protected_zip(file_list, zip_name, password):
    with pyzipper.AESZipFile(zip_name, 'w', compression=pyzipper.ZIP_DEFLATED, encryption=pyzipper.WZ_AES) as zf:
        zf.setpassword(password.encode("utf-8"))
        for file in file_list:
            zf.write(file)
    print(f"[+] パスワード付きZIPを作成: {zip_name}")

create_protected_zip(["secret.txt", "image.png"], "protected.zip", lock_password)


PDFにパスワードをかけるコード
from pypdf import PdfReader, PdfWriter

# パスワード付きpdfファイルを作成する
def create_protected_pdf(input_pdf, output_pdf, password):
    reader = PdfReader(input_pdf)
    writer = PdfWriter()
    
    for page in reader.pages:
        writer.add_page(page)

    writer.encrypt(password)  # パスワードを設定
    with open(output_pdf, "wb") as f:
        writer.write(f)
    print(f"[+] パスワード付きPDFを作成: {output_pdf}")

create_protected_pdf("original.pdf", "protected.pdf", lock_password)




ZIPとPDFファイルのパスワードを破るコード


ZIPとPDFに対応
総当たりでパスワードを当てにいくものです
一応辞書にも対応しています。
import itertools
import string
import zipfile
import pyzipper
from pypdf import PdfReader

def extract_zip(file_path, password):
    """ ZIPファイルの解凍 (ZIPCrypto & AES-256対応) """
    password_bytes = password.encode("utf-8")  # バイト列に変換
    try:
        with zipfile.ZipFile(file_path) as zf:
            zf.extractall(pwd=password_bytes)
        print(f"[+] ZIP のパスワード発見: {password}")
        return True
    except (RuntimeError, NotImplementedError):
        pass

    try:
        with pyzipper.AESZipFile(file_path) as zf:
            zf.setpassword(password_bytes)
            zf.extractall()
        print(f"[+] PDF のパスワード発見: {password}")
        return True
    except Exception as e:
        return False

def try_password(file_path, file_type, password):
    """ ZIP または PDF のパスワードを試す """
    try:
        if file_type == "zip":
            return extract_zip(file_path, password)
        elif file_type == "pdf":
            reader = PdfReader(file_path)
            if reader.decrypt(password) == 0:
                raise ValueError("Incorrect password")
            print(f"[+] PDF のパスワード発見: {password}")
            return True
    except Exception:
        return False

def password_cracker(file_path, mode="brute", password_list=None, max_length=4):
    """ ZIP/PDFファイルのパスワードを解析 """
    if file_path.endswith(".zip"):
        file_type = "zip"
    elif file_path.endswith(".pdf"):
        file_type = "pdf"
    else:
        print("[-] サポートされていないファイル形式です")
        return

    print(f"[*] {file_path} のパスワード解析開始 (モード: {mode})")

    count = 0

    # **辞書攻撃**
    if mode == "dictionary" and password_list:
        with open(password_list, "r", encoding="utf-8") as file:
            for password in file:
                count += 1
                if try_password(file_path, file_type, password.strip()):
                    print(f"[+] 試行回数: {count}")
                    return

    # **総当たり攻撃**
    elif mode == "brute":
        characters = string.ascii_lowercase + string.digits  # "abcdefghijklmnopqrstuvwxyz0123456789"
        for length in range(1, max_length + 1):
            for password in itertools.product(characters, repeat=length):
                count += 1
                if try_password(file_path, file_type, "".join(password)):
                    print(f"[+] 総当たり攻撃試行回数: {count}")
                    return

    print("[-] パスワードが見つかりませんでした")

使い方は
# 実行例(ZIP)
password_cracker("protected.zip", mode="brute", max_length=3)
[*] protected.zip のパスワード解析開始 (モード: brute)
[+] PDF のパスワード発見: a12
[+] 総当たり攻撃試行回数: 2333

こんな感じで、開けることができます。

max_length
を増やせば、大きな桁数のパスワードにも対応

文字種を増やしたい場合は
コード上の変数 characters
これに文字列を追加してください。




おまけ


文字種と文字数による
パスワードの強度についてです。

今回は文字種の数が 36種類
パスワード文字数が3桁でした

文字種36個の時の
パスワード桁数による最大試行回数は
以下のようになります。


パスワードの長さによる最大試行回数 : 文字数 01 :  0000000000000036
パスワードの長さによる最大試行回数 : 文字数 02 :  0000000000001296
パスワードの長さによる最大試行回数 : 文字数 03 :  0000000000046656
パスワードの長さによる最大試行回数 : 文字数 04 :  0000000001679616
パスワードの長さによる最大試行回数 : 文字数 05 :  0000000060466176
パスワードの長さによる最大試行回数 : 文字数 06 :  0000002176782336
パスワードの長さによる最大試行回数 : 文字数 07 :  0000078364164096
パスワードの長さによる最大試行回数 : 文字数 08 :  0002821109907456
パスワードの長さによる最大試行回数 : 文字数 09 :  0101559956668416
パスワードの長さによる最大試行回数 : 文字数 10 :  3656158440062976



一般的なPCであれば7-8桁くらいまでなら
開けられそうですね


これ以上となると
少し工夫が必要になってきます。

まあ、会社で使うパスワードは
6桁くらいまでに抑えておいた方が
いざというとき開けられなくなるんで
いいかもしれません


今回はパスワードが開けられなくて困った際の
パスワード開けプログラムについてでした

今日はここまでです
それでは。