diff -u -N ../clean-src/JOHN-NTLM-FAQ ./JOHN-NTLM-FAQ
--- ../clean-src/JOHN-NTLM-FAQ	Thu Jan  1 01:00:00 1970
+++ ./JOHN-NTLM-FAQ	Fri Sep 19 14:26:18 2003
@@ -0,0 +1,29 @@
+
+Q: What's this?
+A: It's a patch to Solar Designer's "john the ripper" password cracker.
+
+Q: What's it good for, then?
+A: It enables cracking of Windows NT/2000 MD4 (case-sensitive) password hashes.
+
+Q: Who made this?
+A: This patch was thrown together on a boring Sunday by Olle Segerdahl.
+   It uses Andrew Tridgell's NTLM and MD4 code stolen from samba-2.0.7 .
+
+Q: How do I install it?
+A: I assume you are able to install john from a source distribution,
+   if you are not, PLEASE read john's documentation before e-mailing me. 
+   To install run 'patch < john-ntlm-v02.diff' from the john "src" directory
+   and then run 'make (your-system-type-here)' to build john.
+
+Q: How do I use john to crack NT password hashes?
+A: Use pwdump2 or L0phtcrack to dump the password hashes into a file,
+   then run 'john pwfile -format:NT' to start cracking!
+
+Q: I get all kinds of compile errors!
+A: This patch was made against john-1.6.36, lots of stuff might have broken
+   source compatibility since then... Use something closer to john-1.6.36.
+
+Q: I have a question not covered by this FAQ!
+A: Make sure you have read all there is to read about john, then
+   mail me at olle@nxs.se with "JOHN-NTLM" in the subject.
+
diff -u -N ../clean-src/Makefile ./Makefile
--- ../clean-src/Makefile	Thu Sep 18 12:33:18 2003
+++ ./Makefile	Fri Sep 19 14:20:52 2003
@@ -27,6 +27,8 @@
 	BF_fmt.o BF_std.o \
 	AFS_fmt.o \
 	LM_fmt.o \
+	NT_fmt.o \
+	md4.o smbencrypt.o \
 	batch.o bench.o charset.o common.o compiler.o config.o cracker.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 recovery.o \
