home *** CD-ROM | disk | FTP | other *** search
- /*
- VERSION: 0.01 by Sudog Feb '97
- So what if I have a non-standard version?
- */
-
- #include <stdio.h>
- #include <string.h>
- #ifdef AMIGA
- #include <dos/dos.h>
- #include <exec/memory.h>
- #endif
-
- /* duh */
- #define TRUE 1 /* generic true/false because I don't want to waste time */
- #define FALSE 0 /* including exec/types.h so there. */
-
- /* the following for passwd structure traversal */
- #define USER 1 /* at user field in line */
- #define PASSWD 2 /* at passwd field in passwd entry */
- #define SAVE 3 /* after storing user & password, save it */
- #define DONE 4 /* and after saving it for later, skip over rest */
-
- /* maximum values for internal passwd structure */
- #define NAMESIZE 15 /* for struct passwd and for parsepass routine */
- #define SALTSIZE 3
- #define PASSWDSIZE 14
- #define WORDSIZE 20 /* maximum size of password in command line or password in dictfile */
-
- /* values for return() from getnextdict */
- #define DICT_DONE 1 /* dictionary has been exhausted */
- #define DICT_ERROR 2 /* dictionary file is corrupt or something else just as fucked up */
-
-
- #define SEPARATOR ':' /* passwd field separator.. : for unix, | for AmiTCP */
-
- /*
- ** This is merely a small affectation because I am sometimes curious
- ** to have regular status updates.. uncomment this #define if you like
- ** something happening everytime the dictionary file has been entirely
- ** searched through..
- #define ANIMSIZE 4
- */
-
- #ifdef AMIGA
- int CXBRK(void) {return(0);} /* sorry user we're gonna make SURE that you can't */
- int chkabort(void) {return(0);} /* mess us up without giving us chance to clean up */
- #endif
-
- struct passwd
- {
- char name[NAMESIZE];
- char salt[SALTSIZE];
- char password[PASSWDSIZE];
- struct passwd *nextitem;
- struct passwd *lastitem;
- short cracked;
- };
-
- FILE *dictionary; /* global because we want getnextdict() to have an open-and-ready */
- /* file handle from which to read words from the dictionary when in */
- /* dictionary mode */
-
- char *crypt(char *, char *);
- struct passwd *parsepass(char *);
- void cleanup(struct passwd *);
- void log(char *, char *, char *);
- long getnextdict(char *, char *);
-
- int main(int argc, char *argv[])
- {
- unsigned int counter;
- unsigned int c=FALSE;
- unsigned char commandword[WORDSIZE];
-
- struct passwd *firstitem=NULL;
- struct passwd *currentitem=NULL;
-
- long status; /* for returns from various functions.. scratchpad */
-
- #ifdef ANIMSIZE
- char anim[] = "\\|/-";
- int animcounter = 0;
- #endif
-
- #ifdef AMIGA
- long actualsigs;
- long waitmask = SIGBREAKF_CTRL_C;
- #endif
-
- dictionary=NULL; /* i don't want to do this more than once */
-
- /* do some command line argument parsing */
- /* this is hereby hard-coded.*/
- printf("sizeof: %d\n", sizeof(struct passwd));
- exit(10);
- for (counter = 0; counter < argc; counter++)
- {
- if (argv[counter][0] == '-')
- {
- /*
- ** The following accepts the - as an indicator, and then it copies the
- ** rest of this particular argument as a word to search a passwd file for.
- ** The reason this isn't hard-coded as argv[2] is for future expandability--
- ** sort of a functional work-in-progress.
- */
- c = TRUE;
- for (counter=1; counter < WORDSIZE; counter++)
- {
- commandword[counter-1] = argv[2][counter];
- if (commandword[counter-1] == 0) break;
- }
- break;
- }
- if (argv[counter][0] == '?')
- {
- /*
- ** I could never really see the harm in goto statements within programs.
- ** "A Book On C" says that goto statements are bad programming pratice.
- ** Whatever..
- */
- usage:
- printf("Usage: %s <passwdfile> -<word> [outputfile]\n", argv[0]);
- printf(" %s <passwdfile> <dictfile> [outputfile]\n", argv[0]);
- printf(" %s ?\n", argv[0]);
- printf("This program written in Feb, '97 by sudog.\n");
- printf("So there.\n");
- exit(0);
- }
- }
-
- counter = 0;
-
- if (argc > 2)
- {
- if (firstitem = parsepass(argv[1]))
- {
- currentitem = firstitem;
- /*
- ** This section deals with a command-line supplied password.
- */
- if (c)
- {
- while (currentitem != NULL)
- {
- if (!strcmp(currentitem->password, crypt(commandword, currentitem->salt)))
- {
- printf("%s %s\n", currentitem->name, commandword);
- if (argc > 3)
- {
- log(argv[3], currentitem->name, commandword);
- }
- }
- /* This section is amiga-only--it allows the user to break the program,
- ** CLEANLY! (Ie: We trap SIGBREAKF_CTRL_C and clean up the memory we allocated.)
- */
- #ifdef AMIGA
- actualsigs = CheckSignal(waitmask);
- if (actualsigs)
- {
- cleanup(firstitem);
- }
- #endif
- currentitem = currentitem->nextitem;
- }
- }
- /*
- ** This section deals with a dictionary file!
- ** TODO:
- ** Add place holder so a system crash can be survived and iterations can
- ** continue from last point... VERY cool. let's do som background cracking!
- */
- /*
- ** First priority is to check the entire dictionary against the
- ** current passwd entry. It's MUCH MUCH INCREDIBLY FASTER then.
- */
- else
- {
- currentitem=firstitem;
- /*
- ** A simple while loop to search an entire dictionary on a single
- ** password entry. Trust me, this saves a SHITLOAD of time, since
- ** for each new salt which is used, crypt() has to re-set all its
- ** damned data structure and shit. VERY crappy. Otherwise it zips
- ** through things in like, 500 keys per second. At least, on my
- ** machine, compared with maybe 10 keys/sec otherwise.
- */
- while ( currentitem != NULL )
- {
- while (((status=getnextdict(commandword, argv[2])) != DICT_DONE) && (status != DICT_ERROR))
- {
- if (!currentitem->cracked)
- {
- if (!strcmp(currentitem->password, crypt(commandword, currentitem->salt)))
- {
- printf("%s %s\n", currentitem->name, commandword);
- currentitem->cracked = TRUE;
- if (argc > 3)
- {
- log(argv[3], currentitem->name, commandword);
- }
- }
- }
- #ifdef AMIGA
- actualsigs = CheckSignal(waitmask);
- if (actualsigs)
- {
- cleanup(firstitem);
- }
- #endif
- }
- if (status == DICT_ERROR)
- {
- printf("Error: Unable to access dictionary file..\n");
- break;
- }
- if (status == DICT_DONE)
- {
- #ifdef ANIMSIZE
- printf("%c%c", anim[animcounter], 8);
- animcounter++;
- if (animcounter >= ANIMSIZE)
- {
- animcounter = 0;
- }
- #endif
- }
- currentitem=currentitem->nextitem;
- }
- }
- }
- else
- {
- printf("Error in parsing password file.\n");
- }
- }
- else
- {
- printf("Error. You don't have a clue. Here. Have one.\n");
- goto usage;
- }
-
- cleanup(firstitem);
-
- }
-
- /*
- ** In order that we get dictionary words, we have to
- ** return words in cyclical order. Ie: We have to
- ** get the first word after we got the last word.
- ** So we aren't returning any end-of-file conditions.
- ** We're just returning words unless an error
- ** condition exists.
- */
-
- long getnextdict(char *commandword, char *filename)
- {
- long counter=0;
- int gotone=FALSE;
- char temp;
-
- if (commandword == NULL && filename == NULL)
- {
- if (dictionary)
- {
- fclose(dictionary);
- }
- return(0);
- }
- if (!dictionary)
- {
- if (!(dictionary = fopen(filename, "r")))
- {
- return(DICT_ERROR);
- }
- }
- if (dictionary)
- {
- while ( 1 )
- {
- temp = fgetc(dictionary);
- if (feof(dictionary))
- {
- if (gotone)
- {
- commandword[counter] = 0;
- return(0);
- }
- else
- {
- /*
- ** We're going to re-use the dictionary file again and again and
- ** again until we're TOLD to close it with getnextdict(NULL, NULL);
- */
- rewind(dictionary);
- return(DICT_DONE);
- }
- }
- else if (temp > 31 && temp < 127)
- {
- if (gotone == FALSE)
- {
- gotone = TRUE;
- }
- if (counter < WORDSIZE)
- {
- commandword[counter++] = temp;
- }
- }
- else
- {
- if (gotone == TRUE)
- {
- commandword[counter] = 0;
- return(0);
- }
- }
- } /* end of while loop */
- }
- }
-
- /*
- ** Excellently enough, calloc() remembers how big the memory chunks
- ** it allocated are, so a call to free() doesn't have to specify anything
- ** but the pointer!! ANSI-C rules!
- */
- void cleanup(struct passwd *firstitem)
- {
- struct passwd *currentitem;
- while (firstitem != NULL)
- {
- currentitem = firstitem->nextitem;
- free(firstitem);
- firstitem = currentitem;
- }
- getnextdict(NULL, NULL);
- exit(0);
- }
-
- void log (char *filename, char *username, char *password)
- {
- FILE *output;
-
- if (output = fopen(filename, "a"))
- {
- fprintf(output, "%s %s\n", username, password);
- fclose(output);
- }
- else
- {
- printf("Error: Unable to open output file!\n");
- }
- }
-
- /*
- ** This routine opens a passwd file, and parses it according to the
- ** following rules:
- **
- ** {user}{separator}{passwd field entry}{separator}
- ** There MUST be two separators per line.. the separator should be defined as
- ** SEPARATOR in the preprocessor.. usually ':' for UNIX-style passwd files.
- */
-
- /*
- ** We use a state variable to define which part of the passwd entry we
- ** are currently processing.. it's more used as a sort of directive..
- ** if it's USER, store it in the user field of the struct passwd..
- ** etc etc..
- */
- struct passwd *parsepass(char *filename)
- {
- struct passwd *currentitem=NULL;
- struct passwd *firstitem=NULL;
- struct passwd *floatitem=NULL;
-
- unsigned int counter = 0;
- unsigned int state; /* the part of the field we're parsing right now */
- unsigned int ff = FALSE;
-
- FILE *input;
- char temp;
-
-
- if (input = fopen(filename, "r"))
- {
- while ( 1 )
- {
- temp = fgetc(input);
- if (feof(input)) break;
- if (temp > 31 && temp < 127)
- {
- /*
- ** ff here is being used as a sort of flip-flop switch. It is used for
- ** QUICKLY skipping over non-printable characters.
- */
- if (ff == FALSE)
- {
- ff = TRUE;
- if (!(floatitem = (struct passwd *)calloc(1, sizeof(struct passwd))))
- {
- printf("Error: Unable to allocate %d bytes. Exiting..\n", sizeof(struct passwd));
- cleanup(firstitem);
- }
- state = USER;
- }
- if (state == USER)
- {
- if (temp != SEPARATOR && counter < NAMESIZE)
- {
- floatitem->name[counter++] = temp;
- }
- if (temp == SEPARATOR)
- {
- state = PASSWD;
- counter = 0;
- }
- }
- else if (state == PASSWD)
- {
- if (temp != SEPARATOR && counter < PASSWDSIZE)
- {
- if (counter < 2)
- {
- floatitem->salt[counter] = temp;
- }
- floatitem->password[counter++] = temp;
- }
- if (temp == SEPARATOR)
- {
- state = SAVE;
- counter = 0;
- }
- }
- if (state == SAVE)
- {
- if (!firstitem)
- {
- firstitem=floatitem;
- }
- else
- {
- currentitem=firstitem;
- /*
- ** We are using a doubly-linked list to store our list of passwd
- ** entries.. doubly-linked lists are cool! buhuhuhuhuhuhuhuhuh hehe
- */
- while ( 1 )
- {
- if ((strcmp(floatitem->salt, currentitem->salt)) <= 0)
- {
- floatitem->nextitem=currentitem;
- floatitem->lastitem=currentitem->lastitem;
- currentitem->lastitem = floatitem;
- if (floatitem->lastitem != NULL)
- {
- floatitem->lastitem->nextitem = floatitem;
- }
- else
- {
- firstitem = floatitem;
- }
- break;
- }
- if (currentitem->nextitem == NULL)
- {
- currentitem->nextitem = floatitem;
- floatitem->lastitem = currentitem;
- break;
- }
- currentitem=currentitem->nextitem;
- }
- }
- state = DONE;
- }
- }
- else
- {
- state = USER;
- ff = FALSE;
- }
- }
- fclose(input);
- }
- else
- {
- printf("Error: Unable to open specified passwd file.\n");
- }
- return(firstitem);
- }
-