Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save ww9/6b674402984e5eca2529b3db6574a53c to your computer and use it in GitHub Desktop.
Save ww9/6b674402984e5eca2529b3db6574a53c to your computer and use it in GitHub Desktop.

Cracking PDF password with broteforce using Docker + Python

I needed to pay a bill where the barcode was password protected.

I found https://gist.github.com/dhondta/efe84a92e4dfae3b6c14932c73ab2577 but the Dockerfile was broken becuase it used abbandoned CentOS.

So I converted the Dockerfile to Ubuntu and it worked! Took around 20 seconds to crack 3 number password.

Instructions

  1. Download both files in the same directory: Dockerfile and pdf-password-bruteforcer.py

  2. Copy your PDF file to the same directory

  3. Build docker image with docker build -t pdftool .

  4. Run docker image with a terminal inside it with: docker run --rm -it pdftool /bin/bash

  5. Once you are inside the running container execute: python3 pdf-password-bruteforcer.py your_pdf_file.pdf

  6. By default it will use this regular expression to generate password attempts:

^[0-9a-zA-Z!-_]{1,8}

Which means it will try to use numbers, letters, !, - and _. Between 1 and 8 characters.

But you can specify your own regex like so:

python3 pdf-password-bruteforcer.py -p '[a-z0-9]{5}' your_pdf_file.pdf

This will try only passwords with 5 characters, and it will only try lower case letters and numbers.

# Usage:
# docker build -t pdftool .
# docker run --rm -it pdftool /bin/bash
# >> python3 pdf-password-bruteforcer.py your_pdf_file.pdf
FROM ubuntu:20.04
# set environment variables
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
ENV APP_HOME=/app
WORKDIR $APP_HOME
# install system dependencies
RUN apt-get update -y && \
apt-get install -y gcc python3 python3-pip python3-dev && \
apt-get clean
RUN pip3 install --upgrade pip
# Install reqs and copy over files from context
COPY . $APP_HOME
RUN chmod +x $APP_HOME/*
RUN pip3 install pypdf tinyscript
# pdf-password-bruteforcer.py contents below:
# #!/usr/bin/python3
# from tinyscript import *
# try:
# import pikepdf
# BACKEND = "pikepdf"
# except ImportError:
# import pypdf
# BACKEND = "pypdf"
# __author__ = "Alexandre D'Hondt"
# __version__ = "1.4"
# __copyright__ = ("A. D'Hondt", 2020)
# __license__ = "gpl-3.0"
# __examples__ = ["secret.pdf -p '[a-z0-9]{5}'"]
# __doc__ = """
# *PDF Password Bruteforcer* allows to execute a bruteforce attack on a given PDF file,
# setting a regular expression pattern for the target password.
# """
# BANNER_FONT = "tombstone"
# BANNER_STYLE = {'fgcolor': "lolcat"}
# def bruteforce_pdf_password(path, regex):
# if BACKEND == "pypdf":
# with open(path, 'rb') as f:
# reader = pypdf.PdfReader(f)
# for p in ts.bruteforce_re(regex):
# logger.debug(p)
# try:
# reader.decrypt(p)
# len(reader.pages)
# logger.success("FOUND: " + p)
# return True
# except pypdf.errors.FileNotDecryptedError:
# pass
# except Exception as e:
# logger.exception(e)
# break
# else:
# for p in ts.bruteforce_re(regex):
# logger.debug(p)
# try:
# with pikepdf.open(path, password=p) as f:
# logger.success("FOUND: " + p)
# return True
# except pikepdf._qpdf.PasswordError:
# pass
# except Exception as e:
# logger.exception(e)
# break
# return False
# if __name__ == '__main__':
# parser.add_argument("file", type=ts.file_exists, help="encrypted PDF file")
# parser.add_argument("-p", "--pattern", default="^[0-9a-zA-Z!-_]{1,8}", help="password pattern")
# initialize(add_time=True, noargs_action="demo", action_at_interrupt="confirm")
# logger.info("Starting PDF password bruteforce...")
# logger.handlers[-1].terminator = ""
# if not bruteforce_pdf_password(args.file, args.pattern):
# logger.failure("Password not found")
#!/usr/bin/python3
from tinyscript import *
try:
import pikepdf
BACKEND = "pikepdf"
except ImportError:
import pypdf
BACKEND = "pypdf"
__author__ = "Alexandre D'Hondt"
__version__ = "1.4"
__copyright__ = ("A. D'Hondt", 2020)
__license__ = "gpl-3.0"
__examples__ = ["secret.pdf -p '[a-z0-9]{5}'"]
__doc__ = """
*PDF Password Bruteforcer* allows to execute a bruteforce attack on a given PDF file,
setting a regular expression pattern for the target password.
"""
BANNER_FONT = "tombstone"
BANNER_STYLE = {'fgcolor': "lolcat"}
def bruteforce_pdf_password(path, regex):
if BACKEND == "pypdf":
with open(path, 'rb') as f:
reader = pypdf.PdfReader(f)
for p in ts.bruteforce_re(regex):
logger.debug(p)
try:
reader.decrypt(p)
len(reader.pages)
logger.success("FOUND: " + p)
return True
except pypdf.errors.FileNotDecryptedError:
pass
except Exception as e:
logger.exception(e)
break
else:
for p in ts.bruteforce_re(regex):
logger.debug(p)
try:
with pikepdf.open(path, password=p) as f:
logger.success("FOUND: " + p)
return True
except pikepdf._qpdf.PasswordError:
pass
except Exception as e:
logger.exception(e)
break
return False
if __name__ == '__main__':
parser.add_argument("file", type=ts.file_exists, help="encrypted PDF file")
parser.add_argument("-p", "--pattern", default="^[0-9]{1,8}", help="password pattern")
initialize(add_time=True, noargs_action="demo", action_at_interrupt="confirm")
logger.info("Starting PDF password bruteforce...")
logger.handlers[-1].terminator = ""
if not bruteforce_pdf_password(args.file, args.pattern):
logger.failure("Password not found")
@ww9
Copy link
Author

ww9 commented Oct 11, 2024

Example of it cracking a 3 number password (took 20 seconds):

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment