CRACKING OF ENCRYPT-IT FOR WINDOWS

by

CASIMIR

Part C

Other Essays by Casimir
  • Cracking of Crypt-o-Text v1.21 & v1.24
  • Correspondence From Casimir On Reversing Turbo Encrypto
  • Cracking of WinXFiles
  • The Cracking of File Locker
  • The Cracking of Keeper
  • The Cracking of Gregory Braun's Crypto v3.5
  • The Cracking of SecurityPlus!
  • The Cracking of MasterKey v1.02/1.05
  • Software by MaeDae Enterprises
    (You might need to use FTP Search to find the software.)

    This file presents cracking procedure for both proprietary algorithms found in this software:

    Source code (C) for a cracker is also provided.


    Map of the essay:
    Introduction
    Strategy
    PART A - REVERSING OF EIW 
    	1. Warm up
    	2. What's going on with my input?
                2.1. Task 1: Computation of Block_size 
                2.2. Task 2: Permutations in encrypted file 
    	3. Building of Sum_vector 
    	4. Making of Xor_vector 
    	5. Making of Cmp_vector 
    	6. The Ultimate CMP 
    PART B - ANALYSIS AND BREAKING OF EIW 
    	1. Questions/answers
    	2. Mimic of EIW
    	3. The 3 solving methods 
                3.1. High speed solving method
                3.2. Medium speed solving method
                3.3. Low speed solving method
    PART C - SOURCE FOR CRACKER 
    
    

    PART C - SOURCE FOR CRACKER

    
    
    
    OK, enough blah-blah, compile C listing below into DOS executable CRACKEIW.EXE, and enjoy!
    
    ********************************************************************************
    #include <stdio.h>
    #include <io.h>
    #include <fcntl.h>
    #include <errno.h>
    #include <dir.h>
    #include <string.h>
    #include <dos.h>
    #include <alloc.h>
    #include <malloc.h>
    #include <stdlib.h>
    #include <time.h>
    #include <conio.h>
    #include <math.h>
    
    // PROTOTYPES
    
    void Hi_folks(void);
    int Get_target(void);
    void Chrono(void);
    void Wait_key();
    int Min(int,int);
    int Max(int,int);
    void Print_pwd(int,int *,time_t);
    void Euclid(int,int **);
    int Odd(int);
    void Update_pwd(int,int,int **,int **);
    void Fill_buffer(int,char **,int);
    int Shift(int,int,int ***,int *);
    void Set_free_vars(int,int,int,int **,int *,int ***,int ***,int **);
    void Set_other_vars(int,int,int,int,int,int **,int *,int ***,int ***,int **);
    int Check_eqs(int,int,int,int,int **,int *,int **,int ***,int **);
    void Order_vars(int,int **);
    int Calc_free_nb(int *,int,int *,int *);
    void Extract(unsigned char *,int,int,int,int **,int **,int *,int **,int **);
    int Check_block_size(int,int,int *);
    int Check_init_12(int,int,int *);
    int Check_tail_0(int,int,int *,int *);
    int Speed_high(int,int,int,int,int *,int **);
    int Check_char_0(int,int,int *);
    int Speed_medium(int,int,int,int,int *,int **);
    int Check_init_12_pwd(int,int,int *);
    int Check_pwd(int,int *,int *);
    int Can_break(char *,int *);
    void Show_progress(int,int,int);
    int Speed_low(int,int,int,int,int *,int *,int **,int **,int **,int **,
    	      int ***,int ***,int ***);
    
    main()
    {
    const int buf_size=1000;
    const int name_size=12;
    const int head_size=8;
    int soft_len_max;  // max pwd'lenght allowed by EIW (40 or 123 characters)
    int fn;                     //encrypted file'handle
    int pwd_len,pwd_len_min,pwd_len_max; // pwd_len_min<=pwd_len<=pwd_len_max
    int char_0;   // 13ψ character in permuted file
    int block_size;  //0x02<=block_size<=0x11
    int tail_0_nb; //number of "0" (0x00) AFTER password in Tail
    int i,found;
    time_t time_start,t; // chrono
    
    char *Buffer; // storage for beginning of encrypted file
    int *Pwd;
    int *Header,*Name_enc,*Pwd_enc,*Tail; //arrays filled with cypher file
    int *Order,*Sum,*Char_0_bin;
    int **Carry,**Pwd_enc_bin,**Pwd_bin;    //*_bin : binary variables
    
    Hi_folks();
    fn=Get_target();
    Fill_buffer(fn,&Buffer,buf_size);
    if(!Can_break(Buffer,&soft_len_max)) {Wait_key(); exit(0);}
    //we search the whole range
    pwd_len_min=5;
    pwd_len_max=soft_len_max;
    time_start=time(NULL); //start chrono
    printf("\nPROGRESS |");
    
    Pwd=(int *)malloc(sizeof(int)*soft_len_max);
    Header=(int *)malloc(sizeof(int)*8);
    Name_enc=(int *)malloc(sizeof(int)*12);
    Pwd_enc=(int *)malloc(sizeof(int)*soft_len_max);
    Tail=(int *)malloc(sizeof(int)*(124));
    Order=(int *)malloc(sizeof(int)*soft_len_max);
    Sum=(int *)malloc(sizeof(int)*soft_len_max);
    Char_0_bin=(int *)malloc(sizeof(int)*8);
    Pwd_bin=(int **)malloc(sizeof(int *)*soft_len_max);
    Pwd_enc_bin=(int **)malloc(sizeof(int *)*soft_len_max);
    Carry=(int **)malloc(sizeof(int *)*soft_len_max);
    for(i=0;i<soft_len_max;i++)
       {
       Pwd_bin[i]=(int *)malloc(sizeof(int)*8);
       Pwd_enc_bin[i]=(int *)malloc(sizeof(int)*8);
       Carry[i]=(int *)malloc(sizeof(int)*8);
       }
    
    // ******** MAIN LOOPS ********
    for(pwd_len=pwd_len_min;pwd_len<=pwd_len_max;pwd_len++)  //loop 0
       {
       tail_0_nb=soft_len_max+1-pwd_len;
       Show_progress(pwd_len,tail_0_nb,soft_len_max);
       for(block_size=0x02;block_size<=0x11;block_size++) //loop 1
          {
          Extract(Buffer,block_size,pwd_len_max,soft_len_max,&Header,&Name_enc,
    	      &char_0,&Pwd_enc,&Tail);
    
          if(tail_0_nb>=pwd_len)
    	 {
    	 found=Speed_high(pwd_len,block_size,soft_len_max,char_0,Tail,&Pwd);
    	 }
          else
    	 {
    	 if(tail_0_nb>=12)
    	    {
    	    found=Speed_medium(pwd_len,block_size,soft_len_max,char_0,Tail,&Pwd);
    	    }
    	 else
    	    {
    	    found=Speed_low(pwd_len,block_size,soft_len_max,char_0,Pwd_enc,Tail,
    		      &Pwd,&Order,&Sum,&Char_0_bin,&Carry,&Pwd_enc_bin,&Pwd_bin);
    	    }
    	 }
          if(found) {break;}
          } //end loop 1 (each block_size)
       if(found) {break;}
       }  //end loop 0 (each pwd_len)
    
    Print_pwd(pwd_len,Pwd,time_start);
    Wait_key();
    }
    
    /***************************************************************************/
    /*************************       FUNCTIONS       ***************************/
    /***************************************************************************/
    
    /***************************************************************************/
    /* Method used to recover largest passwords (up to 40 and 123 characters)  */
    
    int Speed_low(int pwd_len,int block_size,int soft_len_max,int char_0,
    	      int *Pwd_enc,int *Tail,int **Pwd,int **Order,int **Sum,
    	      int **Char_0_bin,int ***Carry,int ***Pwd_enc_bin,int ***Pwd_bin)
    {
    int first_var;  // where to start enumeration
    int case_1,case_2;
    int init_12,temp_int;
    int free_nb;    // number of free variable(s), can be 0
    int found;                  // 0: pwd not found yet     1: pwd found
    int i,j,weight;         //0<=weight<=7
    
    for(i=0;i<pwd_len;i++)
       {
       (*Order)[i]=0; (*Pwd)[i]=0; (*Sum)[i]=0;
       for(j=0;j<8;j++) {(*Pwd_bin)[i][j]=0; (*Pwd_enc_bin)[i][j]=0;
    		     (*Carry)[i][j]=0;}
       }
    for(i=0;i<pwd_len;i++)
       {
       Euclid(Pwd_enc[i],&(*Pwd_enc_bin)[i]);
       }
    Euclid(char_0,Char_0_bin);
    
    Order_vars(pwd_len,Order);
    free_nb=Calc_free_nb(*Order,pwd_len,&case_1,&case_2);
    
    for(init_12=0x00;init_12<0x100;init_12++)   //loop 2
       {
       for(i=0;i<pwd_len;i++) {(*Pwd)[i]=0; (*Carry)[i][0]=0;}
       if(char_0>=init_12) {temp_int=char_0-init_12;}
       else {temp_int=0x100+char_0-init_12;}
       Euclid(temp_int,&(*Pwd_bin)[(*Order)[0]]);    //!!!!
    
       for(weight=0;weight<8;weight++)    //loop 3: slicing
          {  //initializations
          for(i=0;i<pwd_len;i++) {(*Sum)[i]=0;}
          for(i=0;i<pwd_len && i!=(*Order)[0];i++) {(*Pwd_bin)[i][weight]=0;}
          first_var=0;
          (*Sum)[0]=(*Char_0_bin)[weight];
    
          do  //loop 4:solving
    	 {
    	 Set_free_vars(first_var,free_nb,weight,*Pwd_enc_bin,*Order,Pwd_bin,Carry,Sum);
    	 Set_other_vars(pwd_len,case_1,case_2,free_nb,weight,*Pwd_enc_bin,*Order,Pwd_bin,Carry,Sum);
    	 found=Check_eqs(case_1,case_2,pwd_len,weight,*Pwd_enc_bin,*Order,*Pwd_bin,Carry,Sum);
    	 if(found)
    	    {
    	    Update_pwd(pwd_len,weight,*Pwd_bin,Pwd);
    	    break;
    	    }
    	 else {if(!Shift(free_nb,weight,Pwd_bin,&first_var)) {break;}}
    	 } while(!found); //end loop 4
    
          if(!found) {break;}
          } //end loop 3 (each weight)
    
       if(found)
          {// begin checks
          if(Check_block_size(pwd_len,block_size,(*Pwd)))
    	 {
    	 if(Check_init_12(pwd_len,init_12,(*Pwd)))
    	    {
    	    if(Check_tail_0(pwd_len,soft_len_max,(*Pwd),Tail))
    	       {
    	       if(Check_pwd(pwd_len,(*Pwd),Tail))
    		  {
    		  //printf("\nSlow Way block:%x init_12:%x len:%d PWD FOUND ",
    			 //block_size,init_12,pwd_len);
    		  return(1);
    		  }
    	       }
    	    }
    	 }
          }// end checks
       }//end loop 2 (each init_12)
    return(0);
    }
    
    /***************************************************************************/
    /*   Can be used to recover passwords longer than with Speed_high, but     */
    /*   some more work is needed. max pwd'lenght=29 (Int. Ver.)               */
    /*   or 112 characters (U.S. Ver.)           				   */
    /*   init_12=Sum(pwd'chars)+first 12 chars of pwd (wrap if pwd'lenght<12)  */
    /*   Build password using 3 rounds:                                        */
    /*        Pwd[13],Pwd[14],...,Pwd[23],Pwd[24]   1ψ round                   */
    /*        Pwd[12]                                                          */
    /*        Pwd[ 0],Pwd[ 1],...,Pwd[10],Pwd[11]   2ψ round                   */
    /*        Pwd[25],Pwd[26],...and so on          3ψ round                   */
    
    int Speed_medium(int pwd_len,int block_size,int soft_len_max,int char_0,
    	  int *Tail,int **Pwd)
    {
    const int name_size=12;
    int i,sum,init_12,init_12_pwd,pos,tail_0_nb,temp;
    
    tail_0_nb=soft_len_max+1-pwd_len;
    
    for(init_12_pwd=0x00;init_12_pwd<0x100;init_12_pwd++)  //loop 0
       {
       sum=init_12_pwd;
       for(i=0;i<name_size;i++)
          {//1ψ round: (sum+Pwd[13+i])^Tail[pwd_len+i]=0x00 => Pwd[13+i]
          pos=name_size+1+pwd_len+i;
          pos=fmod(pos,pwd_len);
          if(Tail[pwd_len+i]>=sum) {(*Pwd)[pos]=Tail[pwd_len+i]-sum;}
          else {(*Pwd)[pos]=0x100+Tail[pwd_len+i]-sum;}
          sum+=(*Pwd)[pos];
          sum=(sum&0x000000FF); //mask
          }
       for(init_12=0x00;init_12<0x100;init_12++) //loop 1
          {
          if(char_0>=init_12) {(*Pwd)[12]=char_0-init_12;}
          else {(*Pwd)[12]=0x100+char_0-init_12;}
          sum=init_12+(*Pwd)[12];
          sum=(sum&0x000000FF); //mask
    
          for(i=0;i<name_size;i++)
    	 {//2ψ round: (sum+Pwd[13+i])^Tail[i]=Pwd[i] => Pwd[i]
    	 pos=name_size+1+i;
    	 pos=fmod(pos,pwd_len);
    	 sum+=(*Pwd)[pos];
    	 sum=(sum&0x000000FF); //mask
    	 (*Pwd)[i]=(sum^Tail[i]);
    	 }
    
          for(i=25;i<pwd_len;i++)
    	 {//3ψ round: (sum+Pwd[25+i])^Tail[12+i]=Pwd[12+i] => Pwd[25+i]
    	 temp=(*Pwd)[i-13]^Tail[i-13];
    	 if(temp>=sum) {(*Pwd)[i]=temp-sum;}
    	 else {(*Pwd)[i]=0x100+temp-sum;}
    	 sum+=(*Pwd)[i];
    	 sum=(sum&0x000000FF); //mask
    	 }
          //begin checks
          if(Check_block_size(pwd_len,block_size,(*Pwd)))
    	 {
    	 if(Check_init_12(pwd_len,init_12,(*Pwd)))
    	    {
    	    if(Check_char_0(char_0,pwd_len,(*Pwd)))
    	       {
    	       if(Check_init_12_pwd(pwd_len,init_12_pwd,(*Pwd)))
    		  {
    		  if(Check_tail_0(pwd_len,soft_len_max,(*Pwd),Tail))
    		     {
    		     if(Check_pwd(pwd_len,(*Pwd),Tail))
    			{
    			//printf("\nSnail Way block:%x init_12:%x init_12_pwd:%x len:%d PWD FOUND ",
    			       //block_size,init_12,init_12_pwd,pwd_len);
    			return(1);
    			}
    		     }
    		  }
    	       }
    	    }
    	 }//end checks
          }//end loop 1 (each init_12)
       }//end loop 0 (each init_12_pwd)
    return(0);
    }
    
    /***************************************************************************/
    /* Fastest method. Direct computation of password, no "guessing" needed.   */
    /* Can only be used if pwd to recover is short enough: max pwd'lenght=20   */
    /* (International Version) or 62 characters (U.S. Version).                */
    /* Build whole pwd: Pwd[13],Pwd[14],...,Pwd[pwd_len-1],Pwd[0],...,Pwd[12]. */
    
    int Speed_high(int pwd_len,int block_size,int soft_len_max,int char_0,
    	     int *Tail,int **Pwd)
    {
    const int name_size=12;
    int i,sum,init_12_pwd,pos;
    
    for(init_12_pwd=0x00;init_12_pwd<0x100;init_12_pwd++)   //loop 0
       {
       sum=init_12_pwd;
       for(i=0;i<pwd_len;i++)
          {
          pos=name_size+1+pwd_len+i;
          pos=fmod(pos,pwd_len);
          if(Tail[pwd_len+i]>=sum) {(*Pwd)[pos]=Tail[pwd_len+i]-sum;}
          else {(*Pwd)[pos]=0x100+Tail[pwd_len+i]-sum;}
          sum+=(*Pwd)[pos];
          sum=(sum&0x000000FF); //mask
          }
       //begin checks
       if(Check_block_size(pwd_len,block_size,(*Pwd)))
          {
          if(Check_char_0(char_0,pwd_len,(*Pwd)))
    	 {
    	 if(Check_init_12_pwd(pwd_len,init_12_pwd,(*Pwd)))
    	    {
    	    if(Check_tail_0(pwd_len,soft_len_max,(*Pwd),Tail))
    	       {
    	       if(Check_pwd(pwd_len,(*Pwd),Tail))
    		  {
    		  //printf("\nFast Way block:%x init:%x len:%d ",block_size,init_12_pwd,pwd_len);
    		  return(1);
    		  }
    	       }
    	    }
    	 }
          }//end checks
       }//end loop 0 (each init_12_pwd)
    return(0);
    }
    
    /***************************************************************************/
    /* Ultimate (and more time-costing) test for accepting pwd.                */
    /* EIW performs exactly the same test in International and U.S. releases.  */
    /* Return 1 if pwd pass test, 0 if it fails.                               */
    
    int Check_pwd(int pwd_len,int *Pwd,int *Tail)
    {
    int i,sum,dec_pwd,pos;
    
    for(i=0,sum=0;i<pwd_len;i++) {sum+=Pwd[i];}  // Sum(pwd'chars)
    for(i=0;i<=12;i++) {pos=fmod(i,pwd_len); sum+=Pwd[pos];}
    
    for(i=0;i<pwd_len;i++)
       {
       pos=13+i;
       pos=fmod(pos,pwd_len);
       sum+=Pwd[pos];
       sum=(sum&0x000000FF); //mask
       dec_pwd=(sum^Tail[i]);
       if(dec_pwd!=Pwd[i]) {return(0); /*no good*/}
       }
    return(1); //OK, good pwd!
    }
    
    /***************************************************************************/
    /*               check if char_0=0 (0x00) after decryption                 */
    /*                      return 1 if OK, 0 otherwise                        */
    
    int Check_char_0(int char_0,int pwd_len,int *Pwd)
    {
    const int name_size=12;
    int i,sum,pos; //pos=position in pwd (0...pwd_len-1)
    
    for(i=0,sum=0;i<pwd_len;i++) {sum+=Pwd[i];}  // Sum(pwd'chars)
    
    for(i=0;i<=name_size;i++) {pos=fmod(i,pwd_len); sum+=Pwd[pos];}
    
    sum=(sum&0x000000FF); //mask
    
    if(sum==char_0) {return(1);} //char_0=(sum^char_0)
    else {return(0);}
    
    }
    
    /***************************************************************************/
    /*  Called by speed_low routine: return number of free variable(s)         */
    
    int Calc_free_nb(int *Order,int pwd_len,int *case_1,int *case_2)
    {
    const int name_size=12;
    int free_nb;
    
    (*case_1)=pwd_len-(Order[0]+1);
    (*case_2)=Order[0];
    if(pwd_len!=(name_size+1)) {free_nb=Min((*case_1),(*case_2));}
    else {free_nb=Max((*case_1),(*case_2));}
    return(free_nb);
    }
    
    /***************************************************************************/
    /*      Called by speed_low routine: order all variables (free+other)      */
    
    void Order_vars(int pwd_len,int **Order)
    {
    const int name_size=12;
    int i,start;
    
    if(pwd_len>name_size) {start=name_size;}
    else {start=fmod(name_size,pwd_len);}
    
    for(i=0;i<pwd_len;i++)
       {
       if(start+i<pwd_len) {(*Order)[i]=start+i;}
       else {(*Order)[i]=start+i-pwd_len;} //wrap
       }
    }
    
    /***************************************************************************/
    /* Called by speed_low routine:	checks remaining equation(s)               */
    /*       Return 1 if OK, 0 otherwise                                       */
    
    int Check_eqs(int case_1,int case_2,int pwd_len,int weight,int **Pwd_enc_bin,
    	      int *Order,int **Pwd_bin,int ***Carry,int **Sum)
    {
    int i;
    
    // test(s)
    i=Max(case_1,case_2);
    for(i;i<pwd_len-1;i++)
       {
       if(Pwd_bin[i][weight]==Pwd_enc_bin[i][weight])
          {
          if(Odd((*Sum)[i]+(*Carry)[i][weight]+Pwd_bin[Order[i+1]][weight])) {return(0);}
          }
       else
          {
          if(!Odd((*Sum)[i]+(*Carry)[i][weight]+Pwd_bin[Order[i+1]][weight])) {return(0);}
          }
       (*Carry)[i][weight+1]=floor(((*Sum)[i]+Pwd_bin[Order[i+1]][weight]+(*Carry)[i][weight])/2);
       (*Sum)[i+1]=(*Sum)[i]+Pwd_bin[Order[i+1]][weight];
       }
    
    //last test
    i=pwd_len-1;
    if(Pwd_bin[i][weight]==Pwd_enc_bin[i][weight])
       {
       if(Odd((*Sum)[i]+(*Carry)[i][weight]+Pwd_bin[Order[0]][weight])) {return(0);}
       }
    else
       {
       if(!Odd((*Sum)[i]+(*Carry)[i][weight]+Pwd_bin[Order[0]][weight])) {return(0);}
       }
    (*Carry)[i][weight+1]=floor(((*Sum)[i]+Pwd_bin[Order[0]][weight]+(*Carry)[i][weight])/2);
    
    return(1);
    }
    
    /***************************************************************************/
    /*  Called by speed_low routine: sets non-free variable(s) during slicing  */
    
    void Set_other_vars(int pwd_len,int case_1,int case_2,int free_nb,int weight,
    		    int **Pwd_enc_bin,int *Order,int ***Pwd_bin,int ***Carry,
    		    int **Sum)
    {
    int i;
    
    //set other variables
    if(case_1<case_2)
       { //right=fψ(left)
       for(i=free_nb;i<Order[0];i++)
          {
          if(Odd((*Sum)[i]+(*Pwd_bin)[Order[i+1]][weight]+(*Carry)[i][weight]))
    	 {
    	 if(Odd(Pwd_enc_bin[i][weight])) {(*Pwd_bin)[i][weight]=0;}
    	 else {(*Pwd_bin)[i][weight]=1;}
    	 }
          else
    	 {
    	 if(Odd(Pwd_enc_bin[i][weight])) {(*Pwd_bin)[i][weight]=1;}
    	 else {(*Pwd_bin)[i][weight]=0;}
    	 }
          (*Carry)[i][weight+1]=floor(((*Sum)[i]+(*Pwd_bin)[Order[i+1]][weight]
    			    +(*Carry)[i][weight])/2);
          (*Sum)[i+1]=(*Sum)[i]+(*Pwd_bin)[Order[i+1]][weight];
          }
       }
    else
       { //left=fψ(right)
       for(i=free_nb;i<pwd_len-(Order[0]+1);i++)
          {
          if((*Pwd_bin)[i][weight]==Pwd_enc_bin[i][weight])
    	 {
    	 if(Odd((*Sum)[i]+(*Carry)[i][weight])) {(*Pwd_bin)[Order[i+1]][weight]=1;}
    	 else {(*Pwd_bin)[Order[i+1]][weight]=0;}
    	 }
          else
    	 {
    	 if(Odd((*Sum)[i]+(*Carry)[i][weight])) {(*Pwd_bin)[Order[i+1]][weight]=0;}
    	 else {(*Pwd_bin)[Order[i+1]][weight]=1;}
    	 }
          (*Carry)[i][weight+1]=floor(((*Sum)[i]+(*Pwd_bin)[Order[i+1]][weight]
    			   +(*Carry)[i][weight])/2);
          (*Sum)[i+1]=(*Sum)[i]+(*Pwd_bin)[Order[i+1]][weight];
          }
       }
    }
    
    /***************************************************************************/
    /*      Called by speed_low routine: sets free variable(s) (if any)        */
    
    void Set_free_vars(int first_var,int free_nb,int weight,int **Pwd_enc_bin,
    		   int *Order,int ***Pwd_bin,int ***Carry,int **Sum)
    {
    int i;
    
    for(i=first_var;i<free_nb;i++) //set free variable(s)
       {
       if(Odd(Pwd_enc_bin[i][weight]+(*Pwd_bin)[i][weight]))
          {
          if(Odd((*Sum)[i]+(*Carry)[i][weight])) {(*Pwd_bin)[Order[i+1]][weight]=0;}
          else {(*Pwd_bin)[Order[i+1]][weight]=1;}
          }
       else
          {
          if(Odd((*Sum)[i]+(*Carry)[i][weight])) {(*Pwd_bin)[Order[i+1]][weight]=1;}
          else {(*Pwd_bin)[Order[i+1]][weight]=0;}
          }
          //carry
       (*Carry)[i][weight+1]=floor(((*Sum)[i]+(*Carry)[i][weight]
    			 +(*Pwd_bin)[Order[i+1]][weight])/2);
          //sum
       (*Sum)[i+1]=(*Sum)[i]+(*Pwd_bin)[Order[i+1]][weight]; //do NOT add carry !
       }
    }
    
    /***************************************************************************/
    /*           return 0 if no more combi to try, 1 otherwise                 */
    
    int Shift(int free_nb,int weight,int ***Pwd_bin,int *first_var)
    {
    int i;
    
    for(i=free_nb-1;i>=0;i--) //backward
       {
       if(!(*Pwd_bin)[i][weight])
          {
          // OK, var i can be changed
          (*Pwd_bin)[i][weight]++;
          *first_var=i;
          return(1);
          }
       else {(*Pwd_bin)[i][weight]=0;} //reset
       }
    return(0); //no more combi to try => stop
    }
    
    /***************************************************************************/
    
    void Hi_folks(void)
    {
    printf("\n\n CASIMIR'Cracker for: Encrypt-It for Windows (MaeDae Enterprises)");
    printf("\n For International & U.S./Canadian versions\n");
    }
    
    /***************************************************************************/
    /*    try to open crypted file  (must be in the SAME directory)            */
    /*    - success : return file'handle                                       */
    /*    - fail : exit prg                                                    */
    
    int Get_target(void)
    {
    unsigned char buf[100];
    int fn;
    
    printf("\nFile to decrypt [e.g: SECRETXT.~00]?   ");
    gets(buf);
    
    // try to open file
    fn=open(buf,O_BINARY|O_RDONLY);
    switch(fn)
       {
       case -1:printf("\nFILE NOT FOUND! (file to crack MUST be in SAME");
       printf("\ndirectory than Cracker; file'name CAN NOT exceed");
       printf("\n8 characters; DO NOT forget file'extension!)\n ");
       Wait_key(); exit(0);
       default: /*printf("\nOK, FILE FOUND")*/; return(fn);
       }
    }
    
    /***************************************************************************/
    /*                               chronometer                               */
    
    void Chrono(void)
    {
    static time_t t1;
    time_t t2;
    t2=time(NULL);
    
    if(difftime(t2,t1)>1){printf(".");t1=time(NULL);}
    }
    
    /***************************************************************************/
    /*                       wait for key pressed                              */
    
    void Wait_key()
    {
    printf("\n");
    printf("              ΙΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ»\n");
    printf("              Ί Hit any key to exit... Ί\n");
    printf("              ΘΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ1/4\n");
    getch(); {/* wait until key pressed */}      //kbhit
    exit(0); //back to DOS
    }
    
    /***************************************************************************/
    /*                       return smallest value                             */
    
    int Min(int a,int b)
    {
    if(a<b) {return(a);}
    return(b);
    }
    
    /***************************************************************************/
    /*                       return greatest value                             */
    
    int Max(int a,int b)
    {
    if(a>b) {return(a);}
    return(b);
    }
    
    /***************************************************************************/
    /*     Print password decrypted, along with equivalent "ALT" sequence      */
    
    void Print_pwd(int pwd_len,int *Pwd,time_t time_start)
    {
    int i;
    time_t t;
    t=time(NULL);
    
    printf("\n\n ALT sequence: ");
    for(i=0;i<pwd_len;i++)
       {
       printf("[%d]",Pwd[i]);
       if((i+1)%10==0) {printf("\n               ");}
       }
    printf("\n\n PASSWORD: >>> ");
    for(i=0;i<pwd_len;i++)
       {
       printf("%c",Pwd[i]);
       }
    printf(" <<<\n");
    
    printf("\n%d characters [elapsed time: %3.0lfs]\n",pwd_len,difftime(t,time_start));
    }
    
    /***************************************************************************/
    /*                         Euclid's decomposition                          */
    
    void Euclid(int data_hex,int **data_bin)
    {
    int weight;
    
    for(weight=0;weight<8;weight++)
       {
       (*data_bin)[weight]=fmod(data_hex,2);
       data_hex=floor(data_hex/2);
       }
    
    }
    
    /***************************************************************************/
    /*              return 0 if num is even;  1 if num is odd                  */
    
    int Odd(int num)
    {
    if(fmod(num,2)==0) {return(0); /*num is even*/}
    else {return(1); /*num is odd*/}
    }
    
    /***************************************************************************/
    /*         pwd is built "slice by slice", beginning with                   */
    /*  low-weight bit (weight=0) and ending with high-weight bit (weight=7)   */
    
    void Update_pwd(int pwd_len,int weight,int **Pwd_bin,int **Pwd)
    {
    int i;
    
    for(i=0;i<pwd_len;i++) {(*Pwd)[i]+=(pow(2,weight)*Pwd_bin[i][weight]);}
    }
    
    /***************************************************************************/
    /*                        Called only once                                 */
    
    void Fill_buffer(int fn,char **Buffer,int buf_size)
    {
    (*Buffer)=(unsigned char *)malloc(sizeof(char)*buf_size);
    // read first 1000 characters of file
    read(fn,*Buffer,buf_size);
    close(fn);
    }
    
    /***************************************************************************/
    /*    Extract some reordered characters from encrypted file                */
    /*    file'structure: | A B C D E F G H | I J K L M N O P Q R S ....       */
    /*                    |<--- header  --->|<---- useful part ---- ....       */
    /*    step 1: copy header (8 chars, indicates algo used to encrypt file)   */
    /*    step 2: reordering of "useful" part (header is NOT used)             */
    /*    (ex:block'size=4)	before permutations: IJKL MNOP QRST UVWX ...       */
    /*                      after     "   "    : LKJI PONM TSRQ XWVU ...       */
    /*    step 3: extraction of encrypted file'name, char_0 and encrypted pwd  */
    /*                      before decryption: LKJIPONMTSRQ X    WVUBAZYF      */
    /*                      after     "   "  : filename.doc 0x00 password      */
    /*  NB: -file'name format: 8.3 (12 chars)                                  */
    /*      -char_0 (1 char): there's always a 0x00 between original file'name */
    /*                        and password (sort of "borderline")              */
    /*      -to recover a password of n characters, we need n chars from file  */
    
    void Extract(unsigned char *Buffer,int block_size,int pwd_len_max,
    	     int soft_len_max,int **Header,int **Name_enc,int *char_0,
    	     int **Pwd_enc,int **Tail)
    {
    const int head_size=8;
    const int name_size=12;
    int i,j,block_nb,pos_temp,pos_buf;
    int *Temp;
    
    //read header
    for(i=0;i<head_size;i++) {(*Header)[i]=Buffer[i];}
    
    //permute block_nb block(s)
    block_nb=floor((name_size+1+soft_len_max+1)/block_size)+1;
    Temp=(int *)malloc(sizeof(int)*block_nb*block_size);   //pb mem
    pos_temp=0;
    for(i=0;i<block_nb;i++)
       {
       pos_buf=head_size+(i+1)*block_size-1;
       for(j=pos_buf;j>(pos_buf-block_size);j--)
          {
          Temp[pos_temp]=Buffer[j];
          pos_temp++;
          }
       }
    
    //read file'name
    for(i=0;i<name_size;i++) {(*Name_enc)[i]=Temp[i];}
    
    //read char_0
    *char_0=Temp[name_size];
    
    //read pwd_len_max characters
    for(i=name_size+1,j=0;i<name_size+1+pwd_len_max;i++,j++)
       {(*Pwd_enc)[j]=Temp[i];}
    
    //read soft_len_max+1 characters
    for(i=name_size+1,j=0;i<name_size+1+soft_len_max+1;i++,j++)
       {(*Tail)[j]=Temp[i];}
    
    free(Temp);
    }
    
    /***************************************************************************/
    /*        check if [(Sum(pwd'chars)+pwd_len)AND(0000000F)]+2=block_size    */
    /*        return 1 if pwd pass test, 0 otherwise                           */
    
    int Check_block_size(int pwd_len,int block_size,int *Pwd)
    {
    int i,sum;
    
    for(i=0,sum=0;i<pwd_len;i++) {sum+=Pwd[i];}
    sum+=pwd_len;
    sum=(sum&0x0000000F);  //mask
    sum+=2;
    
    if(sum==block_size) {/*printf("CBSgood");*/ return(1);}
    else {/*printf("CBSbad");*/ return(0);}
    }
    
    /***************************************************************************/
    /*     check if init_12=Sum(pwd'chars)+first 12 chars of pwd (+mask)       */
    /*       (wrap if pwd'lenght<12 chars)                                     */
    /*        return 1 if pwd pass test, 0 otherwise                           */
    /* e.g: pwd=12345                                                          */
    /* init_12 = 31+32+33+34+35 + 31+32+33+34+35+31+32+33+34+35+31+32          */
    /* init_12 = 360, masking with 000000FF we obtain: init_12=60              */
    
    int Check_init_12(int pwd_len,int init_12,int *Pwd)
    {
    const int name_size=12;
    int i,sum,pos;
    
    for(i=0,sum=0;i<pwd_len;i++) {sum+=Pwd[i];}  // Sum(pwd'chars)
    
    for(i=0;i<name_size;i++) {pos=fmod(i,pwd_len); sum+=Pwd[pos];}
    
    sum=(sum&0x000000FF); //mask
    if(sum==init_12) {/*printf("good");*/ return(1);}
    else {/*printf("no good");*/ return(0);}
    }
    
    /***************************************************************************/
    /*     check if init_12_pwd=Sum(pwd'chars)+first 13 chars of pwd           */
    /*       (wrap if pwd'lenght<13 chars)+Sum(pwd'chars)                      */
    /*        return 1 if pwd pass test, 0 otherwise                           */
    /* e.g: pwd=ABCDEFGHIJKLMNOPQRSTUVWXYZ012  sum=872                         */
    /* init_12_pwd = 872 + 41+42+*/
    
    int Check_init_12_pwd(int pwd_len,int init_12_pwd,int *Pwd)
    {
    const int name_size=12;
    int i,sum,pos;
    
    for(i=0,sum=0;i<pwd_len;i++) {sum+=Pwd[i];}  // Sum(pwd'chars)
    sum*=2;
    for(i=0;i<=name_size;i++) {pos=fmod(i,pwd_len); sum+=Pwd[pos];}
    
    sum=(sum&0x000000FF); //mask
    if(sum==init_12_pwd) {/*printf("good");*/ return(1);}
    else {/*printf("no good");*/ return(0);}
    }
    
    /***************************************************************************/
    /*  Start of decrypted file always has this structure (NB: 0 means 0x00):  */
    /*  |name.doc0000|     0    |password000000000000000000000000000000000|    */
    /*  |<-12 chars->|<-1 char->|<--- Tail: soft_len_max+1 characters --->|    */
    /*  check if 0s AFTER password are present                                 */
    /*        return 1 if pwd pass test, 0 otherwise                           */
    
    int Check_tail_0(int pwd_len,int soft_len_max,int *Pwd,int *Tail)
    {
    const int name_size=12;
    int i,sum,pos;
    
    for(i=0,sum=0;i<pwd_len;i++) {sum+=Pwd[i];}  // Sum(pwd'chars)
    for(i=0;i<name_size+1+pwd_len;i++) {pos=fmod(i,pwd_len); sum+=Pwd[pos];}
    for(i=pwd_len;i<soft_len_max+1;i++)
       {
       pos=fmod(name_size+1+i,pwd_len);
       sum+=Pwd[pos];
       sum=(sum&0x000000FF); //mask
       if((sum^Tail[i])!=0x00) {return(0);/*no good*/}
       }
    return(1); //OK
    }
    
    /***************************************************************************/
    /*  The 2 first bytes of an encoded file learn us software release         */
    /*  (International or U.S. version) and algo used:                         */
    /*                              International   U.S.\Canada   Can break?   */
    /*  3 Way Proprietary           00.00.          00.01.        yes          */
    /*  Multilayer Proprietary +    02.00.          02.01.        yes          */
    /*  D.E.S.                      none            01.01.        no           */
    /*  D.E.S + C.B.C.              none            03.01.        no           */
    /*  D.E.S + C.B.C. + Blowfish   none            04.01.        no           */
    /*                                                                         */
    /*  Return 1 if encryption can be broken, 0 otherwise                      */
    
    int Can_break(char *Buffer,int *soft_len_max)
    {
    int byte_0,byte_1;
    
    byte_0=Buffer[0];
    byte_1=Buffer[1];
    switch(byte_0)
       {
       case(0):{printf("\n Encryption method: 3 Way Proprietary"); break;}
       case(2):{printf("\n Encryption method: Multilayer Proprietary +"); break;}
       default:{printf("\n Sorry, can't break DES stuff {:-( \n");
    	    return(0);}
       }
    //Benchmark: how long will you wait for password to pop up?
    if(byte_1)
       {
       *soft_len_max=123;
       printf(" (U.S. & Canada version)\n");
       printf("\npwd'len: |5±±±±±±±±±±±±±±±±±±±±±±±±±±62|63±±±±±±±±±±±±±±±±±±±±112|113±±±±±123|\n");
       printf("waiting: |<-           12s           ->|<-        30min        ->|<-  22h  ->|");
       }
    else
       {
       *soft_len_max=40;
       printf(" (International version)\n");
       printf("\npwd'len: |5±±±±±±±±±±±±±20|21±±±±±29|30±±±±±±±40|\n");
       printf("waiting: |<-     1s     ->|<-150s ->|<-2h45min->|");
       }
    return(1);
    }
    
    /***************************************************************************/
    /*                  Display progression of research.                       */
    
    void Show_progress(int pwd_len,int tail_0_nb,int soft_len_max)
    {
    switch(soft_len_max)
       {
       case(40):
          {
          printf("°");
          if(pwd_len==20 || pwd_len==29) {printf("|");}
          break;
          }
       case(123):
          {
          if(pwd_len==62 || pwd_len==112) {printf("|");}
          if((pwd_len<113)&&(Odd(pwd_len))) {printf("°");}
          else
    	 {
    	 if(pwd_len>=113) {printf("°");}
    	 }
          break;
          }
       }
    }
    
    
    Here is the Executable Crackeiw and Source Code
    Mail Casimir.