diff -ruN john-1.7.2/src/Makefile john-1.7.2_nt/src/Makefile --- john-1.7.2/src/Makefile 2006-05-15 18:38:00.000000000 +0200 +++ john-1.7.2_nt/src/Makefile 2007-01-22 13:35:18.000000000 +0100 @@ -28,6 +28,7 @@ BF_fmt.o BF_std.o \ AFS_fmt.o \ LM_fmt.o \ + NT_fmt.o \ batch.o bench.o charset.o common.o compiler.o config.o cracker.o \ crc32.o external.o formats.o getopt.o idle.o inc.o john.o list.o \ loader.o logger.o math.o memory.o misc.o options.o params.o path.o \ diff -ruN john-1.7.2/src/NT_fmt.c john-1.7.2_nt/src/NT_fmt.c --- john-1.7.2/src/NT_fmt.c 1970-01-01 01:00:00.000000000 +0100 +++ john-1.7.2_nt/src/NT_fmt.c 2007-01-22 13:51:02.000000000 +0100 @@ -0,0 +1,313 @@ +/* + * NTLM patch for john (performance improve) + * + * Alain Espinosa + * + * license: GPL + * + * This patch asume 32 bits architecture and little endian memory organization + * + * This file is based on code from Solar Designer + */ + +#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 long a; +unsigned long b; +unsigned long c; +unsigned long d; + +unsigned long md4_buffer[16]; +int last_size; + +//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,64); + last_size=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 uchar binary[BINARY_SIZE]; + unsigned long *t=(unsigned long *)binary; + int i=0; + + ciphertext+=4; + for (; i> 15) | (t[1] << 17); + t[1] -= SQRT_3 + (t[2] ^ t[3] ^ t[0]); + t[1] = (t[1] >> 15) | (t[1] << 17); + t[1] -= SQRT_3; + + return binary; +} + +static int binary_hash_0(void *binary) +{ + return ((unsigned long *)binary)[1] & 0x0F; +} + +static int binary_hash_1(void *binary) +{ + return (((unsigned long *)binary)[1] >> 4) & 0x0F; +} + +static int binary_hash_2(void *binary) +{ + return (((unsigned long *)binary)[1] >> 8)& 0x0F; +} + +static int get_hash_0(int index) +{ + return b & 0x0F; +} + +static int get_hash_1(int index) +{ + return (b>>4) & 0x0F; +} + +static int get_hash_2(int index) +{ + return (b>>8) & 0x0F; +} + +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 long *)binary)[1]; +} + +static int cmp_one(void * binary, int index) +{ + unsigned long *t=(unsigned long *)binary; + + b += SQRT_3;b = (b << 15) | (b >> 17); + a += (b ^ c ^ d) + md4_buffer[3] + SQRT_3; a = (a << 3 ) | (a >> 29); + d += (a ^ b ^ c) + md4_buffer[11]+ SQRT_3; d = (d << 9 ) | (d >> 23); + c += (d ^ a ^ b) + md4_buffer[7] + SQRT_3; c = (c << 11) | (c >> 21); + + return (a==t[0] && c==t[2] && d==t[3]); +} + +static int cmp_exact(char *source, int index) +{ + return 1; +} + +static void set_salt(void *salt) +{ +} + +static void set_key(char *key, int index) +{ + uchar *buffer=(uchar*)md4_buffer; + int md4_size=0; + int clean; + + /* Password must be converted to NT unicode + and lesser than PLAINTEXT_LENGTH bytes*/ + for(;key[md4_size] && md4_size < PLAINTEXT_LENGTH;md4_size++) + { + buffer[md4_size<<1] =key[md4_size]; + saved_plain[md4_size]=key[md4_size]; + } + saved_plain[md4_size]=0; + + buffer[md4_size<<1] = 0x80; + + md4_buffer[14] = md4_size << 4; + + //Cleaning + clean=md4_size+1; + + for(;clean<=last_size;clean++) + buffer[clean<<1]=0; + + last_size=md4_size; +} + +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_nt/src/john.c --- john-1.7.2/src/john.c 2006-05-08 16:48:48.000000000 +0200 +++ john-1.7.2_nt/src/john.c 2007-01-22 13:36:06.000000000 +0100 @@ -37,7 +37,7 @@ #endif 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_AFS, fmt_LM, fmt_NT; extern int unshadow(int argc, char **argv); extern int unafs(int argc, char **argv); @@ -64,6 +64,7 @@ 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_nt/src/loader.c --- john-1.7.2/src/loader.c 2005-11-08 14:03:20.000000000 +0100 +++ john-1.7.2_nt/src/loader.c 2007-01-22 13:39:57.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);