Article 31 of alt.security:
Path: bloom-beacon!snorkelwacker!think!zaphod.mps.ohio-state.edu!rpi!brutus.cs.uiuc.edu!ux1.cso.uiuc.edu!uxc.cso.uiuc.edu!paul
From: paul@uxc.cso.uiuc.edu (Paul Pomes - UofIllinois CSO)
Newsgroups: alt.security
Subject: Improved password cracker
Message-ID: <1990Apr19.222725.24345@ux1.cso.uiuc.edu>
Date: 19 Apr 90 22:27:25 GMT
Sender: usenet@ux1.cso.uiuc.edu (News)
Organization: University of Illinois at Urbana
Lines: 562


/*
 * pwc -- password cracker
 *
 * pwc is a brute force password cracking program.  It reads a list of
 * /etc/passwd entries from the password file argument and compares
 * the password field against the contents of the remaining file arguments.
 * Good pattern files are the dictionary files in /usr/lib/dict, lists of
 * first names from the GECOS field, single letters and numbers,
 * license plates, etc.
 *
 * usage: pwc [-d] [-v] [-i] passwd_file file1 file2
 *
 * -d	issue debugging information
 *
 * -v	verbose.  Print intermediate information as cracking proceeds
 *
 * -i	identify and print usage message
 */

char *Copyright_Legend[] = {
 " Written by Paul Pomes, University of Illinois, Computing Services Office",
 " Copyright (C) 1986 by Paul Pomes and the University of Illinois Board",
 " of Trustees",
 " ",
 " This program is distributed in the hope that it will be useful,",
 " but without any warranty.  No author or distributor accepts",
 " responsibility to anyone for the consequences of using it or for",
 " whether it serves any particular purpose or works at all, unless",
 " s/he says so in writing.",
 " ",
 " Everyone is granted permission to copy, modify and redistribute",
 " this program under the following conditions:",
 " ",
 "    Permission is granted to anyone to make or distribute copies",
 "    of program source code, either as received or modified, in any",
 "    medium, provided that all copyright notices, permission and",
 "    nonwarranty notices are preserved, and that the distributor",
 "    grants the recipient permission for further redistribution as",
 "    permitted by this document, and gives him and points out to",
 "    him an exact copy of this document to inform him of his rights.",
 " ",
 "    Permission is granted to distribute this program in compiled",
 "    or executable form under the same conditions applying for",
 "    source code, provided that either",
 "    A. it is accompanied by the corresponding machine-readable",
 "       source code, or",
 "    B. it is accompanied by a written offer, with no time limit,",
 "       to give anyone a machine-readable copy of the corresponding",
 "       source code in return for reimbursement of the cost of",
 "       distribution.  This written offer must permit verbatim",
 "       duplication by anyone.",
 "    C. it is distributed by someone who received only the",
 "       executable form, and is accompanied by a copy of the",
 "       written offer of source code which he received along with it.",
 " ",
 " In other words, you are welcome to use, share and improve this",
 " program.  You are forbidden to forbid anyone else to use, share",
 " and improve what you give them.   Help stamp out software-hoarding!",
 " ",
 " UUCP:     {ihnp4,pur-ee,convex}!uiucdcs!uiucuxc!paul",
 " ARPANET:  paul%uxc@a.cs.uiuc.edu   CSNET: paul%uxc@uiuc.csnet",
 " ICBMS:    88 13 N / 40 07 W",
 " US Mail:  Univ of Illinois, CSO, 1304 W Springfield Ave, Urbana, IL  61801",
 0
};

/*
 * $Log:	pwc.c,v $
 * Revision 1.1  86/08/26  15:55:23  paul
 * Initial revision
 * 
 */

#ifndef lint
static char	RcsId[] = "$Header: pwc.c,v 1.1 86/08/26 15:55:23 paul Exp $";
#endif

#include	<stdio.h>
#include	<strings.h>
#include	<ctype.h>
#include	<pwd.h>

#define		equal(s1, s2)	(strcmp (s1, s2) == 0)
#define		skipline(f)	while (getc (f) != '\n')

#define		PROC				/* null; easy to find procs */
#define		FALSE		0
#define		TRUE		1
#define		CHNULL		('\0')
#define		CPNULL		((char *) NULL)
#define		FILENULL	((FILE *) NULL)
#define		REG		register
#define		BMASK		0377

