        ..:-={{National Security Center}}=-:..
    X-TREME & TECHNOTRONIC Security Collaboration Project
http://www.technotronic.com  -=(c)=-  http://www.x-treme.abyss.com


#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <alloc.h>
#include <time.h>
#include <bios.h>

#define MAX_WPWD_LEN  10
#define MAX_EPWD_LEN  15

extern char *crypt(register const char *key, register const char *setting);
int   ProcessPasswdFile(char *efn);
void   Back2DOS(int code, char *txt);
void   DisplayStatus(char *wpwd);
void   help(void);

unsigned long wc  =0;       // Word counter
unsigned int eacct=0;       // Number of accounts (encrypted passwords)
unsigned int fpwd =0;       // Number of cracked passwords
time_t tm1, tm2;            // Time counters
FILE   *ofp;                // Output file pointer
char   *ofn;                // Output file name
char   far **dptr;          // Table of passwords


void main(int argc, char *argv[]) {
   char    wpwd[MAX_WPWD_LEN];    // Buffer for dict. words
   char    epwd[MAX_EPWD_LEN];    // Buffer for encrypted passwords
   char   far *ppwd;              // Current password to encrypt
   char   *wfn, *efn;             // Dictionary and Passwords' filenames
   FILE   *wfp, *efp;             // Dictionary and Passwords' file pointers
   int    wi,   ei;               // Flags for EOF
   char    fastmode;              // Flag for fastmode (1=load pwds in memory)
   unsigned    more;              // fastmode=0: Flag for more passwords
                                  // fastmode=1: Index for table of passwords
   int    stw=0;                  // Flag for starting word
   int    v=0;                    // Flag for verbose
   char    stword[MAX_WPWD_LEN];  // Starting word to check in dictionary
   char    salt[3]="ÍÍ";          // Salt keys
   long    floc;                  // File pointer offset, to adjust st.word
   char   *rpwd;                  // Resulting enc.password from crypt()
   char   *parm;                  // Pointer to command line options
   char    ch;                    // Used by bioskey()
   int    cp;                     // Parameter counter

   cputs("ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»\r\n");
   cputs("º [XiT] v2.0 386 º (C) Copyright 1993, 1994  XCrypt Productions\r\n");
   cputs("ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ¼ by Roche'Crypt / Feb.94\r\n\n");


   /*   ****************** PROCESS COMMAND LINE PARAMETERS ***************** */

   if(argc<4 || argc>6) help();          // Wrong number of parameters
   if(argc>=5) {                         // Process command line options
      cp = 4;
      do {
         parm = argv[cp];                // Process next parameter
         if(parm[0]=='-')   parm++;      // Ignore dash charachter
         switch(parm[0]) {
            case 'S' :                   // STARTING WORD
               _fstrcpy(stword, parm+1); // Obtain starting word
               _fstrcat(stword,"\n");    // Speeds up st.word' searching process
               stw=1;                    // Set flag
               break;
            case 'v' :                   // VERBOSE
               if(!parm[1])   v = 1;
               else            help();
               break;
            default : help();            // WRONG SWITCH
         }
      } while(++cp<argc);                // Go for next parameter (if any)
   }

   /*   *************************** OPEN FILES **************************** */

   efn=strupr(argv[2]);
   fastmode = ProcessPasswdFile(efn);   // Analyze Password file

   wfn=strupr(argv[1]);                 // Open Dictionary file
   if((wfp=fopen(wfn,"r"))==NULL) {
      perror(wfn); exit(-3);
   }

   if(!fastmode){                        // If table is not being used
      if((efp=fopen(efn,"r"))==NULL) {   // open Password file
         perror(efn); exit(-3);
      }
   }

   ofn=strupr(argv[3]);                  // Create output file
   if((ofp=fopen(ofn,"w"))==NULL) {
      perror(ofn); exit(-3);
   }
   fclose(ofp);

   /*   ******************* GO TO SELECTED STARTING PASSWORD **************** */

   if(stw) {                           // Move file pointer to starting-word
      stw=0;                           // Re-use 'stw' as a "found" flag
      while(!feof(wfp) && (!stw)) {
         fgets(wpwd, MAX_WPWD_LEN, wfp);
         if(!strcmp(wpwd, stword))   stw++;   // Found! Exit loop
      }
      if(feof(wfp)) {                         // EOF was reached.
         stword[strlen(stword)-1] = '\0';     // Eliminate CR character
         printf("Word '%s' is not in the dictionary %s.",stword,wfn);
         Back2DOS(-2,"");
      }
      floc = ftell(wfp) - (strlen(wpwd)+1);   // Calculate starting offset
      fseek(wfp,floc,SEEK_SET);               // Readjust offset file pointer
   }

   /************************************************************************/
   /*                            *** MAIN  LOOP ***                           */
   /************************************************************************/

   puts("Cracking... (press SPACE for status, ESC to abort)");
   tm1 = time(NULL);                           // Get beginning time
   wi=0;                                       // Reset EOF flag
   do {
      fgets(wpwd, MAX_WPWD_LEN, wfp);          // Get word in dictionary
      if(!feof(wfp)) {                         // End of file not reached yet
         wpwd[strlen(wpwd)-1] = '\0';          // Eliminate CR character
         if(v) printf("Trying %s\n\r",wpwd);   // Echo if verbose
         salt[0]=0xff;                         // Reset salt
         if(fastmode) more = eacct-1;          // Start checking LAST enc.password
         else          rewind(efp);            // Seek from beginning of enc.pwd file
         ei=0;                                 // Reset EOF flag
         wc++;                                 // Increment word counter
         do {
            if(fastmode)
               ppwd = dptr[more];              // Assign next enc.pwd to 'ppwd'
            else {
               fgets(epwd, MAX_EPWD_LEN, efp); // Get encrypted password
               epwd[strlen(epwd)-1] = '\0';    // Eliminate CR character
               ppwd = epwd;                    // Assign next pwd to 'ppwd'
               if(!feof(efp)) more=1; else more=0;
            }
            if(more<65535) {                   // Valid encripted password
               if(salt[0]!=ppwd[0] || salt[1]!=ppwd[1]) { // Avoid encryption
                  rpwd = crypt(wpwd, ppwd);  // of words that use the same salt
                  salt[0]=ppwd[0];           // keys. NOTE: The enc.pwd file
                  salt[1]=ppwd[1];           // must be sorted in advance!!
               }
               if(rpwd[2]==ppwd[2])            // Ugly coding, but much
                  if(rpwd[3]==ppwd[3])         // faster than just a plain
                     if(rpwd[4]==ppwd[4])      // strcmp() call. Augh!
                        if(rpwd[5]==ppwd[5])
                  if (!strcmp(rpwd+6,ppwd+6)) {   // PASSWORD FOUND!
                     printf("'%s' deCrypts as '%s'\n",ppwd,wpwd);
                     if((ofp=fopen(ofn,"a"))==NULL) { perror(ofn); exit(-3); }
                     fprintf(ofp, "'%s' deCrypts as '%s'\n",ppwd,wpwd);
                     fclose(ofp);
                     fpwd++;
                     //   ei=-1;      // Enable ONLY if you KNOW a password
                                      // can't occur TWICE in the pwd file.
                  }
               more--;
            }
            else ei=-1;
         } while(ei>=0);
         if(bioskey(1)) {      // Check if a key has been pressed
            ch=getch();
            switch(ch) {
               case ' ' :               // 'SPACE'
                  if(v)   getch();        // When '-v' is active: PAUSE
                  else                  // Otherwise: SHOW STATUS
                     DisplayStatus(wpwd);
                  break;
               case 0x1b: Back2DOS(-1,wpwd); break;   // 'ESC'   ABORT
            }
         }
      }
      else wi=-1;
   } while(wi>=0);
   Back2DOS(0,"");
}

