CRACKING OF WinXFiles

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 Encrypt-It For Windows
  • 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 PepSoft
    (You might need to use FTP Search to find the software.)
    Try searching for WXF.

    This essay presents in-extenso the reverse-engineering and cracking of an encryption utility distributed by PEPSOFTWARE Ltd, WinXFiles(TM). Map of the essay:

       Introduction
       Strategy
       Getting prepared
    
       PART A - REVERSING OF WINXFILES 
            1. First contact
            2. Where is the fork?
            3. The Check routine
            4. The making of Check_string
            5. The Remainder
            6. Decryption process
    
       PART B - ANALYSIS AND BREAKING OF WINXFILES
            Method 1: let's suppose Tail = 000...
                   Step 1: Solving
                   Step 2: Checking password found
                   Notes on Method 1
            Method 2: Tail = garbage
                   Step 1: How to find 2 characters from pwd
                   Step 2: System(s) solving
                   Step 3: Checking password found
                   Bad luck!
                   Notes on Method 2
    
       PART C - 'C' SOURCE OF CRACKER
    

    PART C - 'C' SOURCE OF CRACKER

    
    #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 Fill_header(int,char **,int);
    void Build_r_m1(int,int,int,int,int **,int **);
    void Build_r_m2(int,int,int,int,int **,int **);
    void Build_h_m1(int,int,unsigned char *,int **);
    void Build_h_m2(int,int,unsigned char *,int **);
    int Odd(int);
    void Print_pwd(int,int *);
    void Wait_key();
    int Check_bound(int,int,unsigned char *,int *,int *);
    void Build_pos_m1(int,int,int **);
    void Build_pos_m2(int,int,int **);
    void Solver_m1(int,int *,int *,int *,int **);
    int Check_tail(int,int,int,unsigned char *,int *,int *);
    int Check_rem_start(int,int,int *);
    int Calc_sys_num(int,int *);
    void Hints(int,int,int *,unsigned char *,int *,int *,int *,int *);
    int Check_hr_m1(int,int,int *,int *);
    int Check_hr_m2(int,int,int *,int *);
    int Solver_m2_fast(int,int *,int *,int **);
    int Solver_m2_slow(int,int,int,int,int,int *,int *,int *,int **);
    int Solve_eq(int,int);
    int Check_eq(int,int,int);
    int Check_pwd(int,int,int *,unsigned char *,int *);
    void Print_name(int,int *);
    int Check_name(int,int,int *,int *,unsigned char *,int **);
    
    main()
    {
    int pwd_found=0; 
    int name_len;
    int name_len_max=50;
    int pwd_len;
    int pwd_len_max=30;
    int rem_start; //rem_start=(sum of PWD'characters)modulo(0xFF)
    int hint_pos_l,hint_pos_r,hint_val_l,hint_val_r;
    int fn;       //encrypted file'handle
    const int head_len=255;  //Header's size
    int sys_num;  //number of systems to solve (must be 0, 1 or 2)
    time_t time_start,t; // chrono
    
    char *Header;   //storage for beginning of encrypted file
    int *H,*Remain,*R;
    int *Pwd,*Pos;
    int *File_name; //original file name
    
    H=(int *)malloc(sizeof(int)*pwd_len_max); //a part of Header
    Remain=(int *)malloc(sizeof(int)*head_len);
    R=(int *)malloc(sizeof(int)*pwd_len_max); //a part of Remain
    Pos=(int *)malloc(sizeof(int)*pwd_len_max);
    Pwd=(int *)malloc(sizeof(int)*pwd_len_max);
    File_name=(int *)malloc(sizeof(int)*name_len_max);
    
    //program starts HERE
    Hi_folks();
    fn=Get_target();
    Fill_header(fn,&Header,head_len);
    time_start=time(NULL); //start chrono
    
    
    //Method 1 : Tail=0000....
    printf("\nMethod 1 of 2 ");
    for(name_len=1;name_len<=name_len_max;name_len++) //EACH NAME_LEN (1 -> 100)
      {
      printf("*"); //show search progression
      for(pwd_len=5;pwd_len<=pwd_len_max;pwd_len++) //EACH PWD_LEN (5 -> 30)
        {
        Build_pos_m1(name_len,pwd_len,&Pos);
        Build_h_m1(name_len,pwd_len,Header,&H);
        for(rem_start=0x00;rem_start<0xFF;rem_start++) //EACH REM_START (0 -> 255)
          {
          Build_r_m1(rem_start,head_len,name_len,pwd_len,&Remain,&R);
          if(Check_hr_m1(pwd_len,rem_start,H,R))
    	{
    	Solver_m1(pwd_len,H,R,Pos,&Pwd);
    	if(Check_tail(name_len,pwd_len,head_len,Header,Remain,Pwd))
    	  {
    	  if(Check_bound(name_len,pwd_len,Header,Remain,Pwd))
    	    {
    	    if(Check_rem_start(pwd_len,rem_start,Pwd))
    	      {
    	      if(Check_pwd(name_len,pwd_len,Pwd,Header,Remain))
    		{
    		if(Check_name(name_len,pwd_len,Pwd,Remain,Header,&File_name))
    		  {
    		  Print_name(name_len,File_name);
    		  Print_pwd(pwd_len,Pwd);
    		  Wait_key();
    		  exit(0);
    		  }
    		}
    	      }
    	    }
    	  }
    	}
          }//EACH REM_START
        }//EACH PWD_LEN
      }//EACH NAME_LEN 
    printf("done\n");
    
    //Method 2 : Tail=garbage
    printf("\nMethod 2 of 2 ");
    for(name_len=1;name_len<=name_len_max;name_len++) //EACH NAME_LEN (1 -> 50)
      {
      printf("*");  //show search progression
      for(pwd_len=5;pwd_len<=pwd_len_max;pwd_len++) //EACH PWD_LEN (5 -> 30)
        {
        Build_pos_m2(name_len,pwd_len,&Pos);
        Build_h_m2(name_len,pwd_len,Header,&H);
        sys_num=Calc_sys_num(pwd_len,Pos);
        for(rem_start=0x00;rem_start<0xFF;rem_start++) //EACH REM_START (0 -> 254)
          {
          Build_r_m2(rem_start,head_len,name_len,pwd_len,&Remain,&R);
          if(Check_hr_m2(pwd_len,rem_start,H,R))
    	{
    	if(sys_num==0)
    	  {
    	  if(Solver_m2_fast(pwd_len,H,R,&Pwd))
    	    {
    	    if(Check_bound(name_len,pwd_len,Header,Remain,Pwd))
    	      {
    	      if(Check_rem_start(pwd_len,rem_start,Pwd))
    		{
    		if(Check_pwd(name_len,pwd_len,Pwd,Header,Remain))
    		  {
    		  if(Check_name(name_len,pwd_len,Pwd,Remain,Header,&File_name))
    		    {
    		    Print_name(name_len,File_name);
    		    Print_pwd(pwd_len,Pwd);
    		    Wait_key();
                        pwd_found=1;
    		    }
    		  }
    		}
    	      }
    	    }
    	  }
    	else  //number of systems to solve > 0
    	  {
    	  if(sys_num==1 || sys_num==2)
    	    {
    	    Hints(name_len,pwd_len,Remain,Header,&hint_pos_l,
    	    &hint_pos_r,&hint_val_l,&hint_val_r);
    	    if(Solver_m2_slow(pwd_len,hint_pos_l,hint_pos_r,hint_val_l,
    	    hint_val_r,H,R,Pos,&Pwd))
    	      {
    	      if(Check_rem_start(pwd_len,rem_start,Pwd))
    		{
    		if(Check_pwd(name_len,pwd_len,Pwd,Header,Remain))
    		  {
    		  if(Check_name(name_len,pwd_len,Pwd,Remain,Header,&File_name))
    		    {
    		    Print_name(name_len,File_name);
    		    Print_pwd(pwd_len,Pwd);
    		    Wait_key();
                        pwd_found=1;
    		    }
    		  }
    		}
    	      }
    	    }
    	  }
    	}
          }//EACH REM_START
        }//EACH PWD_LEN
      }//EACH NAME_LEN
    printf("done\n");
    
    if(!pwd_found) {printf("\nsorry, password not found...\n");}
    exit(0);
    }
    
    /**********************************************************************/
    /**********************       FUNCTIONS       *************************/
    /**********************************************************************/
    
    /***********************************************************************/
    /*                Function used by Method 2                            */
    /*          solve linear system (pwd_len eqs, pwd_len-2 unknowns)      */
    /*                      Matrix * Pwd = Header + Remain                 */
    /*    for each line, we solve:                                         */
    /*     0+...+Pwd[li][li]+0+...+Pwd[li][co]+... = Header[li]+Remain[li] */
    /*       each line used is marked, and Solver stops by himself if      */
    /*          search doesn't progress                                    */
    /*     Solver return 1 if the whole password is found, 0 otherwise     */
    int Solver_m2_slow(int pwd_len,int hint_pos_l,int hint_pos_r,int hint_val_l,
    	   int hint_val_r,int *H,int *R,int *Pos,int **Pwd)
    {
    int i,li;          //current line (equation)
    int done;          //done=1 : STOP
    int used_nb,used_nb_last;  //how many lines have been used until now?
    int found_nb,found_nb_last; //how many characters from pwd found until now?
    int *HR,*Found;    //Found[i]=1 : Pwd[i] found!
    int *Used;         //Used[line]=1 : line already used
    
    HR=(int *)malloc(sizeof(int)*pwd_len);
    Found=(int *)malloc(sizeof(int)*pwd_len);
    Used=(int *)malloc(sizeof(int)*pwd_len);
    
    for(li=0;li<pwd_len;li++)
       {
       HR[li]=H[li]+R[li];
       Found[li]=0;
       Used[li]=0;
       (*Pwd)[li]=0;
       }
    (*Pwd)[hint_pos_l]=hint_val_l;
    Found[hint_pos_l]=1;
    (*Pwd)[hint_pos_r]=hint_val_r;
    Found[hint_pos_r]=1;
    
    //init
    found_nb_last=2;
    used_nb_last=0;
    done=0;
    
    while(!done)
       {
       for(li=0;li<pwd_len;li++) //try to solve each line, one at a time
          {
          if(!Used[li]) //line already used?
    	 {
    	 if(Found[li])
    	    {
    	    if(Found[Pos[li]])
    	       {
    	       Used[li]=1; //mark line
    	       if(!Check_eq((*Pwd)[li],(*Pwd)[Pos[li]],HR[li]))
    		  {
    		  free(HR);
    		  free(Found);
    		  free(Used);
    		  return(0);
    		  }
    	       }
    	    else
    	       {//compute Pwd[Pos[li]]
    	       (*Pwd)[Pos[li]]=Solve_eq((*Pwd)[li],HR[li]);
    	       Used[li]=1;
    	       Found[Pos[li]]=1;
    	       }
    	    }
    	 else
    	    {
    	    if(Found[Pos[li]])
    	       {//compute Pwd[li]
    	       (*Pwd)[li]=Solve_eq((*Pwd)[Pos[li]],HR[li]);
    	       Used[li]=1;
    	       Found[li]=1;
    	       }
    	    }
    	 }
          }
       //how many line(s) used and pwd'char found?
       for(used_nb=0,found_nb=0,li=0;li<pwd_len;li++)
          {
          used_nb+=Used[li];
          found_nb+=Found[li];
          }
       //did search progress?
       if(used_nb==used_nb_last && found_nb==found_nb_last)
          {
          free(HR);
          free(Found);
          free(Used);
          return(0);    //failed (no progression)
          }
       used_nb_last=used_nb;
       found_nb_last=found_nb;
       //finished?
       if(used_nb==pwd_len) {done=1;}
       }
    
    free(HR);
    free(Found);
    free(Used);
    
    return(1); //succeed
    }
    
    /**********************************************************************/
    /*                Function used by Method 2                           */
    /*       we have:    Remain[i] + Header[i] - Pwd[i] = Pwd[j]          */
    /*  if i=j then: Pwd[i] = (Remain[i] + Header[i])/2 (fast solving!)   */
    /*  return 1 if Pwd[i] found, 0 otherwise                             */
    int Solver_m2_fast(int pwd_len,int *H,int *R,int **Pwd)
    {
    int i,sum;
    
    for(i=0;i<pwd_len;i++)
       {
       sum=H[i]+R[i];
       //if(sum>0x100) {sum-=0x100;}
       //else {if(sum<0x00) {sum+=0x100;} }
       if((sum%2)!=0) {return(0);}  //sum must be EVEN
       (*Pwd)[i]=(sum/2);
       //printf(" %d ",sum);
       }
    return(1);
    }
    
    /**********************************************************************/
    /*                Function used by Method 1                           */
    int Check_hr_m1(int pwd_len,int rem_start,int *H,int *R)
    {
    int i,tmp,sum,rem;
    
    for(sum=0,i=0;i<pwd_len;i++)
       {
       tmp=H[i]+R[i];
       if(tmp>0xFF) {sum+=(tmp-0x100);}
       else {sum+=tmp;}
       }
    //if(Odd(sum)) {return(0);}
    //sum/=2;
    rem=fmod(sum,0xFF);
    if(rem!=rem_start) {return(0);}
    return(1);
    }
    
    /**********************************************************************/
    /*                Function used by Method 2                           */
    int Check_hr_m2(int pwd_len,int rem_start,int *H,int *R)
    {
    int i,sum,rem;
    
    for(sum=0,i=0;i<pwd_len;i++)
       {
       sum+=H[i]+R[i];
       }
    if(Odd(sum)) {return(0);}
    return(1);
    }
    
    /**********************************************************************/
    /*                Function used by Method 1                           */
    /*   If pwd is correct, a large part of Header must decrypt to 0s     */
    /*  We use this info to build a pwd (BTW, pwd found must be checked)  */
    /*      method:   H[i]+R[i]-Pwd[Pos[i]]=0x00 => Pwd[Pos[i]] found     */
    void Solver_m1(int pwd_len,int *H,int *R,int *Pos,int **Pwd)
    {
    int i,sum;
    
    for(i=0;i<pwd_len;i++)
       {
       sum=H[i]+R[i];
       if(sum<0x100) {(*Pwd)[Pos[i]]=sum;}
       else {(*Pwd)[Pos[i]]=sum-0x100;}
       }
    }
    
    /**********************************************************************/
    /*                return number of systems to be solved               */
    int Calc_sys_num(int pwd_len,int *Pos)
    {
    int i,shift_l,shift_r;
    
    for(i=0;i<pwd_len;i++)
       {
       if(Pos[i]==0) {shift_l=i; break;}
       }
    
    if(shift_l==0) {return(0); /* no system to solve */}
    shift_r=pwd_len-shift_l;
    
    if(shift_l==shift_r) {return(shift_l);}
    
    if(shift_l>shift_r)
       {
       if(fmod(shift_l,shift_r)==0) {return(shift_r);}
       else {return(1);}
       }
    else
       {
       if(fmod(shift_r,shift_l)==0) {return(shift_l);}
       else {return(1);}
       }
    }
    
    /**********************************************************************/
    /*   return 1 if ALL 0s are present:  filename.ext|password\000000... */
    /*   return 0 if one 0 (or +) is missing                              */
    int Check_tail(int name_len,int pwd_len,int head_len,unsigned char *Header,
    	       int *Remain,int *Pwd)
    {
    int i,sum,temp;
    
    for(i=name_len+1+pwd_len+1;i<head_len;i++)
       {
       temp=fmod(i,pwd_len);
       sum=Header[i]+Remain[i]-Pwd[temp];
       if((sum!=0x00) && (sum!=0x100)) {return(0);}
       }
    return(1);  //OK
    }
    
    /**********************************************************************/
    /*  This routine checks if value assumed for rem_start is compatible  */
    /*  with pwd found.                                                   */
    /*  return 1 if rem_start==(sum of PWD'characters)modulo(0xFF),       */
    /*  otherwise return 0                                                */
    /*  for instance, if we found CASIMIR as a pwd, we should have:       */
    /*                 rem_start=(43+41+53+49+4D+49+52)modulo(FF)=0A      */
    /*                                                                    */
    int Check_rem_start(int pwd_len,int rem_start,int *Pwd)
    {
    int sum,rem,i;
    
    for(sum=0,i=0;i<pwd_len;i++)
       {
       sum+=Pwd[i];
       }
    rem=fmod(sum,0xFF);
    
    if(rem!=rem_start) {return(0);}
    
    return(1); //OK
    }
    
    /**********************************************************************/
    /*   return 1 if structure:   filename.ext|password\   is found       */
    /*   as decrypting Header with pwd                                    */
    /*   return 0 if not found                                            */
    int Check_bound(int name_len,int pwd_len,unsigned char *Header,
    		int *Remain,int *Pwd)
    {
    int pwd_bound,rem_bound,buf_bound,sum,temp;
    
    //we only check boundaries (| and \), as filename.ext is unknown
    //check if | is present
    temp=fmod(name_len,pwd_len);
    pwd_bound=Pwd[temp];
    rem_bound=Remain[name_len];
    buf_bound=Header[name_len];
    sum=rem_bound-pwd_bound+buf_bound;
    if(sum>0x100) {sum-=0x100;}
    else {if(sum<0x00) {sum+=0x100;} }
    if(sum!=0x7C) {return(0);}
    
    //check if \ is present
    temp=fmod(name_len+1+pwd_len,pwd_len);
    pwd_bound=Pwd[temp];
    rem_bound=Remain[name_len+1+pwd_len];
    buf_bound=Header[name_len+1+pwd_len];
    sum=rem_bound-pwd_bound+buf_bound;
    if(sum>0x100) {sum-=0x100;}
    else {if(sum<0x00) {sum+=0x100;} }
    if(sum!=0x5C) {return(0);}
    
    return(1); //OK
    }
    
    /**********************************************************************/
    /*         check if Header[i] + Remain[i] - Pwd[j] = Pwd[i]           */
    /*         check if every char from Pwd is valid (sup. 0x19)          */
    /*               return 1 if OK, otherwise return  0                  */
    int Check_pwd(int name_len,int pwd_len,int *Pwd,unsigned char *Header,
    	      int *Remain)
    {
    int pwd_test,rem_test,head_test,sum_test,i,temp;
    
    for(i=0;i<pwd_len;i++)
       {
       temp=fmod(name_len+1+i,pwd_len);
       pwd_test=Pwd[temp];
       rem_test=Remain[name_len+1+i];
       head_test=Header[name_len+1+i];
       sum_test=head_test+rem_test-pwd_test;
       if(sum_test>0x100) {sum_test-=0x100;}
       else {if(sum_test<0x00) {sum_test+=0x100;} }
       if(sum_test!=Pwd[i]) {return(0);}
       if(Pwd[i]<0x20) {return(0);}
       }
    return(1); //OK
    }
    
    /**********************************************************************/
    /*  check if every char from original file name is valid (sup. 0x19)  */
    /*               return 1 if OK, otherwise return  0                  */
    int Check_name(int name_len,int pwd_len,int *Pwd,int *Remain,
    	       unsigned char *Header,int **File_name)
    {
    int pwd_test,rem_test,head_test,name_test,i,temp;
    
    for(i=0;i<name_len;i++)
       {
       temp=fmod(i,pwd_len);
       pwd_test=Pwd[temp];
       rem_test=Remain[i];
       head_test=Header[i];
       name_test=head_test+rem_test-pwd_test;
       if(name_test>0x100) {name_test-=0x100;}
       else {if(name_test<0x00) {name_test+=0x100;} }
       if(name_test<0x20) {return(0);}
       else {(*File_name)[i]=name_test;}
       }
    
    return(1); //OK
    }
    
    /**********************************************************************/
    /*                Function used by Method 1                           */
    /*     fill H using encrypted Header (e.g.: pwd_len=8):               */
    /*     Header (encrypted):  ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefgh...     */
    /*                         >                255@                 <    */
    /*          H (encrypted):                        WXYZabcd            */
    /*                                               >   8@   <           */
    /*     Header (decrypted):  filename.ext|password\000000000000...     */
    /*          H (decrypted):                        00000000            */
    /*  (NB: 0 means 0x00)                           >      tail     <    */
    void Build_h_m1(int name_len,int pwd_len,unsigned char *Header,int **H)
    {
    int i;
    
    for(i=0;i<pwd_len;i++)
       {
       (*H)[i]=Header[name_len+1+pwd_len+1+i];
       }
    }
    
    /**********************************************************************/
    /*                Function used by Method 2                           */
    /*     fill H using encrypted Header (e.g.: pwd_len=8):               */
    /*     Header (encrypted):  ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefgh...     */
    /*                         >                255@                 <    */
    /*          H (encrypted):               NOPQRSTU                     */
    /*                                      >   8@   <                    */
    /*     Header (decrypted):  filename.ext|password\000000000000...     */
    /*          H (decrypted):               00000000                     */
    /*  (NB: 0 means 0x00)                           >      tail     <    */
    void Build_h_m2(int name_len,int pwd_len,unsigned char *Header,int **H)
    {
    int i;
    
    for(i=0;i<pwd_len;i++)
       {
       (*H)[i]=Header[name_len+1+i];
       }
    }
    
    /**********************************************************************/
    /*                Function used by Method 1                           */
    /*    Fill Remain and R, using a unique value, rem_start, as a seed.  */
    /*    (e.g.: pwd_len=8): 				              */
    /*                 Remain:  0123456789012345678901234567890123...     */
    /*                      R:                        23456789            */
    /*     Header (decrypted):  filename.ext|password\000000000000...     */
    void Build_r_m1(int rem_start,int head_len,int name_len,int pwd_len,
    	     int **Remain,int **R)
    {
    int i,rem;
    
    if(rem_start==0) {rem_start=0xFF;}
    else {rem_start--;}
    
    rem=rem_start;
    for(i=0;i<head_len;i++)    //fill Remain
       {
       if(rem==0) {rem=rem_start+1;}
       if(Odd(rem)) {(*Remain)[i]=rem;}     //Remain[2n+1]=rem
       else {(*Remain)[i]=0x100-rem;}       //Remain[2n]=0x100-rem
       rem--;
       }
    for(i=0;i<pwd_len;i++)  //fill R
       {
       (*R)[i]=(*Remain)[name_len+1+pwd_len+1+i];
       }
    }
    
    /**********************************************************************/
    /*                Function used by Method 2                           */
    /*    Fill Remain and R, using a unique value, rem_start, as a seed.  */
    /*    (e.g.: pwd_len=8): 				              */
    /*                 Remain:  0123456789012345678901234567890123...     */
    /*                      R:               34567890                     */
    /*     Header (decrypted):  filename.ext|password\000000000000...     */
    void Build_r_m2(int rem_start,int head_len,int name_len,int pwd_len,
    	     int **Remain,int **R)
    {
    int i,rem;
    
    if(rem_start==0) {rem_start=0xFF;}
    else {rem_start--;}
    
    rem=rem_start;
    for(i=0;i<head_len;i++)    //fill Remain
       {
       if(rem==0) {rem=rem_start+1;}
       if(Odd(rem)) {(*Remain)[i]=rem;}     //Remain[2n+1]=rem
       else {(*Remain)[i]=0x100-rem;}       //Remain[2n]=0x100-rem
       rem--;
       }
    for(i=0;i<pwd_len;i++)  //fill R
       {
       (*R)[i]=(*Remain)[name_len+1+i];
       }
    }
    
    /***************************************************************************/
    /*              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*/}
    }
    
    /***************************************************************************/
    /*                      display original file name                         */
    void Print_name(int name_len,int *File_name)
    {
    int i;
    
    printf("\n\n Original file name: ");
    for(i=0;i<name_len;i++) {printf("%c",File_name[i]);}
    }
    
    /***************************************************************************/
    /*                        display password                                 */
    void Print_pwd(int pwd_len,int *Pwd/*,time_t time_start*/)
    {
    int i;
    
    printf("\n\n ASCII seq: ");
    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("<<< (%d characters)\n\n",pwd_len);
    printf("(don't type >>> and <<<)\n");
    }
    
    /***********************************************************************/
    /*                   wait for key pressed                              */
    void Wait_key()
    {
    printf("\n");
    printf("              ******************\n");
    printf("              * hit any key... *\n");
    printf("              ******************\n");
    getch(); {/* wait until key pressed */}      //kbhit
    }
    
    /***********************************************************************/
    /*                Function used by Method 1                            */
    /*   build Position vector:                                            */
    /*           Header decrypted: filename.ext|password\0000000000...     */
    /*                      input: passwordpasswordpasswordpassword...     */
    /*                                                  [rdpasswo]         */
    /*                so: Postion vector [0] ----------> 6                 */
    /*                                   [1] ---------->  7                */
    /*                                           ...       01234           */
    /*                                   [7] ---------->        5          */
    void Build_pos_m1(int name_len,int pwd_len,int **Pos)
    {
    int i;
    
    for(i=0;i<pwd_len;i++)
       {
       (*Pos)[i]=fmod(name_len+2+i,pwd_len);
       }
    }
    
    /***********************************************************************/
    /*                Function used by Method 2                            */
    /*   build Position vector:                                            */
    /*           Header decrypted: filename.ext|password\0000000000...     */
    /*                      input: passwordpasswordpasswordpassword...     */
    /*                                         [ordpassw]                  */
    /*           so: Postion vector [0] ------> 5                          */
    /*                              [1] ------>  6                         */
    /*                                    ...     70123                    */
    /*                              [7] ------>        4                   */
    void Build_pos_m2(int name_len,int pwd_len,int **Pos)
    {
    int i;
    
    for(i=0;i<pwd_len;i++)
       {
       (*Pos)[i]=fmod(name_len+1+i,pwd_len);
       }
    }
    
    /***************************************************************************/
    /*    try to open crypted file  (must be in the SAME directory)            */
    /*    - success : return file'handle                                       */
    /*    - failure : exit prg                                                 */
    int Get_target(void)
    {
    unsigned char buf[110];
    int fn;
    
    printf("\nFile to decrypt [e.g: SecreTXT.xfd]?   ");
    gets(buf);
    
    // try to open file
    fn=open(buf,O_BINARY|O_RDONLY);
    switch(fn)
       {
       case -1:printf("\nFILE NOT FOUND!");
       printf("\n->File to crack MUST be in SAME directory as Cracker");
       printf("\n->DO NOT forget file's extension (usually: xfd or xfp)!\n");
       Wait_key(); exit(0);
       default: /*printf("\nOK, FILE FOUND")*/; return(fn);
       }
    }
    
    /***************************************************************************/
    /*                        Called only once                                 */
    void Fill_header(int fn,char **Header,int buf_size)
    {
    (*Header)=(unsigned char *)malloc(sizeof(char)*buf_size);
    // read beginning of file
    read(fn,*Header,buf_size);
    close(fn);
    }
    
    /***********************************************************************/
    /*      We know that structure:  filename.ext|password\  is present    */
    /*      Whatever pwd was used to encrypt, "boundaries" ( | and \ )     */
    /*      are there. We use them to find out TWO characters from pwd,    */
    /*      called "hints".                                                */
    void Hints(int name_len,int pwd_len,int *Remain,unsigned char *Header,
    	   int *hint_pos_l,int *hint_pos_r,int *hint_val_l,int *hint_val_r)
    {
    *hint_pos_l=fmod(name_len,pwd_len);
    *hint_pos_r=fmod(name_len+1,pwd_len);
    
    *hint_val_l=Remain[name_len]+Header[name_len]-0x7C;
    *hint_val_r=Remain[name_len+1+pwd_len]+Header[name_len+1+pwd_len]-0x5C;
    
    if(*hint_val_l>0x100) {*hint_val_l-=0x100;}
    else {if(*hint_val_l<0x00) {*hint_val_l+=0x100;} }
    if(*hint_val_r>0x100) {*hint_val_r-=0x100;}
    else {if(*hint_val_r<0x00) {*hint_val_r+=0x100;} }
    }
    
    /***********************************************************************/
    /**/
    int Solve_eq(int pwd,int hr)
    {
    if(pwd>hr)
       {//we add 0x100 to hr, this way a solution can be found
       return(hr+0x100-pwd);
       }
    else
       {
       if((hr-pwd)>=0x100)
          {//we substract 0x100 from hr
          return(hr-0x100-pwd);
          }
        else
          {
          return(hr-pwd);
          }
       }
    }
    
    /***********************************************************************/
    /*     check if:  Pwd[i] + Pwd[j] = Header[i] + Remain[i] +/- 0x100    */
    /*                     return 1 if OK, 0 otherwise                     */
    int Check_eq(int pwdi,int pwdj,int hr)
    {
    if( (pwdi+pwdj) ==  hr        ) {return(1); /* succeed */}
    if( (pwdi+pwdj) == (hr+0x100) ) {return(1); /* succeed */}
    if( (pwdi+pwdj) == (hr-0x100) ) {return(1); /* succeed */}
    
    return(0); //failed
    }
    
    /***********************************************************************/
    void Hi_folks(void)
    {
    printf("\n\nYet Another Password Cracker by CASIMIR {:-)");
    printf("\n-> Target: WinXFiles(TM) by PepSoftware\n");
    }
    </pre>
    
    Click here for the executable crack, source code, and a file to crack.

    I WOULD LIKE TO THANK SINCERELY JOE PESCHEL FOR HOSTING THIS THIRD ESSAY OF MINE ON HIS GREAT SITE. MERCI JOE !

    De rien. And my thanks to Casimir for his wonderful work!

    Copyright December 1998 by Casimir.

    Mail Casimir

    Converted to hypertext by Joe Peschel December 18, 1998.