#define		MAXFILE		15

/*
 * Miscellaneous global values:
 */

char *usage[] = {
	"usage: %s [-d] [-v] [-i] passwd_file [file1] [file2 ...]",
	CPNULL
};

/* how program was invoked (argv[0]) for error messages */
char		*myname;

/* debug messages printed if set (-d) */
int		dflag = FALSE;

/* print informational messages every so often (-v) */
int		vflag = FALSE;

/* external functions */
extern char	*fcrypt ();

/* internal functions */
char		*getstr ();

PROC main (argc, argv)
int	argc;
char	**argv;
{
	extern int	optind;		/* from getopt () */
	extern char	*optarg;	/* from getopt () */
	int		option;		/* option "letter" */
	int		i;		/* counters */
	int		done = 0;	/* found a login match */
	REG FILE	*filep;		/* open input file */
	char		*pw_file = CPNULL;	/* name to use */
	char		pattern[200];	/* word patterns from file */
	char		*ciphered;	/* result from fcrypt () */
	char		*cp, *cp2;
	REG struct passwd	*pwp;	/* fast pointer to passwd struct */
	FILE		*pat_fp[MAXFILE];	/* pattern file pointers */
	char		*indexm();

	/*
	 * BASENAME:  Full string, or past '/' if any:
	 */

	myname = ((myname = rindex (*argv, '/')) == CPNULL) ? *argv : (myname + 1);

	/*
	 * PARSE ARGUMENTS:
	 */

	while ((option = getopt (argc, argv, "dvi")) != EOF) {
		switch (option) {
		    case 'd':
			dflag++;
			fprintf (stderr, "%s: dflag = %d\n", myname, dflag);
			break;

		    case 'v':
			vflag++;
			break;

		    case 'i':
			Usage (1);
			break;

		    default:
			Usage (0);
		}
	}
	argc -= optind;			/* skip options */
	argv += optind;

	if (argc < 1) 			/* no file names */
		Error ("No password file specified");
	pw_file = *argv;
	argc--; argv++;
	if (dflag)
		fprintf (stderr, "password file is %s\n", pw_file);
	setlinebuf (stdout);

	/*
	 * open the pattern files and assign stream pointers in pat_fp.
	 * when stepping through the files, the register variable filep
	 * will be what's referenced.  care must be taken to set fp_pat[n]
	 * back to what filep is before rewind the file and going on to
	 * fp_pat[n+1].
	 */

	if (argc < 1) 			/* no file names */
		pat_fp[0] = FILENULL;
	else {
		for (i = 0; i < MAXFILE && argc > 0; i++, argc--, argv++) {
			if (dflag)
				fprintf (stderr, "%d opening %s\n", i, *argv);
			if ((pat_fp[i] = fopen (*argv, "r")) == FILENULL)
				Error ("can't open file \"%s\" to read it", *argv);
		}
		pat_fp[i] = FILENULL;
		if (i == MAXFILE)
			fprintf (stderr, "%s: too many pattern files.  files after %s ignored\n",
				myname, *(--argv));
	}

	/* set the password file name for use by getpwent */

	setpwfile (pw_file);
	setpwent ();

	init_des();

	/*
	 * two nested loops do the real work.  outermost loop steps through
	 * password entries.  next loop works through pat_fp array of FILE
	 * descriptors.  innermost loop works through each file issuing
	 * calls to fcrypt ().
	 */

	while ((pwp = getpwent()) != NULL) {
		done = 0;
		printf ("%.8s", pwp->pw_name);
		(void) fflush (stdout);
		if (*pwp->pw_name == 'U') {
			printf("\t- UUCP account, skipping\n");
			fflush(stdout);
			continue;
		}
		if (*pwp->pw_passwd == '\0') {
			printf("\t- Null password (shell is %s)\n",
			    pwp->pw_shell);
			continue;
		}
		if (equal (pwp->pw_passwd, "*")) {
			printf("\n");
			continue;
		}
		/*
		 * Try the user's login name
		 */
		*pattern = '\0';
		do {
			(void)strcat(pattern, pwp->pw_name);
			if (uandltry(pwp, pattern)) {
				done++;
				break;
			}
		} while (strlen(pattern) < 8);
		if (done)
			continue;

		/*
		 * Try names from the gecos field
		 */
		strcpy(pattern, pwp->pw_gecos);
		cp = pattern;
		for (;;) {
			if ((cp2 = indexm(cp, " ,;")) == NULL)
				cp2 = pattern + strlen(pwp->pw_gecos) - 1;
			else
				*cp2 = '\0';
			if (uandltry(pwp,cp)) {
				done++;
				break;
			}
			cp = ++cp2;
		}
		if (done)
			continue;

		/*
		 * Try all single letters
		 * (try digits too .  --Seth)
		 */
		pattern[1] = '\0';
		for (pattern[0]='a'; pattern[0] <= 'z'; pattern[0]++)
			if (try(pwp,pattern)) {
				done++;
				break;
			}
		for (pattern[0]='A'; pattern[0] <= 'Z'; pattern[0]++)
			if (try(pwp,pattern)) {
				done++;
				break;
			}
		for (pattern[0]='0'; pattern[0] <= '9'; pattern[0]++)
			if (try(pwp,pattern)) {
				done++;
				break;
			}
		if (done)
			continue;
		for (i = 0, filep = pat_fp[i];
		    filep != FILENULL; i++, filep = pat_fp[i]) {
			while (getstr (pattern, 8, filep) != CPNULL) {
				ciphered = fcrypt (pattern, pwp->pw_passwd);
				if (dflag > 1)
					fprintf(stderr, "  Testing =%s=, got =%s=\n", pattern, ciphered);
				if (equal (ciphered, pwp->pw_passwd)) {
					try (pwp, pattern);
					done++;
					break;
				}
			}
			rewind (filep);
			if (done)
				break;
		}
		if (! done)
			putchar ('\n');
	}
	exit (0);
} /* main */

