Openwall GNU/*/Linux - a small security-enhanced Linux distro for servers
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date: Wed, 7 Feb 2007 13:02:23 -0800
From: "Alain Espinosa" <alainesp@...il.com>
To: john-users@...ts.openwall.com
Subject: Re: New NT patch

Revision #4

- This revision (I thinks) works for little-endian and big-endian
architecture. Please someone that have a computer based on big-endian
architecture test it. I test with little-endian.
- little improve: now benchmark 7100K

alain

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 <alainesp@...il.com> in 2007
+ * and placed in the public domain.
+ */
+
+#include <string.h>
+#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)

-- 
To unsubscribe, e-mail john-users-unsubscribe@...ts.openwall.com and reply
to the automated confirmation request that will be sent to you.

Powered by blists - more mailing lists

Your e-mail address:

Powered by Openwall GNU/*/Linux - Powered by OpenVZ