diff -u -N ../clean-src/NT_fmt.c ./NT_fmt.c
--- ../clean-src/NT_fmt.c	Thu Jan  1 01:00:00 1970
+++ ./NT_fmt.c	Fri Sep 19 14:28:35 2003
@@ -0,0 +1,187 @@
+/*
+ * NTLM patch for john version 0.3
+ *
+ * (C) 2001 Olle Segerdahl <olle@nxs.se>
+ *
+ * license: GPL <http://www.gnu.org/licenses/gpl.html>
+ *
+ * This file is based on code from John the Ripper,
+ * Copyright (c) 1996-99 by Solar Designer
+ *
+ */
+
+#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		54
+#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			"TridgeMD4"
+
+#define BINARY_SIZE			16
+#define SALT_SIZE			0
+
+#define MIN_KEYS_PER_CRYPT		1
+#define MAX_KEYS_PER_CRYPT		1
+
+uchar saved_plain[PLAINTEXT_LENGTH + 1];
+uchar output[BINARY_SIZE + 1];
+
+extern void E_md4hash(uchar *passwd, uchar *p16);
+
+
+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];
+	int i;
+
+	ciphertext+=4;
+	for (i=0; i<BINARY_SIZE; i++)
+	   {
+ 		binary[i] = (atoi16[ARCH_INDEX(ciphertext[i*2])])<<4;
+ 		binary[i] |= (atoi16[ARCH_INDEX(ciphertext[i*2+1])]);
+	   }
+
+	return binary;
+}
+
+static int binary_hash_0(void *binary)
+{
+	return ((uchar *)binary)[0] & 0x0F;
+}
+
+static int binary_hash_1(void *binary)
+{
+	return ((uchar *)binary)[0];
+}
+
+static int binary_hash_2(void *binary)
+{
+	return (((uchar *)binary)[0] << 4) + (((uchar *)binary)[1] & 0x0F);
+}
+
+static int get_hash_0(int index)
+{
+	return output[0] & 0x0F;
+}
+
+static int get_hash_1(int index)
+{
+	return output[0];
+}
+
+static int get_hash_2(int index)
+{
+	return (output[0] << 4) + (output[1] & 0x0F);
+}
+
+static void crypt_all(int count)
+{
+	E_md4hash(saved_plain, output);
+}
+
+static int cmp_all(void *binary, int count)
+{
+	return !memcmp(output, binary, BINARY_SIZE);
+
+}
+
+static int cmp_exact(char *source, int index)
+{
+	return !memcmp(output, get_binary(source), BINARY_SIZE);
+}
+
+static void set_salt(void *salt)
+{
+}
+
+static void set_key(char *key, int index)
+{
+	strncpy(saved_plain, key, PLAINTEXT_LENGTH);
+	saved_plain[PLAINTEXT_LENGTH] = 0;
+}
+
+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_default_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_all,
+		cmp_exact
+	}
+};
diff -u -N ../clean-src/byteorder.h ./byteorder.h
--- ../clean-src/byteorder.h	Thu Jan  1 01:00:00 1970
+++ ./byteorder.h	Thu Mar 20 03:59:23 2003
@@ -0,0 +1,274 @@
+/* 
+   Unix SMB/Netbios implementation.
+   Version 1.9.
+   SMB Byte handling
+   Copyright (C) Andrew Tridgell 1992-1998
+   
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef _BYTEORDER_H
+#define _BYTEORDER_H
+
+/*
+   This file implements macros for machine independent short and 
+   int manipulation
+
+Here is a description of this file that I emailed to the samba list once:
+
+> I am confused about the way that byteorder.h works in Samba. I have
+> looked at it, and I would have thought that you might make a distinction
+> between LE and BE machines, but you only seem to distinguish between 386
+> and all other architectures.
+> 
+> Can you give me a clue?
+
+sure.
+
+The distinction between 386 and other architectures is only there as
+an optimisation. You can take it out completely and it will make no
+difference. The routines (macros) in byteorder.h are totally byteorder
+independent. The 386 optimsation just takes advantage of the fact that
+the x86 processors don't care about alignment, so we don't have to
+align ints on int boundaries etc. If there are other processors out
+there that aren't alignment sensitive then you could also define
+CAREFUL_ALIGNMENT=0 on those processors as well.
+
+Ok, now to the macros themselves. I'll take a simple example, say we
+want to extract a 2 byte integer from a SMB packet and put it into a
+type called uint16 that is in the local machines byte order, and you
+want to do it with only the assumption that uint16 is _at_least_ 16
+bits long (this last condition is very important for architectures
+that don't have any int types that are 2 bytes long)
+
+You do this:
+
+#define CVAL(buf,pos) (((unsigned char *)(buf))[pos])
+#define PVAL(buf,pos) ((unsigned)CVAL(buf,pos))
+#define SVAL(buf,pos) (PVAL(buf,pos)|PVAL(buf,(pos)+1)<<8)
+
+then to extract a uint16 value at offset 25 in a buffer you do this:
+
+char *buffer = foo_bar();
+uint16 xx = SVAL(buffer,25);
+
+We are using the byteoder independence of the ANSI C bitshifts to do
+the work. A good optimising compiler should turn this into efficient
+code, especially if it happens to have the right byteorder :-)
+
+I know these macros can be made a bit tidier by removing some of the
+casts, but you need to look at byteorder.h as a whole to see the
+reasoning behind them. byteorder.h defines the following macros:
+
+SVAL(buf,pos) - extract a 2 byte SMB value
+IVAL(buf,pos) - extract a 4 byte SMB value
+SVALS(buf,pos) signed version of SVAL()
+IVALS(buf,pos) signed version of IVAL()
+
+SSVAL(buf,pos,val) - put a 2 byte SMB value into a buffer
+SIVAL(buf,pos,val) - put a 4 byte SMB value into a buffer
+SSVALS(buf,pos,val) - signed version of SSVAL()
+SIVALS(buf,pos,val) - signed version of SIVAL()
+
+RSVAL(buf,pos) - like SVAL() but for NMB byte ordering
+RSVALS(buf,pos) - like SVALS() but for NMB byte ordering
+RIVAL(buf,pos) - like IVAL() but for NMB byte ordering
+RIVALS(buf,pos) - like IVALS() but for NMB byte ordering
+RSSVAL(buf,pos,val) - like SSVAL() but for NMB ordering
+RSIVAL(buf,pos,val) - like SIVAL() but for NMB ordering
+RSIVALS(buf,pos,val) - like SIVALS() but for NMB ordering
+
+it also defines lots of intermediate macros, just ignore those :-)
+
+*/
+
+/* some switch macros that do both store and read to and from SMB buffers */
+
+#define RW_PCVAL(read,inbuf,outbuf,len) \
+	{ if (read) { PCVAL (inbuf,0,outbuf,len); } \
+	else      { PSCVAL(inbuf,0,outbuf,len); } }
+
+#define RW_PIVAL(read,big_endian,inbuf,outbuf,len) \
+	{ if (read) { if (big_endian) { RPIVAL(inbuf,0,outbuf,len); } else { PIVAL(inbuf,0,outbuf,len); } } \
+	else      { if (big_endian) { RPSIVAL(inbuf,0,outbuf,len); } else { PSIVAL(inbuf,0,outbuf,len); } } }
+
+#define RW_PSVAL(read,big_endian,inbuf,outbuf,len) \
+	{ if (read) { if (big_endian) { RPSVAL(inbuf,0,outbuf,len); } else { PSVAL(inbuf,0,outbuf,len); } } \
+	else      { if (big_endian) { RPSSVAL(inbuf,0,outbuf,len); } else { PSSVAL(inbuf,0,outbuf,len); } } }
+
+#define RW_CVAL(read, inbuf, outbuf, offset) \
+	{ if (read) { (outbuf) = CVAL (inbuf,offset); } \
+	else      { SCVAL(inbuf,offset,outbuf); } }
+
+#define RW_IVAL(read, big_endian, inbuf, outbuf, offset) \
+	{ if (read) { (outbuf) = ((big_endian) ? RIVAL(inbuf,offset) : IVAL (inbuf,offset)); } \
+	else      { if (big_endian) { RSIVAL(inbuf,offset,outbuf); } else { SIVAL(inbuf,offset,outbuf); } } }
+
+#define RW_SVAL(read, big_endian, inbuf, outbuf, offset) \
+	{ if (read) { (outbuf) = ((big_endian) ? RSVAL(inbuf,offset) : SVAL (inbuf,offset)); } \
+	else      { if (big_endian) { RSSVAL(inbuf,offset,outbuf); } else { SSVAL(inbuf,offset,outbuf); } } }
+
+#undef CAREFUL_ALIGNMENT
+
+/* we know that the 386 can handle misalignment and has the "right" 
+   byteorder */
+#ifdef __i386__
+#define CAREFUL_ALIGNMENT 0
+#endif
+
+#ifndef CAREFUL_ALIGNMENT
+#define CAREFUL_ALIGNMENT 1
+#endif
+
+#define CVAL(buf,pos) (((unsigned char *)(buf))[pos])
+#define PVAL(buf,pos) ((unsigned)CVAL(buf,pos))
+#define SCVAL(buf,pos,val) (CVAL(buf,pos) = (val))
+
+
+#if CAREFUL_ALIGNMENT
+
+#define SVAL(buf,pos) (PVAL(buf,pos)|PVAL(buf,(pos)+1)<<8)
+#define IVAL(buf,pos) (SVAL(buf,pos)|SVAL(buf,(pos)+2)<<16)
+#define SSVALX(buf,pos,val) (CVAL(buf,pos)=(val)&0xFF,CVAL(buf,pos+1)=(val)>>8)
+#define SIVALX(buf,pos,val) (SSVALX(buf,pos,val&0xFFFF),SSVALX(buf,pos+2,val>>16))
+#define SVALS(buf,pos) ((int16)SVAL(buf,pos))
+#define IVALS(buf,pos) ((int32)IVAL(buf,pos))
+#define SSVAL(buf,pos,val) SSVALX((buf),(pos),((uint16)(val)))
+#define SIVAL(buf,pos,val) SIVALX((buf),(pos),((uint32)(val)))
+#define SSVALS(buf,pos,val) SSVALX((buf),(pos),((int16)(val)))
+#define SIVALS(buf,pos,val) SIVALX((buf),(pos),((int32)(val)))
+
+#else /* CAREFUL_ALIGNMENT */
+
+/* this handles things for architectures like the 386 that can handle
+   alignment errors */
+/*
+   WARNING: This section is dependent on the length of int16 and int32
+   being correct 
+*/
+
+/* get single value from an SMB buffer */
+#define SVAL(buf,pos) (*(const uint16 *)((const char *)(buf) + (pos)))
+#define IVAL(buf,pos) (*(const uint32 *)((const char *)(buf) + (pos)))
+#define SVALS(buf,pos) (*(const int16 *)((const char *)(buf) + (pos)))
+#define IVALS(buf,pos) (*(const int32 *)((const char *)(buf) + (pos)))
+
+/* store single value in an SMB buffer */
+#define SVALMOD(buf,pos) (*(uint16 *)((char *)(buf) + (pos)))
+#define IVALMOD(buf,pos) (*(uint32 *)((char *)(buf) + (pos)))
+#define SVALSMOD(buf,pos) (*(int16 *)((char *)(buf) + (pos)))
+#define IVALSMOD(buf,pos) (*(int32 *)((char *)(buf) + (pos)))
+
+#define SSVAL(buf,pos,val) SVALMOD(buf,pos)=((uint16)(val))
+#define SIVAL(buf,pos,val) IVALMOD(buf,pos)=((uint32)(val))
+#define SSVALS(buf,pos,val) SVALSMOD(buf,pos)=((int16)(val))
+#define SIVALS(buf,pos,val) IVALSMOD(buf,pos)=((int32)(val))
+
+#endif /* CAREFUL_ALIGNMENT */
+
+/* macros for reading / writing arrays */
+
+#define SMBMACRO(macro,buf,pos,val,len,size) \
+{ uint32 l; for (l = 0; l < (uint32)(len); l++) (val)[l] = macro((buf), (pos) + (size)*l); }
+
+#define SSMBMACRO(macro,buf,pos,val,len,size) \
+{ uint32 l; for (l = 0; l < (uint32)(len); l++) macro((buf), (pos) + (size)*l, (val)[l]); }
+
+/* reads multiple data from an SMB buffer */
+#define PCVAL(buf,pos,val,len) SMBMACRO(CVAL,buf,pos,val,len,1)
+#define PSVAL(buf,pos,val,len) SMBMACRO(SVAL,buf,pos,val,len,2)
+#define PIVAL(buf,pos,val,len) SMBMACRO(IVAL,buf,pos,val,len,4)
+#define PCVALS(buf,pos,val,len) SMBMACRO(CVALS,buf,pos,val,len,1)
+#define PSVALS(buf,pos,val,len) SMBMACRO(SVALS,buf,pos,val,len,2)
+#define PIVALS(buf,pos,val,len) SMBMACRO(IVALS,buf,pos,val,len,4)
+
+/* stores multiple data in an SMB buffer */
+#define PSCVAL(buf,pos,val,len) SSMBMACRO(SCVAL,buf,pos,val,len,1)
+#define PSSVAL(buf,pos,val,len) SSMBMACRO(SSVAL,buf,pos,val,len,2)
+#define PSIVAL(buf,pos,val,len) SSMBMACRO(SIVAL,buf,pos,val,len,4)
+#define PSCVALS(buf,pos,val,len) SSMBMACRO(SCVALS,buf,pos,val,len,1)
+#define PSSVALS(buf,pos,val,len) SSMBMACRO(SSVALS,buf,pos,val,len,2)
+#define PSIVALS(buf,pos,val,len) SSMBMACRO(SIVALS,buf,pos,val,len,4)
+
+
+/* now the reverse routines - these are used in nmb packets (mostly) */
+#define SREV(x) ((((x)&0xFF)<<8) | (((x)>>8)&0xFF))
+#define IREV(x) ((SREV(x)<<16) | (SREV((x)>>16)))
+
+#define RSVAL(buf,pos) SREV(SVAL(buf,pos))
+#define RSVALS(buf,pos) SREV(SVALS(buf,pos))
+#define RIVAL(buf,pos) IREV(IVAL(buf,pos))
+#define RIVALS(buf,pos) IREV(IVALS(buf,pos))
+#define RSSVAL(buf,pos,val) SSVAL(buf,pos,SREV(val))
+#define RSSVALS(buf,pos,val) SSVALS(buf,pos,SREV(val))
+#define RSIVAL(buf,pos,val) SIVAL(buf,pos,IREV(val))
+#define RSIVALS(buf,pos,val) SIVALS(buf,pos,IREV(val))
+
+/* reads multiple data from an SMB buffer (big-endian) */
+#define RPSVAL(buf,pos,val,len) SMBMACRO(RSVAL,buf,pos,val,len,2)
+#define RPIVAL(buf,pos,val,len) SMBMACRO(RIVAL,buf,pos,val,len,4)
+#define RPSVALS(buf,pos,val,len) SMBMACRO(RSVALS,buf,pos,val,len,2)
+#define RPIVALS(buf,pos,val,len) SMBMACRO(RIVALS,buf,pos,val,len,4)
+
+/* stores multiple data in an SMB buffer (big-endian) */
+#define RPSSVAL(buf,pos,val,len) SSMBMACRO(RSSVAL,buf,pos,val,len,2)
+#define RPSIVAL(buf,pos,val,len) SSMBMACRO(RSIVAL,buf,pos,val,len,4)
+#define RPSSVALS(buf,pos,val,len) SSMBMACRO(RSSVALS,buf,pos,val,len,2)
+#define RPSIVALS(buf,pos,val,len) SSMBMACRO(RSIVALS,buf,pos,val,len,4)
+
+#define DBG_RW_PCVAL(charmode,string,depth,base,read,inbuf,outbuf,len) \
+	{ RW_PCVAL(read,inbuf,outbuf,len) \
+	DEBUG(5,("%s%04x %s: ", \
+             tab_depth(depth), base,string)); \
+    if (charmode) print_asc(5, (unsigned char*)(outbuf), (len)); else \
+	{ uint32 idx; for (idx = 0; idx < len; idx++) { DEBUG(5,("%02x ", (outbuf)[idx])); } } \
+	DEBUG(5,("\n")); } 
+
+#define DBG_RW_PSVAL(charmode,string,depth,base,read,big_endian,inbuf,outbuf,len) \
+	{ RW_PSVAL(read,big_endian,inbuf,outbuf,len) \
+	DEBUG(5,("%s%04x %s: ", \
+             tab_depth(depth), base,string)); \
+    if (charmode) print_asc(5, (unsigned char*)(outbuf), 2*(len)); else \
+	{ uint32 idx; for (idx = 0; idx < len; idx++) { DEBUG(5,("%04x ", (outbuf)[idx])); } } \
+	DEBUG(5,("\n")); }
+
+#define DBG_RW_PIVAL(charmode,string,depth,base,read,big_endian,inbuf,outbuf,len) \
+	{ RW_PIVAL(read,big_endian,inbuf,outbuf,len) \
+	DEBUG(5,("%s%04x %s: ", \
+             tab_depth(depth), base,string)); \
+    if (charmode) print_asc(5, (unsigned char*)(outbuf), 4*(len)); else \
+	{ uint32 idx; for (idx = 0; idx < len; idx++) { DEBUG(5,("%08x ", (outbuf)[idx])); } } \
+	DEBUG(5,("\n")); }
+
+#define DBG_RW_CVAL(string,depth,base,read,inbuf,outbuf) \
+	{ RW_CVAL(read,inbuf,outbuf,0) \
+	DEBUG(5,("%s%04x %s: %02x\n", \
+             tab_depth(depth), base, string, outbuf)); }
+
+#define DBG_RW_SVAL(string,depth,base,read,big_endian,inbuf,outbuf) \
+	{ RW_SVAL(read,big_endian,inbuf,outbuf,0) \
+	DEBUG(5,("%s%04x %s: %04x\n", \
+             tab_depth(depth), base, string, outbuf)); }
+
+#define DBG_RW_IVAL(string,depth,base,read,big_endian,inbuf,outbuf) \
+	{ RW_IVAL(read,big_endian,inbuf,outbuf,0) \
+	DEBUG(5,("%s%04x %s: %08x\n", \
+             tab_depth(depth), base, string, outbuf)); }
+
+/* Alignment macros. */
+#define ALIGN4(p,base) ((p) + ((4 - (PTR_DIFF((p), (base)) & 3)) & 3))
+#define ALIGN2(p,base) ((p) + ((2 - (PTR_DIFF((p), (base)) & 1)) & 1))
+
+#endif /* _BYTEORDER_H */
Common subdirectories: ../clean-src/john-ntlm and ./john-ntlm
diff -u -N ../clean-src/john.c ./john.c
--- ../clean-src/john.c	Mon Sep 15 10:17:17 2003
+++ ./john.c	Fri Sep 19 14:20:52 2003
@@ -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 -u -N ../clean-src/loader.c ./loader.c
--- ../clean-src/loader.c	Thu Aug 21 05:31:17 2003
+++ ./loader.c	Fri Sep 19 14:20:52 2003
@@ -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;
@@ -206,10 +207,27 @@
 		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 {
+                                *ciphertext -= 4;
+                                strncpy(*ciphertext,"$NT$",4);
+                        }
+                }
+
+                /* 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 +236,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 -u -N ../clean-src/md4.c ./md4.c
--- ../clean-src/md4.c	Thu Jan  1 01:00:00 1970
+++ ./md4.c	Thu Mar 20 03:59:23 2003
@@ -0,0 +1,187 @@
+/* 
+   Unix SMB/Netbios implementation.
+   Version 1.9.
+   a implementation of MD4 designed for use in the SMB authentication protocol
+   Copyright (C) Andrew Tridgell 1997-1998.
+   
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <sys/types.h>
+
+
+#ifndef uchar
+#define uchar unsigned char
+#endif
+
+#if !defined(uint16) && !defined(HAVE_UINT16_FROM_RPC_RPC_H)
+#if (SIZEOF_SHORT == 4)
+#define uint16 __ERROR___CANNOT_DETERMINE_TYPE_FOR_INT16;
+#else /* SIZEOF_SHORT != 4 */
+#define uint16 unsigned short
+#endif /* SIZEOF_SHORT != 4 */
+#endif
+
+#ifndef uint32
+#define uint32 unsigned int
+#endif
+
+/* NOTE: This code makes no attempt to be fast! 
+
+   It assumes that a int is at least 32 bits long
+*/
+
+static uint32 A, B, C, D;
+
+static uint32 F(uint32 X, uint32 Y, uint32 Z)
+{
+	return (X&Y) | ((~X)&Z);
+}
+
+static uint32 G(uint32 X, uint32 Y, uint32 Z)
+{
+	return (X&Y) | (X&Z) | (Y&Z); 
+}
+
+static uint32 H(uint32 X, uint32 Y, uint32 Z)
+{
+	return X^Y^Z;
+}
+
+static uint32 lshift(uint32 x, int s)
+{
+	x &= 0xFFFFFFFF;
+	return ((x<<s)&0xFFFFFFFF) | (x>>(32-s));
+}
+
+#define ROUND1(a,b,c,d,k,s) a = lshift(a + F(b,c,d) + X[k], s)
+#define ROUND2(a,b,c,d,k,s) a = lshift(a + G(b,c,d) + X[k] + (uint32)0x5A827999,s)
+#define ROUND3(a,b,c,d,k,s) a = lshift(a + H(b,c,d) + X[k] + (uint32)0x6ED9EBA1,s)
+
+/* this applies md4 to 64 byte chunks */
+static void mdfour64(uint32 *M)
+{
+	int j;
+	uint32 AA, BB, CC, DD;
+	uint32 X[16];
+
+	for (j=0;j<16;j++)
+		X[j] = M[j];
+
+	AA = A; BB = B; CC = C; DD = D;
+
+        ROUND1(A,B,C,D,  0,  3);  ROUND1(D,A,B,C,  1,  7);  
+	ROUND1(C,D,A,B,  2, 11);  ROUND1(B,C,D,A,  3, 19);
+        ROUND1(A,B,C,D,  4,  3);  ROUND1(D,A,B,C,  5,  7);  
+	ROUND1(C,D,A,B,  6, 11);  ROUND1(B,C,D,A,  7, 19);
+        ROUND1(A,B,C,D,  8,  3);  ROUND1(D,A,B,C,  9,  7);  
+	ROUND1(C,D,A,B, 10, 11);  ROUND1(B,C,D,A, 11, 19);
+        ROUND1(A,B,C,D, 12,  3);  ROUND1(D,A,B,C, 13,  7);  
+	ROUND1(C,D,A,B, 14, 11);  ROUND1(B,C,D,A, 15, 19);	
+
+        ROUND2(A,B,C,D,  0,  3);  ROUND2(D,A,B,C,  4,  5);  
+	ROUND2(C,D,A,B,  8,  9);  ROUND2(B,C,D,A, 12, 13);
+        ROUND2(A,B,C,D,  1,  3);  ROUND2(D,A,B,C,  5,  5);  
+	ROUND2(C,D,A,B,  9,  9);  ROUND2(B,C,D,A, 13, 13);
+        ROUND2(A,B,C,D,  2,  3);  ROUND2(D,A,B,C,  6,  5);  
+	ROUND2(C,D,A,B, 10,  9);  ROUND2(B,C,D,A, 14, 13);
+        ROUND2(A,B,C,D,  3,  3);  ROUND2(D,A,B,C,  7,  5);  
+	ROUND2(C,D,A,B, 11,  9);  ROUND2(B,C,D,A, 15, 13);
+
+	ROUND3(A,B,C,D,  0,  3);  ROUND3(D,A,B,C,  8,  9);  
+	ROUND3(C,D,A,B,  4, 11);  ROUND3(B,C,D,A, 12, 15);
+        ROUND3(A,B,C,D,  2,  3);  ROUND3(D,A,B,C, 10,  9);  
+	ROUND3(C,D,A,B,  6, 11);  ROUND3(B,C,D,A, 14, 15);
+        ROUND3(A,B,C,D,  1,  3);  ROUND3(D,A,B,C,  9,  9);  
+	ROUND3(C,D,A,B,  5, 11);  ROUND3(B,C,D,A, 13, 15);
+        ROUND3(A,B,C,D,  3,  3);  ROUND3(D,A,B,C, 11,  9);  
+	ROUND3(C,D,A,B,  7, 11);  ROUND3(B,C,D,A, 15, 15);
+
+	A += AA; B += BB; C += CC; D += DD;
+	
+	A &= 0xFFFFFFFF; B &= 0xFFFFFFFF;
+	C &= 0xFFFFFFFF; D &= 0xFFFFFFFF;
+
+	for (j=0;j<16;j++)
+		X[j] = 0;
+}
+
+static void copy64(uint32 *M, unsigned char *in)
+{
+	int i;
+
+	for (i=0;i<16;i++)
+		M[i] = (in[i*4+3]<<24) | (in[i*4+2]<<16) |
+			(in[i*4+1]<<8) | (in[i*4+0]<<0);
+}
+
+static void copy4(unsigned char *out,uint32 x)
+{
+	out[0] = x&0xFF;
+	out[1] = (x>>8)&0xFF;
+	out[2] = (x>>16)&0xFF;
+	out[3] = (x>>24)&0xFF;
+}
+
+/* produce a md4 message digest from data of length n bytes */
+void mdfour(unsigned char *out, unsigned char *in, int n)
+{
+	unsigned char buf[128];
+	uint32 M[16];
+	uint32 b = n * 8;
+	int i;
+
+	A = 0x67452301;
+	B = 0xefcdab89;
+	C = 0x98badcfe;
+	D = 0x10325476;
+
+	while (n > 64) {
+		copy64(M, in);
+		mdfour64(M);
+		in += 64;
+		n -= 64;
+	}
+
+	for (i=0;i<128;i++)
+		buf[i] = 0;
+	memcpy(buf, in, n);
+	buf[n] = 0x80;
+	
+	if (n <= 55) {
+		copy4(buf+56, b);
+		copy64(M, buf);
+		mdfour64(M);
+	} else {
+		copy4(buf+120, b); 
+		copy64(M, buf);
+		mdfour64(M);
+		copy64(M, buf+64);
+		mdfour64(M);
+	}
+
+	for (i=0;i<128;i++)
+		buf[i] = 0;
+	copy64(M, buf);
+
+	copy4(out, A);
+	copy4(out+4, B);
+	copy4(out+8, C);
+	copy4(out+12, D);
+
+	A = B = C = D = 0;
+}
+
+
diff -u -N ../clean-src/options.c ./options.c
--- ../clean-src/options.c	Thu Aug 21 03:38:14 2003
+++ ./options.c	Fri Sep 19 14:20:52 2003
@@ -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(int argc, char **argv)
diff -u -N ../clean-src/smbencrypt.c ./smbencrypt.c
--- ../clean-src/smbencrypt.c	Thu Jan  1 01:00:00 1970
+++ ./smbencrypt.c	Thu Mar 20 03:59:23 2003
@@ -0,0 +1,105 @@
+/* 
+   Unix SMB/Netbios implementation.
+   Version 1.9.
+   SMB parameters and setup
+   Copyright (C) Andrew Tridgell 1992-1998
+   Modified by Jeremy Allison 1995.
+   
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+
+#include <sys/types.h>
+
+
+#ifndef uchar
+#define uchar unsigned char
+#endif
+
+#if !defined(uint16) && !defined(HAVE_UINT16_FROM_RPC_RPC_H)
+#if (SIZEOF_SHORT == 4)
+#define uint16 __ERROR___CANNOT_DETERMINE_TYPE_FOR_INT16;
+#else /* SIZEOF_SHORT != 4 */
+#define uint16 unsigned short
+#endif /* SIZEOF_SHORT != 4 */
+#endif
+
+#if !defined(int16) && !defined(HAVE_INT16_FROM_RPC_RPC_H)
+#if (SIZEOF_SHORT == 4)
+#define int16 __ERROR___CANNOT_DETERMINE_TYPE_FOR_INT16;
+#else /* SIZEOF_SHORT != 4 */
+#define int16 short
+#endif /* SIZEOF_SHORT != 4 */
+#endif
+
+#include "byteorder.h"
+
+extern void mdfour(unsigned char *out, unsigned char *in, int n);
+
+
+/* Routines for Windows NT MD4 Hash functions. */
+static int _my_wcslen(int16 *str)
+{
+	int len = 0;
+	while(*str++ != 0)
+		len++;
+	return len;
+}
+
+/*
+ * Convert a string into an NT UNICODE string.
+ * Note that regardless of processor type 
+ * this must be in intel (little-endian)
+ * format.
+ */
+ 
+static int _my_mbstowcs(int16 *dst, uchar *src, int len)
+{
+	int i;
+	int16 val;
+ 
+	for(i = 0; i < len; i++) {
+		val = *src;
+		SSVAL(dst,0,val);
+		dst++;
+		src++;
+		if(val == 0)
+			break;
+	}
+	return i;
+}
+
+/* 
+ * Creates the MD4 Hash of the users password in NT UNICODE.
+ */
+ 
+void E_md4hash(uchar *passwd, uchar *p16)
+{
+	int len;
+	int16 wpwd[129];
+	
+	/* Password cannot be longer than 128 characters */
+	len = strlen((char *)passwd);
+	if(len > 128)
+		len = 128;
+	/* Password must be converted to NT unicode */
+	_my_mbstowcs(wpwd, passwd, len);
+	wpwd[len] = 0; /* Ensure string is null terminated */
+	/* Calculate length in bytes */
+	len = _my_wcslen(wpwd) * sizeof(int16);
+
+	mdfour(p16, (unsigned char *)wpwd, len);
+}
+