/*
 * Usage -- print how to use message
 *
 * Print usage messages (char *usage[]) to stderr and exit nonzero.
 * Each message is followed by a newline.
 *
 *	parameters:
 *		full_text	(IN)	prints the copyright statement if set
 *	returns:
 *		none, exit (1)
 *	side effects:
 *		program terminates
 *	deficiencies:
 */

PROC Usage (full_text)
int	full_text;
{
	REG int		which = 0;		/* current line */

	while (usage[which] != CPNULL) {
		fprintf (stderr, usage[which++], myname);
		putc ('\n', stderr);
	}
	fflush(stdout);
	which = 0;
	if (full_text) {
		while (Copyright_Legend[which] != CPNULL)
			printf ("%s\n", Copyright_Legend[which++]);
	}
	exit (1);
} /* Usage */

/*
 * Error -- print error message with program name
 *
 * Print an error message to stderr and exit nonzero.  Message is preceded
 * by "<myname>: " using global char *myname, and followed by a newline.
 *
 *	parameters:
 *		message (IN)	printf format string
 *		arg1-4	(IN)	printf arguments
 *	returns:
 *		none, exit (1)
 *	side effects:
 *		program terminates
 *	deficiencies:
 */

/* VARARGS */
PROC Error (message, arg1, arg2, arg3, arg4)
char	*message;
long	arg1, arg2, arg3, arg4;
{
	fprintf (stderr, "%s: ", myname);
	fprintf (stderr, message, arg1, arg2, arg3, arg4);
	putc ('\n', stderr);
	exit (1);
} /* Error */

/*
 * Malloc -- a malloc with error checking
 *
 *	parameters:
 *		size	(IN)	number of bytes to get
 *	returns:
 *		(char *) of first char of block, or
 *		calls Error () upon error
 *	side effects:
 *		none
 *	deficiencies:
 */

char	*malloc ();
char	*Malloc ();

PROC char * Malloc (size)
unsigned	size;	/* bytes to get */
{
	char	*cp;	/* pointer to memory */

	if ((cp = malloc (size)) == CPNULL)
	    Error ("malloc %d bytes failed", size);
	return (cp);
} /* Malloc */

/*
 * getstr -- get a string of length n or up to a new-line from a file
 *
 *	parameters:
 *		s	(IN/OUT) char array to place string into
 *		n	(IN)	 maximum number of characters to get
 *		iop	(IN/OUT) FILE descriptor
 *	returns:
 *		(char *) of first char of block, or
 *		calls Error () upon error
 *	side effects:
 *		none
 *	deficiencies:
 */

