home *** CD-ROM | disk | FTP | other *** search
/ The Hacker's Encyclopedia 1998 / hackers_encyclopedia.iso / hacking / unix / pwc.doc < prev    next >
Encoding:
Text File  |  2003-06-11  |  14.3 KB  |  580 lines

  1. /*
  2.  * pwc -- password cracker
  3.  *
  4.  * pwc is a brute force password cracking program.  It reads a list of
  5.  * /etc/passwd entries from the password file argument and compares
  6.  * the password field against the contents of the remaining file arguments.
  7.  * Good pattern files are the dictionary files in /usr/lib/dict, lists of
  8.  * first names from the GECOS field, single letters and numbers,
  9.  * license plates, etc.
  10.  *
  11.  * usage: pwc [-d] [-v] [-i] passwd_file file1 file2
  12.  *
  13.  * -d    issue debugging information
  14.  *
  15.  * -v    verbose.  Print intermediate information as cracking proceeds
  16.  *
  17.  * -i    identify and print usage message
  18.  */
  19.  
  20. char *Copyright_Legend[] = {
  21.  " Written by Paul Pomes, University of Illinois, Computing Services Office",
  22.  " Copyright (C) 1986 by Paul Pomes and the University of Illinois Board",
  23.  " of Trustees",
  24.  " ",
  25.  " This program is distributed in the hope that it will be useful,",
  26.  " but without any warranty.  No author or distributor accepts",
  27.  " responsibility to anyone for the consequences of using it or for",
  28.  " whether it serves any particular purpose or works at all, unless",
  29.  " s/he says so in writing.",
  30.  " ",
  31.  " Everyone is granted permission to copy, modify and redistribute",
  32.  " this program under the following conditions:",
  33.  " ",
  34.  "    Permission is granted to anyone to make or distribute copies",
  35.  "    of program source code, either as received or modified, in any",
  36.  "    medium, provided that all copyright notices, permission and",
  37.  "    nonwarranty notices are preserved, and that the distributor",
  38.  "    grants the recipient permission for further redistribution as",
  39.  "    permitted by this document, and gives him and points out to",
  40.  "    him an exact copy of this document to inform him of his rights.",
  41.  " ",
  42.  "    Permission is granted to distribute this program in compiled",
  43.  "    or executable form under the same conditions applying for",
  44.  "    source code, provided that either",
  45.  "    A. it is accompanied by the corresponding machine-readable",
  46.  "       source code, or",
  47.  "    B. it is accompanied by a written offer, with no time limit,",
  48.  "       to give anyone a machine-readable copy of the corresponding",
  49.  "       source code in return for reimbursement of the cost of",
  50.  "       distribution.  This written offer must permit verbatim",
  51.  "       duplication by anyone.",
  52.  "    C. it is distributed by someone who received only the",
  53.  "       executable form, and is accompanied by a copy of the",
  54.  "       written offer of source code which he received along with it.",
  55.  " ",
  56.  " In other words, you are welcome to use, share and improve this",
  57.  " program.  You are forbidden to forbid anyone else to use, share",
  58.  " and improve what you give them.   Help stamp out software-hoarding!",
  59.  " ",
  60.  " UUCP:     {ihnp4,pur-ee,convex}!uiucdcs!uiucuxc!paul",
  61.  " ARPANET:  paul%uxc@a.cs.uiuc.edu   CSNET: paul%uxc@uiuc.csnet",
  62.  " ICBMS:    88 13 N / 40 07 W",
  63.  " US Mail:  Univ of Illinois, CSO, 1304 W Springfield Ave, Urbana, IL  61801",
  64.  0
  65. };
  66.  
  67. /*
  68.  * $Log:    pwc.c,v $
  69.  * Revision 1.1  86/08/26  15:55:23  paul
  70.  * Initial revision
  71.  * 
  72.  */
  73.  
  74. #ifndef lint
  75. static char    RcsId[] = "$Header: pwc.c,v 1.1 86/08/26 15:55:23 paul Exp $";
  76. #endif
  77.  
  78. #include    <stdio.h>
  79. #include    <strings.h>
  80. #include    <ctype.h>
  81. #include    <pwd.h>
  82.  
  83. #define        equal(s1, s2)    (strcmp (s1, s2) == 0)
  84. #define        skipline(f)    while (getc (f) != '\n')
  85.  
  86. #define        PROC                /* null; easy to find procs */
  87. #define        FALSE        0
  88. #define        TRUE        1
  89. #define        CHNULL        ('\0')
  90. #define        CPNULL        ((char *) NULL)
  91. #define        FILENULL    ((FILE *) NULL)
  92. #define        REG        register
  93. #define        BMASK        0377
  94.  
  95. #define        MAXFILE        15
  96.  
  97. /*
  98.  * Miscellaneous global values:
  99.  */
  100.  
  101. char *usage[] = {
  102.     "usage: %s [-d] [-v] [-i] passwd_file [file1] [file2 ...]",
  103.     CPNULL
  104. };
  105.  
  106. /* how program was invoked (argv[0]) for error messages */
  107. char        *myname;
  108.  
  109. /* debug messages printed if set (-d) */
  110. int        dflag = FALSE;
  111.  
  112. /* print informational messages every so often (-v) */
  113. int        vflag = FALSE;
  114.  
  115. /* external functions */
  116. extern char    *fcrypt ();
  117.  
  118. /* internal functions */
  119. char        *getstr ();
  120.  
  121. PROC main (argc, argv)
  122. int    argc;
  123. char    **argv;
  124. {
  125.     extern int    optind;        /* from getopt () */
  126.     extern char    *optarg;    /* from getopt () */
  127.     int        option;        /* option "letter" */
  128.     int        i;        /* counters */
  129.     int        done = 0;    /* found a login match */
  130.     REG FILE    *filep;        /* open input file */
  131.     char        *pw_file = CPNULL;    /* name to use */
  132.     char        pattern[200];    /* word patterns from file */
  133.     char        *ciphered;    /* result from fcrypt () */
  134.     char        *cp, *cp2;
  135.     REG struct passwd    *pwp;    /* fast pointer to passwd struct */
  136.     FILE        *pat_fp[MAXFILE];    /* pattern file pointers */
  137.     char        *indexm();
  138.  
  139.     /*
  140.      * BASENAME:  Full string, or past '/' if any:
  141.      */
  142.  
  143.     myname = ((myname = rindex (*argv, '/')) == CPNULL) ? *argv : (myname + 1);
  144.  
  145.     /*
  146.      * PARSE ARGUMENTS:
  147.      */
  148.  
  149.     while ((option = getopt (argc, argv, "dvi")) != EOF) {
  150.         switch (option) {
  151.             case 'd':
  152.             dflag++;
  153.             fprintf (stderr, "%s: dflag = %d\n", myname, dflag);
  154.             break;
  155.  
  156.             case 'v':
  157.             vflag++;
  158.             break;
  159.  
  160.             case 'i':
  161.             Usage (1);
  162.             break;
  163.  
  164.             default:
  165.             Usage (0);
  166.         }
  167.     }
  168.     argc -= optind;            /* skip options */
  169.     argv += optind;
  170.  
  171.     if (argc < 1)             /* no file names */
  172.         Error ("No password file specified");
  173.     pw_file = *argv;
  174.     argc--; argv++;
  175.     if (dflag)
  176.         fprintf (stderr, "password file is %s\n", pw_file);
  177.     setlinebuf (stdout);
  178.  
  179.     /*
  180.      * open the pattern files and assign stream pointers in pat_fp.
  181.      * when stepping through the files, the register variable filep
  182.      * will be what's referenced.  care must be taken to set fp_pat[n]
  183.      * back to what filep is before rewind the file and going on to
  184.      * fp_pat[n+1].
  185.      */
  186.  
  187.     if (argc < 1)             /* no file names */
  188.         pat_fp[0] = FILENULL;
  189.     else {
  190.         for (i = 0; i < MAXFILE && argc > 0; i++, argc--, argv++) {
  191.             if (dflag)
  192.                 fprintf (stderr, "%d opening %s\n", i, *argv);
  193.             if ((pat_fp[i] = fopen (*argv, "r")) == FILENULL)
  194.                 Error ("can't open file \"%s\" to read it", *argv);
  195.         }
  196.         pat_fp[i] = FILENULL;
  197.         if (i == MAXFILE)
  198.             fprintf (stderr, "%s: too many pattern files.  files after %s ignored\n",
  199.                 myname, *(--argv));
  200.     }
  201.  
  202.     /* set the password file name for use by getpwent */
  203.  
  204.     setpwfile (pw_file);
  205.     setpwent ();
  206.  
  207.     init_des();
  208.  
  209.     /*
  210.      * two nested loops do the real work.  outermost loop steps through
  211.      * password entries.  next loop works through pat_fp array of FILE
  212.      * descriptors.  innermost loop works through each file issuing
  213.      * calls to fcrypt ().
  214.      */
  215.  
  216.     while ((pwp = getpwent()) != NULL) {
  217.         done = 0;
  218.         printf ("%.8s", pwp->pw_name);
  219.         (void) fflush (stdout);
  220.         if (*pwp->pw_name == 'U') {
  221.             printf("\t- UUCP account, skipping\n");
  222.             fflush(stdout);
  223.             continue;
  224.         }
  225.         if (*pwp->pw_passwd == '\0') {
  226.             printf("\t- Null password (shell is %s)\n",
  227.                 pwp->pw_shell);
  228.             continue;
  229.         }
  230.         if (equal (pwp->pw_passwd, "*")) {
  231.             printf("\n");
  232.             continue;
  233.         }
  234.         /*
  235.          * Try the user's login name
  236.          */
  237.         *pattern = '\0';
  238.         do {
  239.             (void)strcat(pattern, pwp->pw_name);
  240.             if (uandltry(pwp, pattern)) {
  241.                 done++;
  242.                 break;
  243.             }
  244.         } while (strlen(pattern) < 8);
  245.         if (done)
  246.             continue;
  247.  
  248.         /*
  249.          * Try names from the gecos field
  250.          */
  251.         strcpy(pattern, pwp->pw_gecos);
  252.         cp = pattern;
  253.         for (;;) {
  254.             if ((cp2 = indexm(cp, " ,;")) == NULL)
  255.                 cp2 = pattern + strlen(pwp->pw_gecos) - 1;
  256.             else
  257.                 *cp2 = '\0';
  258.             if (uandltry(pwp,cp)) {
  259.                 done++;
  260.                 break;
  261.             }
  262.             cp = ++cp2;
  263.         }
  264.         if (done)
  265.             continue;
  266.  
  267.         /*
  268.          * Try all single letters
  269.          * (try digits too .  --Seth)
  270.          */
  271.         pattern[1] = '\0';
  272.         for (pattern[0]='a'; pattern[0] <= 'z'; pattern[0]++)
  273.             if (try(pwp,pattern)) {
  274.                 done++;
  275.                 break;
  276.             }
  277.         for (pattern[0]='A'; pattern[0] <= 'Z'; pattern[0]++)
  278.             if (try(pwp,pattern)) {
  279.                 done++;
  280.                 break;
  281.             }
  282.         for (pattern[0]='0'; pattern[0] <= '9'; pattern[0]++)
  283.             if (try(pwp,pattern)) {
  284.                 done++;
  285.                 break;
  286.             }
  287.         if (done)
  288.             continue;
  289.         for (i = 0, filep = pat_fp[i];
  290.             filep != FILENULL; i++, filep = pat_fp[i]) {
  291.             while (getstr (pattern, 8, filep) != CPNULL) {
  292.                 ciphered = fcrypt (pattern, pwp->pw_passwd);
  293.                 if (dflag > 1)
  294.                     fprintf(stderr, "  Testing =%s=, got =%s=\n", pattern, ciphered);
  295.                 if (equal (ciphered, pwp->pw_passwd)) {
  296.                     try (pwp, pattern);
  297.                     done++;
  298.                     break;
  299.                 }
  300.             }
  301.             rewind (filep);
  302.             if (done)
  303.                 break;
  304.         }
  305.         if (! done)
  306.             putchar ('\n');
  307.     }
  308.     exit (0);
  309. } /* main */
  310.  
  311. /*
  312.  * Usage -- print how to use message
  313.  *
  314.  * Print usage messages (char *usage[]) to stderr and exit nonzero.
  315.  * Each message is followed by a newline.
  316.  *
  317.  *    parameters:
  318.  *        full_text    (IN)    prints the copyright statement if set
  319.  *    returns:
  320.  *        none, exit (1)
  321.  *    side effects:
  322.  *        program terminates
  323.  *    deficiencies:
  324.  */
  325.  
  326. PROC Usage (full_text)
  327. int    full_text;
  328. {
  329.     REG int        which = 0;        /* current line */
  330.  
  331.     while (usage[which] != CPNULL) {
  332.         fprintf (stderr, usage[which++], myname);
  333.         putc ('\n', stderr);
  334.     }
  335.     fflush(stdout);
  336.     which = 0;
  337.     if (full_text) {
  338.         while (Copyright_Legend[which] != CPNULL)
  339.             printf ("%s\n", Copyright_Legend[which++]);
  340.     }
  341.     exit (1);
  342. } /* Usage */
  343.  
  344. /*
  345.  * Error -- print error message with program name
  346.  *
  347.  * Print an error message to stderr and exit nonzero.  Message is preceded
  348.  * by "<myname>: " using global char *myname, and followed by a newline.
  349.  *
  350.  *    parameters:
  351.  *        message (IN)    printf format string
  352.  *        arg1-4    (IN)    printf arguments
  353.  *    returns:
  354.  *        none, exit (1)
  355.  *    side effects:
  356.  *        program terminates
  357.  *    deficiencies:
  358.  */
  359.  
  360. /* VARARGS */
  361. PROC Error (message, arg1, arg2, arg3, arg4)
  362. char    *message;
  363. long    arg1, arg2, arg3, arg4;
  364. {
  365.     fprintf (stderr, "%s: ", myname);
  366.     fprintf (stderr, message, arg1, arg2, arg3, arg4);
  367.     putc ('\n', stderr);
  368.     exit (1);
  369. } /* Error */
  370.  
  371. /*
  372.  * Malloc -- a malloc with error checking
  373.  *
  374.  *    parameters:
  375.  *        size    (IN)    number of bytes to get
  376.  *    returns:
  377.  *        (char *) of first char of block, or
  378.  *        calls Error () upon error
  379.  *    side effects:
  380.  *        none
  381.  *    deficiencies:
  382.  */
  383.  
  384. char    *malloc ();
  385. char    *Malloc ();
  386.  
  387. PROC char * Malloc (size)
  388. unsigned    size;    /* bytes to get */
  389. {
  390.     char    *cp;    /* pointer to memory */
  391.  
  392.     if ((cp = malloc (size)) == CPNULL)
  393.         Error ("malloc %d bytes failed", size);
  394.     return (cp);
  395. } /* Malloc */
  396.  
  397. /*
  398.  * getstr -- get a string of length n or up to a new-line from a file
  399.  *
  400.  *    parameters:
  401.  *        s    (IN/OUT) char array to place string into
  402.  *        n    (IN)     maximum number of characters to get
  403.  *        iop    (IN/OUT) FILE descriptor
  404.  *    returns:
  405.  *        (char *) of first char of block, or
  406.  *        calls Error () upon error
  407.  *    side effects:
  408.  *        none
  409.  *    deficiencies:
  410.  */
  411.  
  412. PROC char * getstr (s, n, iop)
  413. char    *s;
  414. int    n;
  415. register FILE *iop;
  416. {
  417.     register c;
  418.     register char *cs;
  419.  
  420.     cs = s;
  421.     n++;
  422.     while (--n > 0 && (c = getc (iop)) >= NULL) {
  423.         *cs = c;
  424.         if (c == '\n') {
  425.             *cs = CHNULL;
  426.             break;
  427.         }
  428.         cs++;
  429.     }
  430.     if (c < 0 && cs == s)
  431.         return (CPNULL);
  432.     if (c != '\n')
  433.         while ((c = getc (iop)) != '\n' && c >= 0)
  434.     *cs++ = CHNULL;
  435.     return (s);
  436. } /* getstr */
  437. /*
  438.  * Added by Jacob Gore, March 12, 1987.
  439.  *
  440.  * Finds the pointer of the leftmost occurance within the character string
  441.  * 'string' of any character found within the character string 'chars'.
  442.  *
  443.  * If none of the characters in 'chars' appear in 'string', NULL is retutned.
  444.  *
  445.  */
  446. char *
  447. indexm (string, chars)
  448.     char *string, *chars;
  449. {
  450.     while (*string) {
  451.     if (index(chars, *string) != NULL) {
  452.         return string;
  453.     }
  454.     string++;
  455.     }
  456.     return NULL;
  457. }
  458. /*
  459.  * Stands for "upper and lower" try.  Calls the "real" try, below,
  460.  * with the supplied version of the password, and with
  461.  * an upper and lowercase version of the password. If the user doesn't
  462.  * want to try upper and lower case then we just return after the one
  463.  * check.
  464.  * Written by Craig Leres, modified by Paul Pomes
  465. */
  466.  
  467. uandltry (pwd,guess)
  468. char *guess;
  469. struct passwd *pwd;
  470. {
  471.     register char *cp, *cpx;
  472.     char buf[100];
  473.     int alllower, allupper;
  474.     char *reverse();
  475.  
  476.     alllower = allupper = 1;
  477.  
  478.     if (try(pwd,guess)) return (1); 
  479.     if (try(pwd,(cpx = reverse(guess)))) {
  480.     free (cpx);
  481.     return (1);
  482.     }
  483.     free (cpx);
  484.  
  485.     strcpy (buf, guess);
  486.     cp = buf-1;
  487.     while (*++cp) {
  488.     if (isupper(*cp))
  489.         alllower = 0;
  490.     if (islower(*cp))
  491.         allupper = 0;
  492.     }
  493.  
  494.     if (!allupper) {
  495.     for ( cp=buf; *cp != '\0'; cp++)
  496.         if (islower (*cp))
  497.         *cp += 'A' - 'a';
  498.  
  499.         if (try(pwd,buf)) return (1); 
  500.         if (try(pwd,(cpx = reverse(buf)))) {
  501.         free (cpx);
  502.         return (1);
  503.         }
  504.         free (cpx);
  505.     }
  506.  
  507.     if (!alllower) {
  508.     for ( cp = buf; *cp != '\0'; cp++)
  509.         if (isupper (*cp))
  510.         *cp += 'a' - 'A';
  511.  
  512.     if (try(pwd,buf)) return (1); 
  513.     if (try(pwd,(cpx = reverse(buf)))) {
  514.         free (cpx);
  515.         return (1);
  516.     }
  517.     free (cpx);
  518.     }
  519.     return (0);
  520. }
  521.  
  522. try(pwd,guess)
  523. char *guess;
  524. register struct passwd *pwd;
  525. {
  526.     register char  *cp;
  527.     char   *fcrypt ();
  528.  
  529.     if (! guess || ! *guess) return(0);
  530.     cp = fcrypt (guess, pwd -> pw_passwd);
  531.     if (strcmp (cp, pwd -> pw_passwd))
  532.     return (0);
  533.     printf("\t- Guessed password is %s (shell is %s)\n",
  534.             guess, pwd->pw_shell);
  535.     fflush (stdout);
  536.     return (1);
  537. }
  538. /*
  539.  * reverse a string
  540.  */
  541. char *reverse(str)
  542. char *str;
  543.  
  544. {
  545.     register char *ptr;
  546.     register int len;
  547.     char    *malloc();
  548.  
  549.     if ((ptr = malloc((len = strlen(str))+1)) == NULL)
  550.     return(NULL);
  551.     ptr += len;
  552.     *ptr = '\0';
  553.     while (*str && (*--ptr = *str++))
  554.     ;
  555.     return(ptr);
  556. }
  557.  
  558.  
  559.  
  560.      Another file downloaded from:                     NIRVANAnet(tm)
  561.  
  562.      & the Temple of the Screaming Electron              510-935-5845
  563.  
  564.      Rat Head                                            510-524-3649
  565.      Burn This Flag                                      408-363-9766
  566.      realitycheck                                        415-474-2602
  567.      Lies Unlimited                                      415-583-4102
  568.  
  569.    Specializing in conversations, obscure information, high explosives,
  570.        arcane knowledge, political extremism, diversive sexuality,
  571.        insane speculation, and wild rumours. ALL-TEXT BBS SYSTEMS.
  572.  
  573.   Full access for first-time callers.  We don't want to know who you are,
  574.    where you live, or what your phone number is. We are not Big Brother.
  575.  
  576.                          "Raw Data for Raw Nerves"
  577.  
  578.  
  579.