int ProcessPasswdFile(char *efn) {
   char   epwd[MAX_EPWD_LEN];  // Buffer for a single encrypted password
   unsigned int pc=0;         // Number of accounts
   char   far *tptr;            // Temporary pointer (several uses)
   int   is_eof;               // Check for end of file
   FILE   *efp;                  // Dictionary and Passwords file pointers

   if((efp=fopen(efn,"r"))==NULL) { perror(efn); exit(-3); }
   cprintf("Counting accounts in %s...\r\n",efn);

   while(!feof(efp)) {                  // Count how many lines (passwords)
      fgets(epwd, MAX_EPWD_LEN, efp);   // are in the password file
      if(strlen(epwd)==14)
         pc++;
   }
   eacct = pc;                         // Assign result to global variable
   cprintf("\r\n%s contains %u passwords\r\n",efn, pc);

   // Check if there is enough memory by "trial and error"
   // Sometimes farcoreleft() can screw up...
   if((tptr=(char far*)farmalloc((unsigned long)MAX_EPWD_LEN*pc)) == NULL) {
      // Couldn't allocate memory for all the passwords
      cprintf("I don't have enough memory to load all accounts in memory.\r\n");
      cprintf("I'd need %lu bytes in order to do that\r\n",(unsigned long)MAX_EPWD_LEN*pc);
      cprintf("Free memory: %lu\r\n",farcoreleft());
      cprintf("The slower method (XiT 1.0) will be used...\r\n");
      fclose(efp);                     // Close the password file, and
      return(0);                        // return (0=fastmode will NOT be used)
   }
   farfree(tptr);                        // Free the "trial and error" memory
   if( (dptr=(char far **)farmalloc(sizeof(char far*)*pc)) == NULL) {
      cputs("Weird  error #03...\r\n"); // Weird because I can't think
      exit(-5);                         // this could ever happen, unless
   }                                     // you're multitasking using a
                                        // crappy memory manager.

   rewind(efp);                         // Go to beginning of file
   cprintf("Loading accounts...\r\n");
   is_eof=pc=0;                         // Set flag and counter
   do {
      fgets(epwd, MAX_EPWD_LEN, efp);   // Read password
      if(!feof(efp)) {                  // Still data in the file
         if(strlen(epwd)==14) {         // Correct password length? If so...
                                        // Allocate memory for the password
            if((tptr=(char far*)farmalloc(MAX_EPWD_LEN)) == NULL) {
               cprintf("\r\nError allocating memory for element %d\r\n",pc);
               exit(-5);
            }
            dptr[pc]=tptr;              // Assign indexed pointer to the buffer
            epwd[strlen(epwd)-1] = '\0';// Eliminate '\n'
            _fmemcpy(tptr ,epwd,15);    // Copy the password in the buffer
            pc++;                       // Increment counter
            if(bioskey(1)) {            // Key pressed?
               if(getch()==0x1b) {      // Was it ESCAPE?
                  puts("\r\nAborting!");// Then abort,
                  fcloseall();          // close all files
                  exit(-4);             // and exit
               }
            }
         }
      }
      else is_eof=-1;                   // No more data in the file
   } while(is_eof>=0);
   fclose(efp);                         // Close the password file
   return(1);                           // And return (1=fastmode will be used)
}

