/*
 * BiffSocko        apc.c (Another Password Cracker)            9/26/98
 *
 * usage: apc <passwd file> <wordlist> [outfile]
 * the password file MUST be in the form of a /etc/password
 * or /etc/shadow file where ":" is the delimeter and the 
 * password is in the second field.  
 * the wordlist must be one word per line.
 *
 * (c) 1998 BiffSocko
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, for NON COMMERCIAL USE are permitted provided that:
 * (1) source code distributions retain the above copyright notice and this
 * paragraph in its entirety, and (2) distributions including binary code
 * include the above copyright notice and this paragraph in its entirety in
 * the documentation or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#include <stdio.h>
#include <strings.h>
#include <sys/types.h>
#include <unistd.h>

#define MAX 1024

int main (int argc, char *argv[])
{
        /* define some variables */
FILE *WordList=NULL;            /* wordlist file descriptor */
FILE *PassFile=NULL;            /* passwd file file descriptor */
FILE *Outfile=NULL;             /* Output file descriptor */
char Salt[3];                   /* salt string */
char Word[ MAX];                /* the unencrypted word */
char *encrypted;                /* the encrypted word */
char PassString[ MAX];          /* String from the passwd file */
char Password[ MAX];            /* the Password String */
int i=0;                        /* counter */
int j=0;                        /* counter */
int len=0;                      /* the lenth of word */

system("clear");
printf("\t\t    apc (Another Password Cracker)\n");
printf("UNIX Password Cracker (C) All rights reserved. Copyright BiffSocko 1998\n\n");
        /*
         * check for usage and open the files 
         */
        if((argc < 3) || (argc > 4)){
                fprintf(stderr, "usage: %s <passwd file> <wordlist> [output file]\n", 
                        argv[0]);       
                exit( -1);      /* bye looser*/
        }


        if(argc == 4){
                if(!(Outfile=fopen(argv[3], "w+"))){
                        fprintf(stderr, "error opening %s to write\n", argv[3]);
                        exit( -1);
                }
        }
        else 
                Outfile = stdout;
        

        if(!(PassFile=fopen(argv[1], "r"))){
                fprintf(stderr, "error opening %s for reading\n",argv[1]);
                fclose(Outfile);
                exit( -1);      /* bye looser */
        }

        if(!(WordList=fopen(argv[2], "r"))){
                fprintf(stderr, "error opening %s for reading\n");
                fclose(Outfile);
                fclose(PassFile);
                exit( -1);      /* bye looser */
        }

        /*
         * start traversing through the passwd file
         */
        while(fgets(PassString, MAX, PassFile)){
                printf("working on %s", PassString);
                /* 
                 * set up variables 
                 */
                Salt[0] = '\0';
                Password[0] = '\0';
                Word[0] = '\0';
                i = 0;
                j = 0;

                /* 
                 * get to the second field in the pass string 
                 */
                while(PassString[i] != ':')
                        i++;

                i++;

                /*
                 * in case of no passwrd in the password field
                 * yes i know that this means users like "lp"
                 * but .. they got no passwds in the file anyway
                 */
                if((PassString[i] == ':') ||  (PassString[i] == '*')){
                        fprintf(Outfile, "%s\thas NO PASSWORD\n",PassString);
                        fflush(Outfile);
                        continue;
                }
 
                /* 
                 * get the users password in a string
                 */
                while(PassString[i] != ':'){
                        Password[j]=PassString[i];
                        i++;
                        j++;
                }

                Password[j] = '\0';
                
                Salt[0] = Password[0];
                Salt[1] = Password[1];
                Salt[2] = '\0';
        
                /* 
                 * ok, now start traversing through the
                 * word list and comparing
                 * depending on the size of your word list
                 * this is gonna take a while
                 */
                while(fgets(Word, MAX, WordList)){
                        len=strlen(Word);
                        Word[len -1] = '\0';
                        encrypted = (char *) crypt(Word, Salt);
                        if((strcmp(Password, encrypted)) == 0){
                                /* woo hoo got one */
                                fprintf(Outfile, "%s \thas %s as a password\n\n"
                                        ,PassString, Word); 
                                fflush(Outfile);
                                break;
                        }
                }

                /* reset for next traversial */
                rewind(WordList);
                PassString[0] = '\0';
        }
        
        /* clean up & exit */
        if(argc == 4)
                fclose(Outfile);
        fclose(WordList);
        fclose(PassFile);
        exit( 0);
}
