home *** CD-ROM | disk | FTP | other *** search
/ Hacker Chronicles 1 / HACKER1.ISO / miscpub1 / tj3_9.txt < prev    next >
Text File  |  1992-09-26  |  16KB  |  534 lines

  1. The LOD/H Technical Journal, Issue #3: File 09 of 11
  2.  
  3. ----------------> UNIX Password Hacker: Courtesy of USENET <------------------
  4.  
  5.     The following is an extensive unix password hacking program taken off
  6. USENET awhile back. It resembles Shooting Sharks' HPW.C program in some ways
  7. but this program has more options. Read the REM statements to determine what
  8. options you wish to enable. If nothing else, this program can give those who
  9. wish to write a similar program an idea of how and what you want to put in it.
  10.  
  11.  
  12. - - - - - - - - - - - - - - - - - cut here - - - - - - - - - - - - - - - - - - -
  13.  
  14.  
  15. #include <stdio.h>
  16. #include <pwd.h>
  17. #include <ctype.h>
  18.  
  19. #define index strchr
  20. #ifndef lint
  21. static char *rcsid = "$Header: pwchkr.c,v 1.2 85/11/30 22:42:07 richl Exp $";
  22. #endif
  23.  
  24. /*
  25.  * Warning: this program burns a lot of cpu.
  26.  */
  27. /*
  28.  * pwchkr - find accounts with poor passwords
  29.         Date: Tue, 29 Nov 83 18:19:32 pst
  30.         From: leres%ucbarpa@Berkeley (Craig Leres)
  31.             Modified by Seth Alford, Roger Southwick, Steve Dum, and
  32.             Rick Lindsley for Tektronix
  33.  */
  34.  
  35. /*
  36.  *      $Log:   pwchkr.c,v $
  37.  *      Revision 1.2  85/11/30  22:42:07  richl
  38.  *      Added code to allow for password aging.
  39.  *
  40.  *      Revision 1.1  85/09/10  16:00:56  root
  41.  *      Initial revision
  42.  *
  43.  *
  44.  * By default, this program only checks for accounts with passwords the same
  45.  * as the login name. The following options add more extensive checking. (The
  46.  * tradeoff is cpu time -- with all options enabled it can run into the 100's
  47.  * of MINUTES.) Any argument that does not begin with a "-" is assumed to be
  48.  * a file name. (A single '-' means stdin.) If no file name is given,
  49.  * /etc/passwd is used.
  50.  *
  51.  * Options:
  52.  *
  53.  *              -v:     verbose -- list all guesses on stdout
  54.  *              -u:     output teh username on the line of the password file
  55.  *                      currently being checked. If the program stops
  56.  *                      abruptly you will then know how far it got.
  57.  *              -w file: use the list of words contained in "file" as likely
  58.  *                      passwords. Words in the file are one to a line.
  59.  *              -b:     check all guesses backwards too
  60.  *              -g:     use the Full Name portion of the gecos field to
  61.  *                      generate more guesses
  62.  *              -s:     check the single letters a-z, A-Z, 0-9 as passwords
  63.  *              -c:     with each guess, check for all-lowercase and
  64.  *                      all-uppercase versions too.
  65.  *              -n:     complain about null passwords (default is to keep
  66. quiet)
  67.  */
  68.  
  69. int verbose = 0, singles = 0, backwards = 0, checkgecos = 0, checkcase = 0,
  70.     chknulls = 0, users = 0, chkwords = 0;
  71.  
  72. char *index(), *reverse();
  73. long atol();
  74. FILE *fopen();
  75. char *fgets();
  76.  
  77. char PASSWD[] = "/etc/passwd";
  78. char EMPTY[] = "";
  79. static FILE *pwf = NULL, *wlf = NULL;
  80. char line[BUFSIZ+1];
  81. struct passwd passwd;
  82. char    *Curpw, *Wordlist = NULL;
  83.  
  84. main(argc, argv)
  85. char **argv;
  86. {
  87.     register int i;
  88.     register char *arg;
  89.     int onedone = 0;
  90.  
  91.  
  92.     for (i = 1; i < argc; i++)
  93.         if ((arg = argv[i]) && *arg == '-')
  94.             while (*++arg) {
  95.                 switch (*arg) {
  96.                     case 'n':
  97.                         /*
  98.                          * complain about null passwords
  99.                          */
  100.                         chknulls++;
  101.                         break;
  102.                     case 'c':
  103.                         /*
  104.                          * check cases
  105.                          */
  106.                         checkcase++;
  107.                         break;
  108.                     case 'g':
  109.                         /*
  110.                          * use gecos
  111.                          */
  112.                         checkgecos++;
  113.                         break;
  114.                     case 'v':
  115.                         /*
  116.                          * turn on motormouth
  117.                          */
  118.                         verbose++;
  119.                         break;
  120.                     case 'b':
  121.                         /*
  122.                          * check all attempts forwards and backwards
  123.                          */
  124.                         backwards++;
  125.                         break;
  126.                     case 's':
  127.                         /*
  128.                          * carry out a more intensive search, checking for
  129.                          * single letter passwords
  130.                          */
  131.                         singles++;
  132.                         break;
  133.                     case 'u':
  134.                         /*
  135.                          * print out users as testing
  136.                          */
  137.                         users++;
  138.                         break;
  139.                     case 'w':
  140.                         /*
  141.                          * consult word list of likely passwords
  142.                          */
  143.                         if ((Wordlist = argv[i+1]) == NULL) {
  144.                             fprintf(stderr,
  145.                                 "%s: No file supplied with -w option\n",
  146.                                 argv[0]);
  147.                             exit (1);
  148.                             }
  149.                         argv[i+1] = NULL;
  150.                         break;
  151.                     case '\0':
  152.                         /*
  153.                          * read from stdin
  154.                          */
  155.                         break;
  156.                     default:
  157.                         fprintf(stderr,
  158.                             "%s: unknown option '%c'. Options are:\n",argv[0],
  159.                             *arg);
  160.                         /* FALL THRU */
  161.                     case '-':
  162.                         fprintf(stderr,"-v:\t\tverbose -- list all guesses on
  163. stdout\n");
  164.                         fprintf(stderr,"-u:\t\toutput the username currently
  165. being checked\n");
  166.                         fprintf(stderr,"-w file:\tconsult the indicated file
  167. for words to check as passwords\n");
  168.                         fprintf(stderr,"-b:\t\tcheck all guesses forwards and
  169. backwards\n");
  170.                         fprintf(stderr,"-g:\t\tuse the Full name portion of the
  171. gecos field for more guesses\n");
  172.                         fprintf(stderr,"-s:\t\tcheck the single letters a-z,
  173. A-Z, 0-9 as passwords\n");
  174.                         fprintf(stderr,"-c:\t\tcheck the all-upper and
  175. all-lower case version of each guess\n");
  176.                         fprintf(stderr,"-n:\t\tcomplain about null
  177. passwords\n");
  178.                         exit(1);
  179.                     }
  180.                 argv[i] = NULL;
  181.                 }
  182.  
  183.     for (i = 1; i < argc; i++) {
  184.         if (argv[i] == NULL) continue;
  185.         onedone++;
  186.         if (*(argv[i]) == '-') {
  187.             /*
  188.              * read from stdin; we'll cheat and set pwf directly
  189.              */
  190.             pwf = stdin;
  191.             chkpw();
  192.             /*
  193.              * don't fclose stdin!
  194.              */
  195.             clearerr(stdin);
  196.             }
  197.         else {
  198.             if (setpwent(argv[i])) {
  199.                 perror(argv[i]);
  200.                 continue;
  201.                 }
  202.             Curpw = argv[i];
  203.             chkpw();
  204.             endpwent();
  205.             }
  206.         }
  207.     if (!onedone) {
  208.         Curpw = NULL;
  209.         chkpw();
  210.         }
  211.     exit(0);
  212. }
  213.  
  214. #define ARB_CONST       30000
  215.  
  216. chkpw()
  217.  
  218. {
  219.     register char       *cp, *cp2;
  220.     register struct passwd *pwd;
  221.     struct passwd       *getpwent();
  222.     char                guess[100];
  223.     char                *wordarray[ARB_CONST];
  224.     char                *malloc(), **wordptr, **endptr;
  225.     int                 done = 0;
  226.  
  227.  
  228.     if (Wordlist)
  229.     {
  230.         if ((wlf = fopen(Wordlist,"r")) == NULL)
  231.         {
  232.             perror(Wordlist);
  233.             exit(1);
  234.         }
  235.  
  236.         wordptr = wordarray;
  237.         /*
  238.          * note that endptr points to space OUTSIDE of wordarray
  239.          */
  240.         endptr = wordarray + (sizeof(wordarray)/sizeof(char *));
  241.  
  242.         while (fscanf(wlf,"%[^\n]\n",guess) != EOF)
  243.         {
  244.             if (wordptr == endptr)
  245.             {
  246.                 fprintf(stderr,"Ran out of wordlist space. ARB_CONST %d must be
  247. too small.\n", ARB_CONST);
  248.                 exit(1);
  249.             }
  250.             if ((*wordptr = malloc(1+strlen(guess))) == NULL)
  251.             {
  252.                 fprintf(stderr,"malloc: no more memory for wordlist\n");
  253.                 exit (1);
  254.             }
  255.             strcpy(*wordptr,guess);
  256.             wordptr++;
  257.         }
  258.         *wordptr = NULL;
  259.     }
  260.  
  261.     while ((pwd = getpwent()) != 0 ) {
  262.  
  263.         if (verbose || users) {
  264.             if (Curpw == NULL)
  265.                 printf("\t%s \"%s\"\n", pwd->pw_name, pwd->pw_gecos);
  266.             else
  267.                 printf("%s -- \t%s \"%s\"\n", Curpw, pwd->pw_name,
  268.                     pwd->pw_gecos);
  269.             fflush(stdout);
  270.             }
  271.         if (*pwd->pw_passwd == '\0') {
  272.             if (chknulls) {
  273.                 if (Curpw == NULL)
  274.                     printf("Problem: null passwd:\t%s\tshell: %s\n",
  275.                         pwd->pw_name, pwd->pw_shell);
  276.                 else
  277.                     printf("%s -- Problem: null passwd:\t%s\tshell: %s\n",
  278.                         Curpw, pwd->pw_name, pwd->pw_shell);
  279.                 fflush(stdout);
  280.                 }
  281.             continue;
  282.         }
  283.         /*
  284.          * Try the user's login name
  285.          */
  286.         if (uandltry(pwd,pwd->pw_name))
  287.             continue;
  288.  
  289.         /*
  290.          * Try names from the gecos field
  291.          */
  292.         if (checkgecos) {
  293.             strcpy(guess, pwd->pw_gecos);
  294.             cp = guess;
  295.             if (*cp == '-') cp++;               /* special gecos field */
  296.             if ((cp2 = index(cp, ';')) != NULL)
  297.                 *cp2 = '\0';
  298.  
  299.             for (;;) {
  300.                 if ((cp2 = index(cp, ' ')) == NULL) {
  301.                     if (uandltry(pwd,cp))
  302.                         done++;
  303.                     break;
  304.                     }
  305.  
  306.                 *cp2 = '\0';
  307.  
  308.                 if (uandltry(pwd,cp)) {
  309.                     done++;
  310.                     break;
  311.                     }
  312.                 cp = ++cp2;
  313.                 }
  314.             }
  315.  
  316.         if (!done && Wordlist)
  317.         {
  318.             /*
  319.              * try the words in the wordlist
  320.              */
  321.             wordptr = wordarray;
  322.             while (endptr != wordptr)
  323.             {
  324.                 if (*wordptr == NULL)
  325.                     break;
  326.                 if (uandltry(pwd,*wordptr++))
  327.                 {
  328.                     done++;
  329.                     break;
  330.                 }
  331.             }
  332.         }
  333.         if (!done && singles) {
  334.             /*
  335.              * Try all single letters
  336.              * (try digits too .  --Seth)
  337.              */
  338.             guess[1] = '\0';
  339.             for (guess[0]='a'; guess[0] <= 'z'; guess[0]++)
  340.                 if (try(pwd,guess))
  341.                     break;
  342.             for (guess[0]='A'; guess[0] <= 'Z'; guess[0]++)
  343.                 if (try(pwd,guess))
  344.                     break;
  345.             for (guess[0]='0'; guess[0] <= '9'; guess[0]++)
  346.                 if (try(pwd,guess))
  347.                     break;
  348.             }
  349.     }
  350. }
  351.  
  352. /*
  353.  * Stands for "upper and lower" try.  Calls the "real" try, below,
  354.  * with the supplied version of the password, and with
  355.  * an upper and lowercase version of the password. If the user doesn't
  356.  * want to try upper and lower case then we just return after the one
  357.  * check.
  358. */
  359.  
  360. uandltry (pwd,guess)
  361. char *guess;
  362. struct passwd *pwd;
  363. {
  364.     register char *cp;
  365.     char buf[100];
  366.     int alllower, allupper;
  367.  
  368.     alllower = allupper = 1;
  369.  
  370.     if (try(pwd,guess) || (backwards && try(pwd,reverse(guess)))) return (1);
  371.  
  372.     if (!checkcase) return(0);
  373.  
  374.     strcpy (buf, guess);
  375.     cp = buf-1;
  376.     while (*++cp) {
  377.         if (isupper(*cp))
  378.             alllower = 0;
  379.         if (islower(*cp))
  380.             allupper = 0;
  381.         }
  382.  
  383.     if (!allupper) {
  384.         for ( cp=buf; *cp != '\0'; cp++)
  385.             if (islower (*cp))
  386.                 *cp += 'A' - 'a';
  387.  
  388.         if (try(pwd,buf) || (backwards && try(pwd,reverse(buf)))) return (1);
  389.         }
  390.  
  391.     if (!alllower) {
  392.         for ( cp = buf; *cp != '\0'; cp++)
  393.             if (isupper (*cp))
  394.                 *cp += 'a' - 'A';
  395.  
  396.         if (try(pwd,buf) || (backwards && try(pwd,reverse(buf)))) return (1);
  397.         }
  398.     return (0);
  399. }
  400.  
  401. try(pwd,guess)
  402. char *guess;
  403. register struct passwd *pwd;
  404. {
  405.     register char  *cp;
  406.     char   *crypt ();
  407.  
  408.     if (verbose) {
  409.         if (Curpw == NULL)
  410.             printf ("Trying \"%s\" on %s\n", guess, pwd -> pw_name);
  411.         else
  412.             printf ("%s -- Trying \"%s\" on %s\n", Curpw, guess,
  413.                 pwd -> pw_name);
  414.         fflush (stdout);
  415.         }
  416.     if (! guess || ! *guess) return(0);
  417.     cp = crypt (guess, pwd -> pw_passwd);
  418.     if (strcmp (cp, pwd -> pw_passwd))
  419.         return (0);
  420.     if (Curpw == NULL)
  421.             printf ("Problem: Guessed:\t%s\tshell: %s passwd: %s\n",
  422.                 pwd -> pw_name, pwd -> pw_shell, guess);
  423.     else
  424.             printf ("%s -- Problem: Guessed:\t%s\tshell: %s passwd: %s\n",
  425.                 Curpw, pwd -> pw_name, pwd -> pw_shell, guess);
  426.     fflush (stdout);
  427.     return (1);
  428. }
  429. /* end of PW guessing program */
  430.  
  431. #define MAXUID 0x7fff   /* added by tonyb 12/29/83 */
  432.                         /* altered to a reasonable number - mae 8/20/84 */
  433.  
  434. /*
  435.  * Add a parameter to "setpwent" so I can override the file name.
  436.  */
  437.  
  438. setpwent(file)
  439. char *file;
  440. {
  441.         if ((pwf = fopen(file,"r")) == NULL)
  442.             return(1);
  443.         return(0);
  444. }
  445.  
  446. endpwent()
  447.  
  448. {
  449.     fclose(pwf);
  450.     pwf = NULL;
  451. }
  452.  
  453. char *
  454. pwskip(p)
  455. register char *p;
  456. {
  457.         while(*p && *p != ':' && *p != '\n')
  458.                 ++p;
  459.         if(*p == '\n')
  460.                 *p = '\0';
  461.         else if(*p)
  462.                 *p++ = '\0';
  463.         return(p);
  464. }
  465.  
  466. struct passwd *
  467. getpwent()
  468. {
  469.         register char *p;
  470.         long    x;
  471.  
  472.         if(pwf == NULL)
  473.             if (setpwent(PASSWD)) {
  474.                 perror(PASSWD);
  475.                 return(NULL);
  476.                 }
  477.         p = fgets(line, BUFSIZ, pwf);
  478.         if(p == NULL)
  479.                 return(0);
  480.         passwd.pw_name = p;
  481.         p = pwskip(p);
  482.         passwd.pw_passwd = p;
  483.         p = pwskip(p);
  484.         x = atol(p);
  485.         passwd.pw_uid = (x < 0 || x > MAXUID)? (MAXUID+1): x;
  486.         p = pwskip(p);
  487.         x = atol(p);
  488.         passwd.pw_gid = (x < 0 || x > MAXUID)? (MAXUID+1): x;
  489.         passwd.pw_comment = EMPTY;
  490.         p = pwskip(p);
  491.         passwd.pw_gecos = p;
  492.         p = pwskip(p);
  493.         passwd.pw_dir = p;
  494.         p = pwskip(p);
  495.         passwd.pw_shell = p;
  496.         (void) pwskip(p);
  497.  
  498.         p = passwd.pw_passwd;
  499. /*      while(*p && *p != ',')
  500.                 p++;
  501.         if(*p)
  502.                 *p++ = '\0';
  503.         passwd.pw_age = p;
  504. */
  505.         return(&passwd);
  506.  
  507. }
  508.  
  509.  
  510. /*
  511.  * reverse a string
  512.  */
  513. char *reverse(str)
  514. char *str;
  515.  
  516. {
  517.     register char *ptr;
  518.     register int len;
  519.     char        *malloc();
  520.  
  521.     if ((ptr = malloc((len = strlen(str))+1)) == NULL)
  522.         return(NULL);
  523.     ptr += len;
  524.     *ptr = '\0';
  525.     while (*str && (*--ptr = *str++))
  526.         ;
  527.     return(ptr);
  528. }
  529.  
  530.  
  531. - - - - - - - - - - - - - - - - - cut here - - - - - - - - - - - - - - - - - - -
  532. 
  533. Downloaded From P-80 International Information Systems 304-744-2253 12yrs+
  534.