void DisplayStatus(char *word) {
   float dt;

   tm2 = time(NULL);
   if(!(dt=difftime(tm2, tm1))) dt=1;

   printf("v: %u  c: %lu  s: %.0f  c/s: %.0f w: %s\n",
         fpwd, (unsigned long)eacct*wc, dt, (float)eacct*wc/dt,word);
}

/* EXIT ROUTINE */ // A better one coming up sometime...
void Back2DOS(int code, char *txt) {
   char msg_xitabort[]="\n[XiT] aborted while processing the word '%s'!!!\n";
   char msg_totwords[]="Total number of words processed in this session: %lu\n";
   char msg_totaccts[]="Total number of accounts                       : %u\n";
   char msg_totencrp[]="Total number of ecryptions made in this sesion : %lu\n";
   char msg_totltime[]="Total time elapsed  : %.0f seconds\n";
   char msg_encsecnd[]="Encryptions/second  : %.0f\n";
   char msg_fndpswds[]="Total number of passwords found: %u\n";
   float difft;
   float encsc;

   tm2 = time(NULL);
   difft = difftime(tm2, tm1);
   encsc = (float)eacct*wc/difft;
   if(code>-2) {
      if((ofp=fopen(ofn,"a"))==NULL) { perror(ofn); exit(-3); }
      putchar('\n');
      fputc('\n',ofp);
      if(code<0) {
         fprintf(ofp,msg_xitabort ,txt);
         printf(msg_xitabort,txt);
      }
      else {
         putchar('\n');
         fputc('\n',ofp);
      }
      fprintf(ofp, msg_totwords,wc);         printf(msg_totwords,wc);
      fprintf(ofp, msg_totaccts,eacct);      printf(msg_totaccts,eacct);
      fprintf(ofp, msg_totencrp,(unsigned long)eacct*wc);   printf(msg_totencrp,(unsigned long)eacct*wc);
      fprintf(ofp, msg_totltime,difft);      printf(msg_totltime,difft);
      fprintf(ofp, msg_encsecnd,encsc);      printf(msg_encsecnd,encsc);
      fprintf(ofp, msg_fndpswds,fpwd);         printf(msg_fndpswds,fpwd);
   }
   fcloseall();
   exit(code);
}

void help(void) {
   puts("\nUsage: XIT2 <dict_filename> <epwd_filename> <ofilename> [options]\n");
   puts("<dict_filename>     : Name of the file containing words (dictionary).");
   puts("<XiT/ECRY_filename> : Name of the (sorted) file containing encrypted passwords.");
   puts("<ofilename>         : Output filename\n");
   puts("[options]");
   puts("    -Sxxxxxxxx      : First word to check in dictionary.");
   puts("    -v              : Display verbose information.\n");
   exit(-1);
}

