diff --git a/src/pdf_fmt_plug.c b/src/pdf_fmt_plug.c index 76dd731d46..530396a22d 100644 --- a/src/pdf_fmt_plug.c +++ b/src/pdf_fmt_plug.c @@ -1,11 +1,13 @@ -/* PDF cracker patch for JtR. Hacked together during Monsoon of 2012 by +/* + * PDF cracker patch for JtR. Hacked together during Monsoon of 2012 by * Dhiru Kholia . * - * This software is Copyright (c) 2012, Dhiru Kholia - * - * Uses code from Sumatra PDF and MuPDF which are under GPL. + * This software is + * Copyright (c) 2012, Dhiru Kholia + * Copyright (c) 2013, Shane Quigley + * Copyright (c) 2024, magnum * - * Edited by Shane Quigley in 2013. + * Uses code from pdfcrack, Sumatra PDF and MuPDF which are under GPL. */ #if FMT_EXTERNS_H @@ -31,6 +33,8 @@ john_register_one(&fmt_pdf); #include "rc4.h" #include "pdfcrack_md5.h" #include "loader.h" +#include "options.h" +#include "logger.h" #define FORMAT_LABEL "PDF" #define FORMAT_NAME "" @@ -76,6 +80,10 @@ static struct custom_salt { int length_oe; } *crypt_out; +#define MAX_KEY_SIZE 256 +#define MAX_U_SIZE sizeof(crypt_out->u) +#define MAX_O_SIZE sizeof(crypt_out->o) + static struct fmt_tests pdf_tests[] = { {"$pdf$4*4*128*-1028*1*16*e03460febe17a048b0adc7f7631bcc56*32*3456205208ad52066d5604018d498a6400000000000000000000000000000000*32*6d598152b22f8fa8085b19a866dce1317f645788a065a74831588a739a579ac4", "openwall"}, {"$pdf$2*3*128*-4*1*16*34b1b6e593787af681a9b63fa8bf563b*32*289ece9b5ce451a5d7064693dab3badf101112131415161718191a1b1c1d1e1f*32*badad1e86442699427116d3e5d5271bc80a27814fc5e80f815efeef839354c5f", "test"}, @@ -140,7 +148,7 @@ static int valid(char *ciphertext, struct fmt_main *self) goto err; if (!isdec(p)) goto err; res = atoi(p); - if (res > 256) + if (res > MAX_KEY_SIZE) goto err; if ((p = strtokm(NULL, "*")) == NULL) /* P */ goto err; @@ -165,7 +173,7 @@ static int valid(char *ciphertext, struct fmt_main *self) goto err; if (!isdec(p)) goto err; res = atoi(p); - if (res > 127) + if (res > MAX_U_SIZE) goto err; if ((p = strtokm(NULL, "*")) == NULL) /* u */ goto err; @@ -177,7 +185,7 @@ static int valid(char *ciphertext, struct fmt_main *self) goto err; if (!isdec(p)) goto err; res = atoi(p); - if (res > 127) + if (res > MAX_O_SIZE) goto err; if ((p = strtokm(NULL, "*")) == NULL) /* o */ goto err; @@ -257,7 +265,7 @@ static int old_valid(char *ciphertext, struct fmt_main *self) return 0; } -char * convert_old_to_new(char ciphertext[]) +char* convert_old_to_new(char ciphertext[]) { char *ctcopy = xstrdup(ciphertext); char *keeptr = ctcopy; @@ -425,13 +433,20 @@ pdf_compute_encryption_key(unsigned char *password, int pwlen, unsigned char *ke /* Step 8 (revision 3 or greater) - do some voodoo 50 times */ if (crypt_out->R >= 3) { - /* for (i = 0; i < 50; i++) - { - MD5_Init(&md5); - MD5_Update(&md5, buf, n); - MD5_Final(buf, &md5); - } */ - md5_50(buf); + switch(crypt_out->length) { + case 128: + md5x50_128(buf); + break; + case 40: + md5x50_40(buf); + break; + default: + for (int i = 0; i < 50; i++) { + MD5_Init(&md5); + MD5_Update(&md5, buf, n); + MD5_Final(buf, &md5); + } + } } /* Step 9 - the key is the first 'n' bytes of the result */ memcpy(key, buf, n); @@ -548,26 +563,24 @@ pdf_compute_hardened_hash_r6(unsigned char *password, int pwlen, unsigned char s static void pdf_compute_user_password(unsigned char *password, unsigned char *output) { - int pwlen = strlen((char*)password); - unsigned char key[128]; + unsigned char key[MAX_KEY_SIZE / 8]; + int n = crypt_out->length / 8; if (crypt_out->R == 2) { RC4_KEY arc4; - int n; - n = crypt_out->length / 8; + pdf_compute_encryption_key(password, pwlen, key); RC4_set_key(&arc4, n, key); RC4(&arc4, 32, padding, output); } - - if (crypt_out->R == 3 || crypt_out->R == 4) { + else if (crypt_out->R == 3 || crypt_out->R == 4) { unsigned char xor[32]; unsigned char digest[16]; MD5_CTX md5; RC4_KEY arc4; - int i, x, n; - n = crypt_out->length / 8; + int i, x; + pdf_compute_encryption_key(password, pwlen, key); MD5_Init(&md5); MD5_Update(&md5, (char*)padding, 32); @@ -581,7 +594,7 @@ static void pdf_compute_user_password(unsigned char *password, unsigned char *o RC4_set_key(&arc4, n, xor); RC4(&arc4, 16, output, output); } - memcpy(output + 16, padding, 16); + //memcpy(output + 16, padding, 16); /* pointless - we only test 16 bytes of it */ } if (crypt_out->R == 5) { pdf_compute_encryption_key_r5(password, pwlen, 0, output); @@ -590,6 +603,20 @@ static void pdf_compute_user_password(unsigned char *password, unsigned char *o /* SumatraPDF: support crypt version 5 revision 6 */ if (crypt_out->R == 6) pdf_compute_hardened_hash_r6(password, pwlen, crypt_out->u + 32, NULL, output); + + if (!bench_or_test_running && crypt_out->length == 40 && !memcmp(output, crypt_out->u, 16)) { + char h_key[2 * 5 + 1], *p; + int i; + + p = &h_key[0]; + for (i = 0; i < 2 * n; i++) + *p++ = itoa16[key[i >> 1] >> (4 * ((i & 0x1) ^ 1)) & 0xf]; + *p = 0; + + log_event("+ RC4 key: %s", h_key); + if (options.verbosity > VERB_DEFAULT) + fprintf(stderr, "+ RC4 key: %s\n", h_key); + } } static int crypt_all(int *pcount, struct db_salt *salt) diff --git a/src/pdfcrack_md5.h b/src/pdfcrack_md5.h index 36fa2af2a8..a005b5bf31 100644 --- a/src/pdfcrack_md5.h +++ b/src/pdfcrack_md5.h @@ -22,8 +22,8 @@ #include -void md5(const uint8_t * msg, const unsigned int msgLen, uint8_t * digest); -void md5_50(uint8_t * msg); +extern void md5x50_40(uint8_t * msg); +extern void md5x50_128(uint8_t * msg); #endif /** _MD5_H_ */ diff --git a/src/pdfcrack_md5_plug.c b/src/pdfcrack_md5_plug.c index f466cfe460..0188f03c4b 100644 --- a/src/pdfcrack_md5_plug.c +++ b/src/pdfcrack_md5_plug.c @@ -47,8 +47,120 @@ #define CC 0x98badcfe #define DD 0x10325476 -/** fast version of "for (i=0; i<50; i++) { md5(msg, 16, msg); }" */ -void md5_50(uint8_t * msg) +/** fast versions of "for (i=0; i<50; i++) { md5(msg, n, msg); }" */ +void md5x50_40(uint8_t* msg) +{ + register uint32_t a, b, c, d; + int i; + + a = ((unsigned int)(((unsigned int)(((unsigned int)msg[3] << 8) + msg[2]) << 8) + msg[1]) << 8) + msg[0]; + b = 0x8000 + (unsigned int)msg[4]; + c = 0; + d = 0; + + for (i = 0; i < 50; ++i) { + uint32_t aa, bb, cc, dd; + + dd = d; + cc = c; + bb = b; + aa = a; + + /** round 1 */ + /**MD5_ROUND1(a,BB,CC,DD, aa, 7, 0xd76aa478); + MD5_ROUND1(d, a,BB,CC, bb,12, 0xe8c7b756); + MD5_ROUND1(c, d, a,BB, cc,17, 0x242070db); + MD5_ROUND1(b, c, d, a, dd,22, 0xc1bdceee);*/ + a += 0xd76aa477; + RnA(a, BB, 7); + d = 0xf8fa0bcc + b + (CC ^ (a & 0x77777777)); + RnA(d, a, 12); + c += 0xbcdb4dd9 + (BB ^ (d & (a ^ BB))); + RnA(c, d, 17); + b = 0xb18b7a77 + dd + (a ^ (c & (d ^ a))); + RnA(b, c, 22); + MD5_ROUND1(a, b, c, d, 0, 7, 0xf57c0faf); + MD5_ROUND1(d, a, b, c, 0, 12, 0x4787c62a); + MD5_ROUND1(c, d, a, b, 0, 17, 0xa8304613); + MD5_ROUND1(b, c, d, a, 0, 22, 0xfd469501); + MD5_ROUND1(a, b, c, d, 0, 7, 0x698098d8); + MD5_ROUND1(d, a, b, c, 0, 12, 0x8b44f7af); + MD5_ROUND1(c, d, a, b, 0, 17, 0xffff5bb1); + MD5_ROUND1(b, c, d, a, 0, 22, 0x895cd7be); + MD5_ROUND1(a, b, c, d, 0, 7, 0x6b901122); + MD5_ROUND1(d, a, b, c, 0, 12, 0xfd987193); + MD5_ROUND1(c, d, a, b, 40, 17, 0xa679438e); + MD5_ROUND1(b, c, d, a, 0, 22, 0x49b40821); + + /** round 2 */ + MD5_ROUND2(a, b, c, d, bb, 5, 0xf61e2562); + MD5_ROUND2(d, a, b, c, 0, 9, 0xc040b340); + MD5_ROUND2(c, d, a, b, 0, 14, 0x265e5a51); + MD5_ROUND2(b, c, d, a, aa, 20, 0xe9b6c7aa); + MD5_ROUND2(a, b, c, d, 0, 5, 0xd62f105d); + MD5_ROUND2(d, a, b, c, 0, 9, 0x02441453); + MD5_ROUND2(c, d, a, b, 0, 14, 0xd8a1e681); + MD5_ROUND2(b, c, d, a, 0, 20, 0xe7d3fbc8); + MD5_ROUND2(a, b, c, d, 0, 5, 0x21e1cde6); + MD5_ROUND2(d, a, b, c, 40, 9, 0xc33707d6); + MD5_ROUND2(c, d, a, b, dd, 14, 0xf4d50d87); + MD5_ROUND2(b, c, d, a, 0, 20, 0x455a14ed); + MD5_ROUND2(a, b, c, d, 0, 5, 0xa9e3e905); + MD5_ROUND2(d, a, b, c, cc, 9, 0xfcefa3f8); + MD5_ROUND2(c, d, a, b, 0, 14, 0x676f02d9); + MD5_ROUND2(b, c, d, a, 0, 20, 0x8d2a4c8a); + + /** round 3 */ + MD5_ROUND3(a, b, c, d, 0, 4, 0xfffa3942); + MD5_ROUND3(d, a, b, c, 0, 11, 0x8771f681); + MD5_ROUND3(c, d, a, b, 0, 16, 0x6d9d6122); + MD5_ROUND3(b, c, d, a, 40, 23, 0xfde5380c); + MD5_ROUND3(a, b, c, d, bb, 4, 0xa4beea44); + MD5_ROUND3(d, a, b, c, 0, 11, 0x4bdecfa9); + MD5_ROUND3(c, d, a, b, 0, 16, 0xf6bb4b60); + MD5_ROUND3(b, c, d, a, 0, 23, 0xbebfbc70); + MD5_ROUND3(a, b, c, d, 0, 4, 0x289b7ec6); + MD5_ROUND3(d, a, b, c, aa, 11, 0xeaa127fa); + MD5_ROUND3(c, d, a, b, dd, 16, 0xd4ef3085); + MD5_ROUND3(b, c, d, a, 0, 23, 0x04881d05); + MD5_ROUND3(a, b, c, d, 0, 4, 0xd9d4d039); + MD5_ROUND3(d, a, b, c, 0, 11, 0xe6db99e5); + MD5_ROUND3(c, d, a, b, 0, 16, 0x1fa27cf8); + MD5_ROUND3(b, c, d, a, cc, 23, 0xc4ac5665); + + /** round 4 */ + MD5_ROUND4(a, b, c, d, aa, 6, 0xf4292244); + MD5_ROUND4(d, a, b, c, 0, 10, 0x432aff97); + MD5_ROUND4(c, d, a, b, 40, 15, 0xab9423a7); + MD5_ROUND4(b, c, d, a, 0, 21, 0xfc93a039); + MD5_ROUND4(a, b, c, d, 0, 6, 0x655b59c3); + MD5_ROUND4(d, a, b, c, dd, 10, 0x8f0ccc92); + MD5_ROUND4(c, d, a, b, 0, 15, 0xffeff47d); + MD5_ROUND4(b, c, d, a, bb, 21, 0x85845dd1); + MD5_ROUND4(a, b, c, d, 0, 6, 0x6fa87e4f); + MD5_ROUND4(d, a, b, c, 0, 10, 0xfe2ce6e0); + MD5_ROUND4(c, d, a, b, 0, 15, 0xa3014314); + MD5_ROUND4(b, c, d, a, 0, 21, 0x4e0811a1); + MD5_ROUND4(a, b, c, d, 0, 6, 0xf7537e82); + MD5_ROUND4(d, a, b, c, 0, 10, 0xbd3af235); + MD5_ROUND4(c, d, a, b, cc, 15, 0x2ad7d2bb); + MD5_ROUND4(b, c, d, a, 0, 21, 0xeb86d391); + + a += AA; + b = ((b + BB) & 0xff) + 0x8000; + c = 0; + d = 0; + } + + /** break digest into bytes */ + msg[0] = (uint8_t) (a & 0xff); + msg[1] = (uint8_t) ((a >>= 8) & 0xff); + msg[2] = (uint8_t) ((a >>= 8) & 0xff); + msg[3] = (uint8_t) ((a >>= 8) & 0xff); + msg[4] = (uint8_t) (b & 0xff); +} + +void md5x50_128(uint8_t* msg) { register uint32_t a, b, c, d; int i; @@ -89,7 +201,7 @@ void md5_50(uint8_t * msg) MD5_ROUND1(b, c, d, a, 0, 22, 0x895cd7be); MD5_ROUND1(a, b, c, d, 0, 7, 0x6b901122); MD5_ROUND1(d, a, b, c, 0, 12, 0xfd987193); - MD5_ROUND1(c, d, a, b, 0x80, 17, 0xa679438e); + MD5_ROUND1(c, d, a, b, 128, 17, 0xa679438e); MD5_ROUND1(b, c, d, a, 0, 22, 0x49b40821); /** round 2 */ @@ -102,7 +214,7 @@ void md5_50(uint8_t * msg) MD5_ROUND2(c, d, a, b, 0, 14, 0xd8a1e681); MD5_ROUND2(b, c, d, a, 0x80, 20, 0xe7d3fbc8); MD5_ROUND2(a, b, c, d, 0, 5, 0x21e1cde6); - MD5_ROUND2(d, a, b, c, 0x80, 9, 0xc33707d6); + MD5_ROUND2(d, a, b, c, 128, 9, 0xc33707d6); MD5_ROUND2(c, d, a, b, dd, 14, 0xf4d50d87); MD5_ROUND2(b, c, d, a, 0, 20, 0x455a14ed); MD5_ROUND2(a, b, c, d, 0, 5, 0xa9e3e905); @@ -114,7 +226,7 @@ void md5_50(uint8_t * msg) MD5_ROUND3(a, b, c, d, 0, 4, 0xfffa3942); MD5_ROUND3(d, a, b, c, 0, 11, 0x8771f681); MD5_ROUND3(c, d, a, b, 0, 16, 0x6d9d6122); - MD5_ROUND3(b, c, d, a, 0x80, 23, 0xfde5380c); + MD5_ROUND3(b, c, d, a, 128, 23, 0xfde5380c); MD5_ROUND3(a, b, c, d, bb, 4, 0xa4beea44); MD5_ROUND3(d, a, b, c, 0x80, 11, 0x4bdecfa9); MD5_ROUND3(c, d, a, b, 0, 16, 0xf6bb4b60); @@ -131,7 +243,7 @@ void md5_50(uint8_t * msg) /** round 4 */ MD5_ROUND4(a, b, c, d, aa, 6, 0xf4292244); MD5_ROUND4(d, a, b, c, 0, 10, 0x432aff97); - MD5_ROUND4(c, d, a, b, 0x80, 15, 0xab9423a7); + MD5_ROUND4(c, d, a, b, 128, 15, 0xab9423a7); MD5_ROUND4(b, c, d, a, 0, 21, 0xfc93a039); MD5_ROUND4(a, b, c, d, 0, 6, 0x655b59c3); MD5_ROUND4(d, a, b, c, dd, 10, 0x8f0ccc92);