PROC char * getstr (s, n, iop)
char	*s;
int	n;
register FILE *iop;
{
	register c;
	register char *cs;

	cs = s;
	n++;
	while (--n > 0 && (c = getc (iop)) >= NULL) {
		*cs = c;
		if (c == '\n') {
			*cs = CHNULL;
			break;
		}
		cs++;
	}
	if (c < 0 && cs == s)
		return (CPNULL);
	if (c != '\n')
		while ((c = getc (iop)) != '\n' && c >= 0)
	*cs++ = CHNULL;
	return (s);
} /* getstr */
/*
 * Added by Jacob Gore, March 12, 1987.
 *
 * Finds the pointer of the leftmost occurance within the character string
 * 'string' of any character found within the character string 'chars'.
 *
 * If none of the characters in 'chars' appear in 'string', NULL is retutned.
 *
 */
char *
indexm (string, chars)
    char *string, *chars;
{
    while (*string) {
	if (index(chars, *string) != NULL) {
	    return string;
	}
	string++;
    }
    return NULL;
}
/*
 * 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.
 * Written by Craig Leres, modified by Paul Pomes
*/

uandltry (pwd,guess)
char *guess;
struct passwd *pwd;
{
    register char *cp, *cpx;
    char buf[100];
    int alllower, allupper;
    char *reverse();

    alllower = allupper = 1;

    if (try(pwd,guess)) return (1); 
    if (try(pwd,(cpx = reverse(guess)))) {
	free (cpx);
	return (1);
    }
    free (cpx);

    strcpy (buf, guess);
    cp = buf-1;
    while (*++cp) {
	if (isupper(*cp))
	    alllower = 0;
	if (islower(*cp))
	    allupper = 0;
	}

    if (!allupper) {
	for ( cp=buf; *cp != '\0'; cp++)
	    if (islower (*cp))
		*cp += 'A' - 'a';

	    if (try(pwd,buf)) return (1); 
	    if (try(pwd,(cpx = reverse(buf)))) {
		free (cpx);
		return (1);
	    }
	    free (cpx);
	}

    if (!alllower) {
	for ( cp = buf; *cp != '\0'; cp++)
	    if (isupper (*cp))
		*cp += 'a' - 'A';

	if (try(pwd,buf)) return (1); 
	if (try(pwd,(cpx = reverse(buf)))) {
	    free (cpx);
	    return (1);
	}
	free (cpx);
	}
    return (0);
}

try(pwd,guess)
char *guess;
register struct passwd *pwd;
{
    register char  *cp;
    char   *fcrypt ();

    if (! guess || ! *guess) return(0);
    cp = fcrypt (guess, pwd -> pw_passwd);
    if (strcmp (cp, pwd -> pw_passwd))
	return (0);
	printf("\t- Guessed password is %s (shell is %s)\n",
		    guess, pwd->pw_shell);
    fflush (stdout);
    return (1);
}
/*
 * 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 = '\0';
    while (*str && (*--ptr = *str++))
	;
    return(ptr);
}
--
         Paul Pomes

UUCP: {att,iuvax,uunet}!uiucuxc!paul   Internet, BITNET: paul@uxc.cso.uiuc.edu
US Mail:  UofIllinois, CSO, 1304 W Springfield Ave, Urbana, IL  61801-2987


Article 33 of alt.security:
Path: bloom-beacon!snorkelwacker!think!zaphod.mps.ohio-state.edu!uwm.edu!lll-winken!uunet!deimos.cis.ksu.edu!ux1.cso.uiuc.edu!uxc.cso.uiuc.edu!paul
From: paul@uxc.cso.uiuc.edu (Paul Pomes - UofIllinois CSO)
Newsgroups: alt.security
Subject: pwc.c and cops
Message-ID: <1990Apr19.223129.25184@ux1.cso.uiuc.edu>
Date: 19 Apr 90 22:31:29 GMT
Sender: usenet@ux1.cso.uiuc.edu (News)
Organization: University of Illinois at Urbana
Lines: 11

Btw, the pwc.c program plus the FastDES routines is uses (fcrypt) are
available via anon-FTP to uxc.cso.uiuc.edu as pub/cops.tar.Z .

Better turn off or restrict tftpd folks.

/pbp
--
         Paul Pomes

UUCP: {att,iuvax,uunet}!uiucuxc!paul   Internet, BITNET: paul@uxc.cso.uiuc.edu
US Mail:  UofIllinois, CSO, 1304 W Springfield Ave, Urbana, IL  61801-2987


