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