2014年8月11日 星期一

兆基解密


得到一個加了密碼的 PDF,但沒有密碼。要如何打開呢?暫時知道密碼組合是 0-9 及 a-f,32 個字符,256-bits。以前試過用 Windows 平台的密碼搜尋工具,那時運行了三天也沒有變穫;知道 CoreGraphics 有 PDF 相關的功能,沒試過,於是嘗試一下。簡單編了個 Mac 程式,感覺會快一點。跑了一天,嘗試了 37,000,000 個組合,距離最大上限還有非常之遠的長度,應該要跑一年才能找到,還是另尋他法...。
#import "AppDelegate.h"

@implementation AppDelegate

int crackPDF(const char *filename)  {
 CFStringRef path = CFStringCreateWithCString (NULL, filename, kCFStringEncodingUTF8);
 CFURLRef url = CFURLCreateWithFileSystemPath (NULL, path, kCFURLPOSIXPathStyle, 0);
 CGPDFDocumentRef myDocument = CGPDFDocumentCreateWithURL(url);

 if (myDocument == NULL) {
  printf ("can't open `%s'.", filename);
  CFRelease (url);
  return EXIT_FAILURE;
 }
 CFRelease (url);

 if (CGPDFDocumentIsEncrypted(myDocument)) {

  const char *startPassword = "00000000000000000000000000000000";
  size_t length = strlen(startPassword);
  char password[length+1];

  //  Set initial password
  password[length] = 0;
  for (int k=0; k<length; k++)  {
   password[k] = startPassword[k];
  }
  
  printf("\nDecode start...");
  int i = 0;
  int count = 0;
  bool done = false;
  while (done == false)  {

   done = CGPDFDocumentUnlockWithPassword(myDocument, password);
   if (done == false)  {

    size_t k = length-1;
    while (k > 0)  {

     password[k]++;
     if (password[k] == ':')  {password[k] = 'a';}
     if (password[k] >= 'g')  {
      password[k] = '0';
      k--;
     }  else  {
      k = 0;
     }
    }
   }  else  {
    printf("\nUnlocked by %s", password);
   }

   i++;
   if (i >= pow(16, 32))  {
    done = true;
    printf("\nLoop limit reached.\n\n");
   }

   count++;
   if (count >= 100000)  {
    count = 0;
    printf("\n100000 done...%s", password);
   }
  }
 }

 if (!CGPDFDocumentIsUnlocked (myDocument)) {
  printf("can't unlock `%s'.", filename);
  CGPDFDocumentRelease(myDocument);
  return EXIT_FAILURE;
 }

 size_t pageCount = CGPDFDocumentGetNumberOfPages(myDocument);
 printf("\nPage count: %ld", pageCount);
 if (pageCount == 0) {
  CGPDFDocumentRelease(myDocument);
  return EXIT_FAILURE;
 }

 return EXIT_SUCCESS;
}

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification  {
 int result = crackPDF("sita_chan.pdf");
 NSLog(@"Done!");
}

@end

沒有留言: