Bring down the wall

Website to crack PDFs

Released: PDF password cracker

Javascript automation

While checking my bank balances, I realized that I have lost access to my SBI account since it hasn’t been checked in a few months. The only way for me to know the pending amount was to check the email statement, but even that was password protected. To add to my injury, the password had parts of my previous phone number which I lost several years ago.

I know from the statement email, that password is of the format:

<last 5 digits of phone number><dob in ddmmyy format>

Since this came down to guessing just the 5-digits of a number, I quickly wrote a python script to do the same and open-sourced SBI PDF Statement cracker GitHub gist. Sneak peek below:

The above is python script needs the ability to install pdfplumber and execute on the terminal which isn’t very user friendly. So, I thought to go through some extra effort and remove that user friction. I decided to use an HTML webpage with Javascript which can do the password cracking on the browser.

My Idea

In short, the following are the key goals to develop this website:

  • Allow users to upload a PDF file

  • Create a password template (a range of numbers to loop over, a fixed prefix and suffix)

  • Loop over the pdf and show the under processing label

  • Display the cracked password and pdf once done, else show password not found.

As POC, I made a simple website to showcase this, here it is: PDF password cracker.

Flow

  1. Allow users to upload a PDF file:

    This can be achieved using an HTML input element. But I needed to restrict to only using PDF files, so I added an accept attribute.

    
     <input id="source_pdf_file_path" type="file" name="Upload" onchange="previewFile()" accept=".pdf" />
    
     // Load this script
     <script>
       function previewFile() {
         const preview = document.querySelector('iframe');
         const file = document.querySelector('input[type=file]').files[0];
         const reader = new FileReader();
         var filename = file.name;
         reader.addEventListener("load", function () {
           // convert file to base64 string
           preview.src = reader.result;
         }, false);
         if (file) {
           reader.readAsDataURL(file);
         }
       }
     </script>
     
  2. Create a password template:

    Creating a password template needed a couple of fields, each for prefix, suffix, starting loop number, ending loop number, and a button to start cracking. So, here it was for me:

    
     <input id="txt_prefix" type="text" name="prefix" placeholder="prefix" />
     <input id="txt_start_num" type="number" min="0" name="start_num" placeholder="Starting number" />
     <input id="txt_end_num" type="number" min="0" name="end_num" placeholder="Last number" />
     <input id="txt_suffix" type="text" name="suffix" placeholder="suffix" />
     <button id="btn_crack_pdf">Crack PDF</button>
     
  3. Loop over the pdf with a password:

    This involved forming a password in a loop and attempt to crack the PDF.

    
     // fetch password parts
     const prefix = document.getElementById('txt_prefix').value;
     const suffix = document.getElementById('txt_suffix').value;
     var pwd_start_num = parseInt(document.getElementById('txt_start_num').value) || 0;
     var pwd_end_num = parseInt(document.getElementById('txt_end_num').value) || 0;
     // swap values if reversed range
     if (pwd_end_num &lt; pwd_start_num) {
       temp = pwd_end_num;
       pwd_end_num = pwd_start_num;
       pwd_start_num = temp;
       // pwd_start_num, pwd_end_num = pwd_end_num, pwd_start_num; // works only in python lol
     }
    
     for (let i = pwd_start_num; i &lt;= pwd_end_num; i++) {
       var cur_pwd = `${prefix}${i}${suffix}`;
       const attempt = await load_pdf_from_url(window.source, cur_pwd);
       if (!attempt) {
         getStatusLabelText('FAILED', cur_pwd);
       } else {
         getStatusLabelText('SUCCESS', cur_pwd);
         break;
       }
     }
     
  4. Attempt to display the cracked password:

    
       async function load_pdf_from_url(source, passwd) {
         // sanitize params
         if (!passwd || typeof passwd.valueOf() != "string" || passwd.length &lt;= 0) {
           // ignore password since improperly formed
           passwd = '';
         }
    
         try {
           // If absolute URL from the remote server is provided, configure the CORS
           // header on that server.
           const pdfjsLib = window['pdfjs-dist/build/pdf'];
    
           // The workerSrc property shall be specified.
           pdfjsLib.GlobalWorkerOptions.workerSrc = 'pdfjs-dist/pdf.worker.js';
    
           const pdf = await pdfjsLib.getDocument({ data: source, password: passwd }).promise;
           const page = await pdf.getPage(1); // page number 1
           // const tokenizedText = await page.getTextContent();
           var scale = 1.5;
           var viewport = page.getViewport({ scale: scale });
           // Render PDF page into canvas context
           var renderContext = {
             canvasContext: context,
             viewport: viewport
           };
           await page.render(renderContext).promise;
           if (passwd) {
             document.getElementById('iframe-pdf').hidden = false;
             return true;
           }
         } catch (e) {
           console.error(e);
           getStatusLabelText('PROCESSING');
           return false;
         }
       }
     

I felt it was straightforward to implement and does not have many dependencies to slow me down. Having a simple website to upload and crack PDF password works just fine for my use cases. I felt it would be super awesome to have the following features - which would be a value add:

  • UI elements can show % of the job accomplished
  • Pause and resume the loop to crack the password!
  • Language change option
  • Adding audio feedback for the visually impaired

For my demo, the source is hosted on GitHub repo: PDF Cracker, quick sneak peek is below:

Preview

Demo Video

TECH
javascript website browser

Dialogue & Discussion