1/*
2	This code is based on work from
3	L0phtcrack 1.5 06.02.97 mudge@l0pht.com
4
5	The code also contains sources from:
6                . routines from the samba code source
7		  md4.c smbdes.c
8
9	Anton Roeckseisen (anton@genua.de)
10
11*/
12
13/*
14 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include "mkntpwd.h"
28
29void str_to_key(unsigned char *,unsigned char *);
30void usage(char *);
31int PutUniCode(char *dst,char *src);
32void printlanhash(char *tmp);
33void mdfour(unsigned char *out, unsigned char *in, int n);
34void E_P16(unsigned char *p14,unsigned char *p16);
35
36
37void main(int argc, char **argv) {
38	extern char *optarg;
39	int c;
40
41	int printlan = 0;
42	char lanpwd[LMPASSWDLEN+1];
43	int printnt = 0;
44	char inputfile[FILENAMEBUFFER+1] = "";
45	FILE* InputFilePtr;
46	int just_pwd = 0;
47	int i;
48	char hashout[17];
49
50	char ntpasswd[NTPASSWDLEN+1];
51	char *hold;
52	unsigned char *p16;
53	int uni_len;
54	char passwd[NTPASSWDLEN+1];
55
56	if (argc==1)
57		usage(argv[0]);
58
59	if (argc==2)
60		just_pwd=1;
61	else
62		just_pwd=0;
63
64	lanpwd[0] = '\0';
65	ntpasswd[0] = '\0';
66
67	while ( (c = getopt(argc, argv, "L:N:f:")) != EOF){
68		switch(c) {
69		case 'L':
70			printlan++;
71			strncpy(lanpwd,optarg,LMPASSWDLEN);
72			lanpwd[LMPASSWDLEN]='\0';
73			for (i=0;i<LMPASSWDLEN;i++)
74				lanpwd[i]=toupper(lanpwd[i]);
75			break;
76		case 'N':
77			printnt++;
78			strncpy(passwd,optarg,NTPASSWDLEN);
79			passwd[NTPASSWDLEN]='\0';
80			break;
81		case 'f':
82			strncpy(inputfile,optarg,FILENAMEBUFFER);
83			inputfile[FILENAMEBUFFER]='\0';
84			break;
85		default:
86			usage(argv[0]);
87		}
88	}
89
90	/* Get password from file or STDIN */
91	if (inputfile[0]!='\0') {
92
93		just_pwd=0; /* make sure no shit is happening... */
94
95		/* get NT-password (longer) */
96		if (strcmp(inputfile,"-")==0) {
97			fgets(passwd,NTPASSWDLEN,stdin);
98		} else {
99			if ((InputFilePtr=fopen(inputfile,"r")) == NULL)
100				fprintf(stderr,"Couldn't open passwordfile: %s",inputfile) ;
101			fgets(passwd,NTPASSWDLEN,InputFilePtr);
102			fclose(InputFilePtr);
103		}
104		while (strlen(passwd)>0 && passwd[strlen(passwd)-1]=='\n')
105			passwd[strlen(passwd)-1]='\0';
106
107		/* create LANMAN-password (shorter) */
108		strncpy(lanpwd,passwd,LMPASSWDLEN);
109		lanpwd[LMPASSWDLEN]='\0';
110		for (i=0;i<LMPASSWDLEN;i++)
111			lanpwd[i]=toupper(lanpwd[i]);
112		printlan++;
113		printnt++;
114
115	}
116
117
118	/* Assume the one and only Arg is the new password! */
119
120	if (argc>1 && just_pwd==1) {
121                strncpy(lanpwd,argv[1],LMPASSWDLEN);
122		lanpwd[LMPASSWDLEN]='\0';
123		for (i=0;i<LMPASSWDLEN;i++)
124			lanpwd[i]=toupper(lanpwd[i]);
125		printlan++;
126
127		strncpy(passwd,argv[1],NTPASSWDLEN);
128		passwd[NTPASSWDLEN]='\0';
129		printnt++;
130	}
131
132	if (printlan >0) {
133		memset(hashout,'\0',17);
134		E_P16((uchar *)lanpwd,hashout);
135		printlanhash(hashout);
136	}
137
138	if (printnt >0) {
139
140		if (printlan>0) printf(":");
141
142		memset(ntpasswd, '\0', sizeof(ntpasswd));
143
144		if (passwd[strlen(passwd)-1] == '\n') /* strip the \n - this
145					is done in LowerString for the case sensitive
146					check */
147		passwd[strlen(passwd)-1] = '\0';
148
149		hold = (char *)malloc(NTPASSWDLEN * 2); /* grab space for
150						       unicode */
151		if (hold == NULL){
152			fprintf(stderr, "out of memory...crackntdialog hold\n");
153			exit(1);
154		}
155
156		uni_len = PutUniCode(hold, passwd); /* convert to
157						   unicode and return correct
158						   unicode length for md4 */
159
160		p16 = (unsigned char*)malloc(17); /* grab space for md4 hash */
161		if (p16 == NULL){
162		      fprintf(stderr, "out of memory...crackntdialect p16\n");
163		      exit(1);
164		}
165
166		memset(p16,'\0',17);
167		mdfour(p16,hold, uni_len);
168
169		printlanhash(p16);
170
171		free(p16);
172		free(hold);
173	}
174
175	printf("\n");
176
177	exit(0);
178
179}
180
181/*****************************************************************************/
182/*****************************************************************************/
183/*****************************************************************************/
184
185void usage(char *progname){
186   char *p;
187
188   p = strrchr(progname, '\\');
189   if (p == NULL)
190        p = progname;
191   else
192        p++;
193
194   fprintf(stderr, "Usage: %s [-L lanmgrpwd] [-N ntpasswd]\n",p);
195   fprintf(stderr, "       %s password\n",p);
196   fprintf(stderr, "       %s -f [-] [filename]\n\n",p);
197   fprintf(stderr, "     -L lanmgrpasswd  LanManager cleartextpwd <= 14 chars\n");
198   fprintf(stderr, "     -N ntpasswd      NT cleartextpwd <=128 chars (usually <=14)\n\n");
199   fprintf(stderr, "     with both options present the encrypted LanManager-Pwd is \n");
200   fprintf(stderr, "     printed first, followed by a ':' and the encrypted NT-Pwd.\n\n");
201   fprintf(stderr, "     The second usage behaves like %s -L pwd -N pwd\n\n",p);
202   fprintf(stderr, "     The third usage reads the password from STDIN or a File. Printout\n");
203   fprintf(stderr, "     is the same as second.\n\n");
204   fprintf(stderr, "anton@genua.de\n\n");
205   exit(1);
206}
207
208
209/*******************************************************************
210write a string in unicoode format
211********************************************************************/
212int PutUniCode(char *dst,char *src)
213{
214  int ret = 0;
215  while (*src) {
216    dst[ret++] = src[0];
217    dst[ret++] = 0;
218    src++;
219  }
220  dst[ret++]=0;
221  dst[ret++]=0;
222  return(ret-2); /* the way they do the md4 hash they don't represent
223                    the last null. ie 'A' becomes just 0x41 0x00 - not
224                    0x41 0x00 0x00 0x00 */
225}
226
227/*
228  print binary buffer as hex-string
229*/
230void printlanhash(char *tmp) {
231
232	int i;
233	unsigned char c;
234	char outbuffer[33];
235
236
237	/* build string from binary hash */
238	for(i=0;i<16;i++) {
239		c=tmp[i];
240		sprintf(outbuffer+2*i,"%x",(c>>4) & 0x0f);
241		sprintf(outbuffer+2*i+1,"%x",c & 0x0f);
242	}
243
244	/* convert to uppercase */
245	for(i=0;i<32;i++)
246		outbuffer[i] = toupper(outbuffer[i]);
247	outbuffer[32]='\0';
248
249	/* print out hex-string */
250	printf("%s",outbuffer);
251}
252
253
254