Skip to content

Instantly share code, notes, and snippets.

@dhondta
Last active Apr 5, 2022
Embed
What would you like to do?
Tinyscript tool to bruteforce the password of a PDF

PDF password bruteforcer

This is a small tool using Tinyscript and PyPDF2 to bruteforce the password of a PDF given an alphabet (defaults to printables) and a length (default is 8).

$ pip install PyPDF2 tinyscript
$ wget https://gist.githubusercontent.com/dhondta/efe84a92e4dfae3b6c14932c73ab2577/raw/pdf-password-bruteforcer.py && chmod +x pdf-password-bruteforcer.py && sudo mv pdf-password-bruteforcer.py /usr/bin/pdf-password-bruteforcer

#!/usr/bin/python3
from tinyscript import *
try:
import pikepdf
BACKEND = "pikepdf"
except ImportError:
import PyPDF2
BACKEND = "PyPDF2"
__author__ = "Alexandre D'Hondt"
__version__ = "1.3"
__copyright__ = ("A. D'Hondt", 2020)
__license__ = "gpl-3.0"
__docformat__ = "md"
__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 == "PyPDF2":
with open(path, 'rb') as f:
reader = PyPDF2.PdfFileReader(f)
for p in ts.bruteforce_re(regex):
logger.debug(p)
try:
reader.decrypt(p)
reader.getNumPages()
logger.success("FOUND: " + p)
return True
except:
pass
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
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")
H4sICGaOFGIAA3Rlc3QucGRmAK2UTWgUSRTHPXmowx5EArIRSiSSBLLV1d3T0y1jdrUnk406JmbG
LxI/qrurk44zXWNNzZK4iiCCiHgQRQ+CelAPKnrwEEFQxEsOSlAPgt78APHiVd1dd2t6xt7OTlxz
sOlLv/q/V7//q3rdMZTN9eCfdNDx8tXsU4ChApkzAUEmA1BxqkIhsokgJTYG0BAZo1WoSsUw6O0F
NPQipZpM2RB4VTii1TU7vxSI8gCyWS0UECdTtWSqzUJBQ1GFerQDKo7Xyg5MNT/iSgAN0yqrcVey
RHlDnLkFKqDRUG4fdCaoKxprA2UFpr8Ay1dW4HKPpglkc1ZZxybhiCK/McQSOU+9gMyNJYD1JPBG
Go6Jcaim64qq4JSUweW1EzsubOleu/jo51s/w/yaw5XJk+1nNp94fhvVizRUMK5nNOuNIHkMEBXp
pIASWtq0d8ai9NwulRgvVIhLodkwsYmUaT1JAahQc0TUqKgEQL/SYGy83nOUC0qCcrlPrkQEzVKX
eTQ+oGbLANoWeNKQlBfypLoXWo0N1gWiOkS5zcoVFta7Z8berYT118f2/9hzr/hDfj6jZtMDytLf
Apf2czIVr6X+3983TcTUCwTd3b34lydL3x3fNR+o9RWYJHiz5XnyPVu+QHh+d++SlXD9/SPzwWMl
ST8IO2+O+v6BmQH983Lv7Ko7E8Pnz13paxsYDT/92f/Hg33jL95Xu+RMwB7NUnQ5WFCLsVFBkNAj
3ANoC+wcdaYfXr0+c2rrQ2X5m0dt9uNF/3lkma1QjYmxaibHBs/5reSZl5UdgZ1BZvXrfQcPnZl9
69p/s7ZDXfWJpEQELPyqQE67V3MlYGcfP3BJqe05fnpabb+m5VZ8zM4u+/DBkJpiIEoy++nHUeei
3T347K8bhd+7EjyTnPpADrcKlPiBRiqlpaAP4xiW9zJaCf+NGUZLDKutOk1RW2KGrrXqzFadjq3W
3HlY0qbeErPSLXvgOXyCk6BEOWj8HEOfweho5JT1hS6fqsiLqzS+B7JwJOOmTFf3PExV00o7xE87
HtYdxzB9zXIc0+rNYJ9SVfFVzTStFHFNz6CKmtIlsTSMidUrb/wwY7Juo2wh2E/rjY8uNOEiOgqs
Gibo6OgbzIF/AMArx2CPBgAA
@Paulemeister
Copy link

Paulemeister commented Feb 21, 2022

Either I have brain-rot or the patterns don't work. Even testing a pdf with password "AB" and using the pattern "^[A-Z]{2}" doesn't work. Also the verbose output is very inconsistent. Sometimes the tried passwords are on new lines, sometimes it gets replaced on the same line. Thanks for the work though. Plus the help only shows with --help and not -h. and the help has the old alphabet/length stuff in it, which was removed

@dhondta
Copy link
Author

dhondta commented Feb 22, 2022

Hi @Paulemeister !
Thank you for reporting this.
I have made some changes to the bruteforce_re function recently (when I figured out itertools.product2 caused an issue with concatenated ranges, e.g. [a-bA-B] ; this caused to generate the combinations of [a-b] and [A-B]).
Can you tell me if you use one of the latest versions of Tinyscript (>=1.24.13), please ?

Edit: I tested your use case ; it works as expected.

  • The debug message displays on the same line, because of the line logger.handlers[-1].terminator = "".
  • The solution is displayed above the last debug message (because of the aforementioned line).
$ pdf-password-bruteforce -v test2.pdf -p "[A-Z]{2}"
[...]
12:34:56 [INFO] Starting PDF password bruteforce...
12:34:56 [SUCCESS] FOUND: AB

@Paulemeister
Copy link

Paulemeister commented Feb 23, 2022

Btw, I am on Linux, but that shouldn't really matter with python. My tinyscript version is 1.24.14. Thanks for the quick response

@Paulemeister
Copy link

Paulemeister commented Feb 23, 2022

I narrowed it down to PyPDF2. It isn't maintained since 2018. I went step by step with the python shell and got this error:
NotImplementedError: only algorithm code 1 and 2 are supported So maybe i just gotta use pikepdf

@dhondta
Copy link
Author

dhondta commented Feb 23, 2022

@Paulemeister
You can try with version 1.3 ; it now supports pikepdf as the backend for handling the input PDF.

@iulian0512
Copy link

iulian0512 commented Mar 5, 2022

tinyscript can't be installed on macos, win10 and ubuntu due to old pathlib dependency, see dhondta/python-tinyscript#24

@cGIfl300
Copy link

cGIfl300 commented Apr 1, 2022

Works fine on linux mint, thank you, now perhaps I'll get a result :D

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