diff -ruN john-1.7.2/src/NT_fmt.c john-1.7.2_ntlm/src/NT_fmt.c --- john-1.7.2/src/NT_fmt.c 1970-01-01 01:00:00.000000000 +0100 +++ john-1.7.2_ntlm/src/NT_fmt.c 2007-02-07 14:37:59.000000000 +0100 @@ -0,0 +1,337 @@ +/* NTLM patch for john (performance improvement) + * + * Written by Alain Espinosa in 2007 + * and placed in the public domain. + */ + +#include +#include "arch.h" +#include "memory.h" +#include "common.h" +#include "formats.h" + +#ifndef uchar +#define uchar unsigned char +#endif + +#define FORMAT_LABEL "nt" +#define FORMAT_NAME "NT MD4" + +#define BENCHMARK_COMMENT "" +#define BENCHMARK_LENGTH -1 + +#define PLAINTEXT_LENGTH 27 +#define CIPHERTEXT_LENGTH 36 + + +static struct fmt_tests tests[] = { + {"$NT$b7e4b9022cd45f275334bbdb83bb5be5", "John the Ripper"}, + {"$NT$8846f7eaee8fb117ad06bdd830b7586c", "password"}, + {"$NT$0cb6948805f797bf2a82807973b89537", "test"}, + {"$NT$31d6cfe0d16ae931b73c59d7e0c089c0", ""}, + {NULL} +}; + +#define ALGORITHM_NAME "Rapid NT MD4" + +#define BINARY_SIZE 16 +#define SALT_SIZE 0 + +#define MIN_KEYS_PER_CRYPT 1 +#define MAX_KEYS_PER_CRYPT 1 + +char saved_plain[PLAINTEXT_LENGTH+1]; + +unsigned int a; +unsigned int b; +unsigned int c; +unsigned int d; + +unsigned int md4_buffer[16]; +int last_i; + +//Init values +#define INIT_A 0x67452301 +#define INIT_B 0xefcdab89 +#define INIT_C 0x98badcfe +#define INIT_D 0x10325476 + +#define SQRT_2 0x5a827999 +#define SQRT_3 0x6ed9eba1 + +static void fmt_NT_init(void) +{ + memset(md4_buffer,0,16*4); + last_i=0; +} + +static int valid(char *ciphertext) +{ + char *pos; + + if (strncmp(ciphertext, "$NT$", 4)!=0) return 0; + + for (pos = &ciphertext[4]; atoi16[ARCH_INDEX(*pos)] != 0x7F; pos++); + + if (!*pos && pos - ciphertext == CIPHERTEXT_LENGTH) + return 1; + else + return 0; + +} + +static void *get_binary(char *ciphertext) +{ + static unsigned int out[4]; + int i=0; + unsigned int temp; + + ciphertext+=4; + for (; i<4; i++) + { + temp = (atoi16[ARCH_INDEX(ciphertext[i*8+0])])<<4; + temp |= (atoi16[ARCH_INDEX(ciphertext[i*8+1])]); + + temp |= (atoi16[ARCH_INDEX(ciphertext[i*8+2])])<<12; + temp |= (atoi16[ARCH_INDEX(ciphertext[i*8+3])])<<8; + + temp |= (atoi16[ARCH_INDEX(ciphertext[i*8+4])])<<20; + temp |= (atoi16[ARCH_INDEX(ciphertext[i*8+5])])<<16; + + temp |= (atoi16[ARCH_INDEX(ciphertext[i*8+6])])<<28; + temp |= (atoi16[ARCH_INDEX(ciphertext[i*8+7])])<<24; + + out[i]=temp; + } + + out[0] -= INIT_A; + out[1] -= INIT_B; + out[2] -= INIT_C; + out[3] -= INIT_D; + + out[1] = (out[1] >> 15) | (out[1] << 17); + out[1] -= SQRT_3 + (out[2] ^ out[3] ^ out[0]); + out[1] = (out[1] >> 15) | (out[1] << 17); + out[1] -= SQRT_3; + + return out; +} + +static int binary_hash_0(void *binary) +{ + return ((unsigned int *)binary)[1] & 0x0F; +} + +static int binary_hash_1(void *binary) +{ + return ((unsigned int *)binary)[1] & 0xFF; +} + +static int binary_hash_2(void *binary) +{ + return ((unsigned int *)binary)[1] & 0x0FFF; +} + +static int get_hash_0(int index) +{ + return b & 0x0F; +} + +static int get_hash_1(int index) +{ + return b & 0xFF; +} + +static int get_hash_2(int index) +{ + return b & 0x0FFF; +} + +static void crypt_all(int count) +{ + /* Round 1 */ + a = 0xFFFFFFFF + md4_buffer[0];a = (a << 3 ) | (a >> 29); + d = INIT_D + (INIT_C ^ (a & 0x77777777)) + md4_buffer[1];d = (d << 7 ) | (d >> 25); + c = INIT_C + (INIT_B ^ (d & (a ^ INIT_B))) + md4_buffer[2];c = (c << 11) | (c >> 21); + b = INIT_B + (a ^ (c & (d ^ a))) + md4_buffer[3];b = (b << 19) | (b >> 13); + + a += (d ^ (b & (c ^ d))) + md4_buffer[4] ;a = (a << 3 ) | (a >> 29); + d += (c ^ (a & (b ^ c))) + md4_buffer[5] ;d = (d << 7 ) | (d >> 25); + c += (b ^ (d & (a ^ b))) + md4_buffer[6] ;c = (c << 11) | (c >> 21); + b += (a ^ (c & (d ^ a))) + md4_buffer[7] ;b = (b << 19) | (b >> 13); + + a += (d ^ (b & (c ^ d))) + md4_buffer[8] ;a = (a << 3 ) | (a >> 29); + d += (c ^ (a & (b ^ c))) + md4_buffer[9] ;d = (d << 7 ) | (d >> 25); + c += (b ^ (d & (a ^ b))) + md4_buffer[10] ;c = (c << 11) | (c >> 21); + b += (a ^ (c & (d ^ a))) + md4_buffer[11] ;b = (b << 19) | (b >> 13); + + a += (d ^ (b & (c ^ d))) + md4_buffer[12] ;a = (a << 3 ) | (a >> 29); + d += (c ^ (a & (b ^ c))) + md4_buffer[13] ;d = (d << 7 ) | (d >> 25); + c += (b ^ (d & (a ^ b))) + md4_buffer[14] ;c = (c << 11) | (c >> 21); + b += (a ^ (c & (d ^ a)))/*+ md4_buffer[15]*/;b = (b << 19) | (b >> 13); + + /* Round 2 */ + a += ((b & (c | d)) | (c & d)) + md4_buffer[0] + SQRT_2; a = (a << 3 ) | (a >> 29); + d += ((a & (b | c)) | (b & c)) + md4_buffer[4] + SQRT_2; d = (d << 5 ) | (d >> 27); + c += ((d & (a | b)) | (a & b)) + md4_buffer[8] + SQRT_2; c = (c << 9 ) | (c >> 23); + b += ((c & (d | a)) | (d & a)) + md4_buffer[12] + SQRT_2; b = (b << 13) | (b >> 19); + + a += ((b & (c | d)) | (c & d)) + md4_buffer[1] + SQRT_2; a = (a << 3 ) | (a >> 29); + d += ((a & (b | c)) | (b & c)) + md4_buffer[5] + SQRT_2; d = (d << 5 ) | (d >> 27); + c += ((d & (a | b)) | (a & b)) + md4_buffer[9] + SQRT_2; c = (c << 9 ) | (c >> 23); + b += ((c & (d | a)) | (d & a)) + md4_buffer[13] + SQRT_2; b = (b << 13) | (b >> 19); + + a += ((b & (c | d)) | (c & d)) + md4_buffer[2] + SQRT_2; a = (a << 3 ) | (a >> 29); + d += ((a & (b | c)) | (b & c)) + md4_buffer[6] + SQRT_2; d = (d << 5 ) | (d >> 27); + c += ((d & (a | b)) | (a & b)) + md4_buffer[10] + SQRT_2; c = (c << 9 ) | (c >> 23); + b += ((c & (d | a)) | (d & a)) + md4_buffer[14] + SQRT_2; b = (b << 13) | (b >> 19); + + a += ((b & (c | d)) | (c & d)) + md4_buffer[3] + SQRT_2; a = (a << 3 ) | (a >> 29); + d += ((a & (b | c)) | (b & c)) + md4_buffer[7] + SQRT_2; d = (d << 5 ) | (d >> 27); + c += ((d & (a | b)) | (a & b)) + md4_buffer[11] + SQRT_2; c = (c << 9 ) | (c >> 23); + b += ((c & (d | a)) | (d & a))/*+ md4_buffer[15]*/+ SQRT_2; b = (b << 13) | (b >> 19); + + /* Round 3 */ + a += (b ^ c ^ d) + md4_buffer[0] + SQRT_3; a = (a << 3 ) | (a >> 29); + d += (a ^ b ^ c) + md4_buffer[8] + SQRT_3; d = (d << 9 ) | (d >> 23); + c += (d ^ a ^ b) + md4_buffer[4] + SQRT_3; c = (c << 11) | (c >> 21); + b += (c ^ d ^ a) + md4_buffer[12] + SQRT_3; b = (b << 15) | (b >> 17); + + a += (b ^ c ^ d) + md4_buffer[2] + SQRT_3; a = (a << 3 ) | (a >> 29); + d += (a ^ b ^ c) + md4_buffer[10] + SQRT_3; d = (d << 9 ) | (d >> 23); + c += (d ^ a ^ b) + md4_buffer[6] + SQRT_3; c = (c << 11) | (c >> 21); + b += (c ^ d ^ a) + md4_buffer[14] + SQRT_3; b = (b << 15) | (b >> 17); + + a += (b ^ c ^ d) + md4_buffer[1] + SQRT_3; a = (a << 3 ) | (a >> 29); + d += (a ^ b ^ c) + md4_buffer[9] + SQRT_3; d = (d << 9 ) | (d >> 23); + c += (d ^ a ^ b) + md4_buffer[5] + SQRT_3; c = (c << 11) | (c >> 21); + b += (c ^ d ^ a) + md4_buffer[13];//+SQRT_3; b = (b << 15) | (b >> 17); + + //This save aproximately 8% of the work + + //Calculate in cmp_one a+= (b ^ c ^ d)+md4_buffer[3] +SQRT_3;a = (a << 3 ) | (a >> 29); + //Calculate in cmp_one d+= (a ^ b ^ c)+md4_buffer[11]+SQRT_3;d = (d << 9 ) | (d >> 23); + //Calculate in cmp_one c+= (d ^ a ^ b)+md4_buffer[7] +SQRT_3;c = (c << 11) | (c >> 21); + //Reversed in get_binary b+= (c ^ d ^ a)+md4_buffer[15]+SQRT_3;b = (b << 15) | (b >> 17); + +} + +static int cmp_all(void *binary, int count) +{ + return b==((unsigned int *)binary)[1]; +} + +static int cmp_one(void * binary, int index) +{ + unsigned int *t=(unsigned int *)binary; + + b += SQRT_3;b = (b << 15) | (b >> 17); + a += (b ^ c ^ d) + md4_buffer[3] + SQRT_3; a = (a << 3 ) | (a >> 29); + if(a!=t[0]) + return 0; + + d += (a ^ b ^ c) + md4_buffer[11]+ SQRT_3; d = (d << 9 ) | (d >> 23); + if(d!=t[3]) + return 0; + + c += (d ^ a ^ b) + md4_buffer[7] + SQRT_3; c = (c << 11) | (c >> 21); + return c==t[2]; +} + +static int cmp_exact(char *source, int index) +{ + return 1; +} + +static void set_salt(void *salt) +{ +} + +static void set_key(char *key, int index) +{ + int md4_size=0; + int i=0; + uchar temp; + + /*Password must be converted to NT unicode + and lesser than PLAINTEXT_LENGTH bytes*/ + for(;;md4_size++,i++) + if(key[md4_size] && md4_size < PLAINTEXT_LENGTH) + { + saved_plain[md4_size] = key[md4_size]; + temp=key[++md4_size]; + saved_plain[md4_size] = temp; + + if(temp) + { + md4_buffer[i] = key[md4_size-1] | (temp<<16); + } + else + { + md4_buffer[i] = key[md4_size-1] | 0x800000; + break; + } + } + else + { + saved_plain[md4_size]=0; + md4_buffer[i] = 0x80; + break; + } + //Cleaning + i++; + + for(;i<=last_i;i++) + md4_buffer[i]=0; + + last_i=md4_size>>1; + + md4_buffer[14] = md4_size << 4; +} + +static char *get_key(int index) +{ + return saved_plain; +} + +struct fmt_main fmt_NT = { + { + FORMAT_LABEL, + FORMAT_NAME, + ALGORITHM_NAME, + BENCHMARK_COMMENT, + BENCHMARK_LENGTH, + PLAINTEXT_LENGTH, + BINARY_SIZE, + SALT_SIZE, + MIN_KEYS_PER_CRYPT, + MAX_KEYS_PER_CRYPT, + FMT_CASE | FMT_8_BIT, + tests + }, { + fmt_NT_init, + valid, + fmt_default_split, + get_binary, + fmt_default_salt, + { + binary_hash_0, + binary_hash_1, + binary_hash_2 + }, + fmt_default_salt_hash, + set_salt, + set_key, + get_key, + fmt_default_clear_keys, + crypt_all, + { + get_hash_0, + get_hash_1, + get_hash_2 + }, + cmp_all, + cmp_one, + cmp_exact + } +}; diff -ruN john-1.7.2/src/john.c john-1.7.2_ntlm/src/john.c --- john-1.7.2/src/john.c 2006-05-08 16:48:48.000000000 +0200 +++ john-1.7.2_ntlm/src/john.c 2007-01-23 23:16:22.000000000 +0100 @@ -38,6 +38,7 @@ extern struct fmt_main fmt_DES, fmt_BSDI, fmt_MD5, fmt_BF; extern struct fmt_main fmt_AFS, fmt_LM; +extern struct fmt_main fmt_NT; extern int unshadow(int argc, char **argv); extern int unafs(int argc, char **argv); @@ -64,6 +65,8 @@ john_register_one(&fmt_BF); john_register_one(&fmt_AFS); john_register_one(&fmt_LM); + john_register_one(&fmt_NT); + if (!fmt_list) { fprintf(stderr, "Unknown ciphertext format name requested\n"); diff -ruN john-1.7.2/src/loader.c john-1.7.2_ntlm/src/loader.c --- john-1.7.2/src/loader.c 2005-11-08 14:03:20.000000000 +0100 +++ john-1.7.2_ntlm/src/loader.c 2007-01-23 23:59:10.000000000 +0100 @@ -18,6 +18,7 @@ #include "signals.h" #include "formats.h" #include "loader.h" +#include "options.h" /* * Flags for read_file(). @@ -183,7 +184,7 @@ static int ldr_split_line(char **login, char **ciphertext, char **gecos, char **home, char *source, struct fmt_main **format, - struct db_options *options, char *line) + struct db_options *db_options, char *line) { char *uid = NULL, *gid = NULL, *shell = NULL; char *tmp; @@ -205,11 +206,32 @@ if (!strncmp(*ciphertext, "NO PASSWORD", 11)) *ciphertext = ""; + + /* NT loader hack starts here ! */ + + if (options.format && (strncmp(options.format, "nt", 2)==0)) { + + tmp = ldr_get_field(&line); + *ciphertext = tmp; + + if (!strncmp(*ciphertext, "NO PASSWORD", 11)) + *ciphertext = ""; + else if(strlen(*ciphertext) == 32) { + *ciphertext -= 4; + strncpy(*ciphertext,"$NT$",4); + } + else { + return 0; + } + + } + + /* NT loader hack ends here ! */ if (source) sprintf(source, "%s:%s", uid, line); } - if (options->flags & DB_WORDS || options->shells->head) { + if (db_options->flags & DB_WORDS || db_options->shells->head) { gid = ldr_get_field(&line); do { *gecos = ldr_get_field(&line); @@ -218,13 +240,13 @@ } while (!**gecos && !strcmp(*home, "0") && !strcmp(shell, "0")); } else - if (options->groups->head) { + if (db_options->groups->head) { gid = ldr_get_field(&line); } - if (ldr_check_list(options->users, *login, uid)) return 0; - if (ldr_check_list(options->groups, gid, gid)) return 0; - if (ldr_check_shells(options->shells, shell)) return 0; + if (ldr_check_list(db_options->users, *login, uid)) return 0; + if (ldr_check_list(db_options->groups, gid, gid)) return 0; + if (ldr_check_shells(db_options->shells, shell)) return 0; if (*format) return (*format)->methods.valid(*ciphertext); diff -ruN john-1.7.2/src/options.c john-1.7.2_ntlm/src/options.c --- john-1.7.2/src/options.c 2006-01-09 15:35:00.000000000 +0100 +++ john-1.7.2_ntlm/src/options.c 2007-01-30 13:28:14.000000000 +0100 @@ -60,7 +60,7 @@ {"salts", FLG_SALTS, FLG_SALTS, FLG_PASSWD, OPT_REQ_PARAM, "%d", &options.loader.min_pps}, {"format", FLG_FORMAT, FLG_FORMAT, - FLG_CRACKING_SUP, + 0, FLG_MAKECHR_CHK | FLG_STDOUT | OPT_REQ_PARAM, OPT_FMT_STR_ALLOC, &options.format}, {"save-memory", FLG_SAVEMEM, FLG_SAVEMEM, 0, OPT_REQ_PARAM, @@ -101,7 +101,7 @@ "--salts=[-]COUNT load salts with[out] at least COUNT passwords " \ "only\n" \ "--format=NAME force ciphertext format NAME: " \ - "DES/BSDI/MD5/BF/AFS/LM\n" \ + "DES/BSDI/MD5/BF/AFS/LM/NT\n" \ "--save-memory=LEVEL enable memory saving, at LEVEL 1..3\n" void opt_init(char *name, int argc, char **argv)