January 07, 2010

Crack PDF password - Java Brute force algorithm

Recently I was in a big mess when I lost the password for an important PDF document. I ended up using the Brute force algorithm and cracked the PDF password.

PDFBox API is being used in the below code to open the PDF file. Please download the dependent JAR files from here.


Word of caution: Based on the length of the password, it might even take few days to run it.


package com.bruteforce;

import java.io.IOException;

import org.apache.pdfbox.exceptions.CryptographyException;
import org.apache.pdfbox.exceptions.InvalidPasswordException;
import org.apache.pdfbox.pdmodel.PDDocument;

public class BruteForceDecryptPDF {

 private static final String PDF_FILE_PATH = "c:/file2.pdf";
 private static final int PASSWORD_MAX_LENGTH = 4;
 private static final int PASSWORD_MIN_LENGTH = 2;
 // Array with characters to use in Brute Force Algorithm.
 // You can remove or add more characters in this array.
 private static char fCharList[] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
   'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u',
   'v', 'w', 'x', 'y', 'z','0','1','2','3','4','5','6','7','8',
   '9'};

 public static void main(String[] args) {
  long startTime=System.currentTimeMillis();
  PDDocument document = null;
  boolean found = false;
  try {
   document = PDDocument.load(PDF_FILE_PATH);

   for (int i = PASSWORD_MIN_LENGTH; i <= PASSWORD_MAX_LENGTH; i++) { 
    try {
     startBruteForce(i, document);
    }catch(PasswordFoundInterrupter ex){
     found=true;
     System.out.println("SUCCESS. PASSWORD: - " + ex.getMessage());
    }
    catch (Exception e) {
     e.printStackTrace();
    }
   }
   if(!found){
    System.out.println("Failure - Password not found");
   }
   document.close();
   long timeTaken=System.currentTimeMillis()-startTime;
   System.out.println("TOTAL TIME TAKEN - " + timeTaken);
  } catch (IOException e) {
   System.out.println("PDF File not found at - "+ PDF_FILE_PATH);
   throw new RuntimeException(e);
  }
 }

 public static void startBruteForce(int length, PDDocument document) {
  StringBuffer sb = new StringBuffer(length);
  char currentChar = fCharList[0];

  for (int i = 1; i <= length; i++) {
   sb.append(currentChar);
  }

  changeCharacters(0, sb, length, document);
 }

 private static StringBuffer changeCharacters(int pos, StringBuffer sb,
   int length, PDDocument document) {
  for (int i = 0; i <= fCharList.length - 1; i++) {
   sb.setCharAt(pos, fCharList[i]);
   if (pos == length - 1) {    
    // Uncomment this to see the generated passwords. It may slow down if you are trying for larger size passwords.
    //System.out.println(sb.toString());
    if(valid(sb.toString(),document)){
     throw new BruteForceDecryptPDF.PasswordFoundInterrupter(sb.toString());
    }
   } else {
    changeCharacters(pos + 1, sb, length, document);
   }
  }

  return sb;
 }
 
 public static boolean valid(String password, PDDocument document) {
  System.out.println(password);
  try {
   document.decrypt(password);
   System.out.println("Success - " + password);
   return true;
  } catch (IOException e) {
   throw new RuntimeException(e);
  } catch (CryptographyException e) {
   return false;
  } catch (InvalidPasswordException e) {
   return false;
  }
 }
 
 private static class PasswordFoundInterrupter extends RuntimeException{
  public PasswordFoundInterrupter(String message) {
   super(message);
  }  
 }
}  

6 comments:

  1. it will not decrypt passwords except 'aaaa'. because of the line of the code char currentChar = fCharList[0]; . you dont loop and refresh the function changecharacters and startbruteforce

    ReplyDelete
  2. Thanks for sharing your observation Kaan. I was editing the code while copying it to the blog and by mistake I had deleted the important line which changes the password in changeCharacters method.
    sb.setCharAt(pos, fCharList[i]);

    It is a good lesson for me as well to verify the code after posting it.

    ReplyDelete
  3. oh you welcome ;) this kind of problems can happen anytime. thanks for your code also :) it helped me very much for writing brute force codes for database cracking

    ReplyDelete
  4. it works perfect now but i have a question. why you have not used multiple threads. you know it will finish it in very short time. and you used changeCharacters method like a loop , I think it will waste lots of memory after some time

    ReplyDelete
  5. hey guyzz, i am really freaking out, i forgot my pdf password, and i have to open the file, plzzz be kind to be and guide me with this procedure to crack the password. i am in very hurry! plzzz understand. how do i run this file.

    ReplyDelete
  6. How to use or test when I try to compile the above code but errors was there
    1-the thrown errors never been thrown
    2-the org.apache.pdfbox is not available

    Iam sure I had made a mistake but pls help me as iam new to java

    ReplyDelete