by
CASIMIR
Part C
This source code was modified,in January by Casimir, to crack version 2.6 as well as 3.5.
#include <stdio.h>
#include <io.h>
#include <time.h>
#include <malloc.h>
#include <conio.h>
#include <math.h>
#include <fcntl.h>
#include <dos.h>
#include <alloc.h>
#include <string.h>
#include <stdlib.h>
#include <sys\stat.h>
// char_min and char_max are Unsigned Long
const int hash1_nb=112; //number of element in Hash table 1
static unsigned long Hash_1[hash1_nb]={
0x23,0x73,0x65,0x72, 0x42,0x26,0x6E,0x7A,
0x7C,0x6D,0x66,0x4D, 0x31,0x2F,0x35,0x28,
0x21,0x73,0x64,0x24, 0x4D,0x71,0x2E,0x7B,
0x73,0x5D,0x2B,0x73, 0x46,0x6A,0x74,0x4B,
0x70,0x7A,0x53,0x64, 0x74,0x7A,0x6F,0x58,
0x71,0x6D,0x62,0x5E, 0x41,0x6C,0x40,0x64,
0x76,0x3A,0x73,0x3F, 0x78,0x2F,0x00,0x00,
0x7C,0x62,0x21,0x70, 0x7A,0x2A,0x6C,0x73,
0x3B,0x72,0x6E,0x7C, 0x6C,0x66,0x24,0x76,
0x69,0x5E,0x41,0x78, 0x70,0x65,0x29,0x72,
0x78,0x35,0x61,0x69, 0x63,0x26,0x39,0x2F,
0x32,0x6D,0x35,0x6C, 0x73,0x69,0x34,0x40,
0x30,0x64,0x6D,0x5A, 0x77,0x39,0x34,0x63,
0x6D,0x71,0x70,0x66, 0x68,0x77,0x00,0x00};
const int hash2_nb=56; //number of element in Hash table 2
static unsigned long Hash_2[hash2_nb]={
0x7C,0x62,0x21,0x70, 0x7A,0x2A,0x6C,0x73,
0x3B,0x72,0x6E,0x7C, 0x6C,0x66,0x24,0x76,
0x69,0x5E,0x41,0x78, 0x70,0x65,0x29,0x72,
0x78,0x35,0x61,0x69, 0x63,0x26,0x39,0x2F,
0x32,0x6D,0x35,0x6C, 0x73,0x69,0x34,0x40,
0x30,0x64,0x6D,0x5A, 0x77,0x39,0x34,0x63,
0x6D,0x71,0x70,0x66, 0x68,0x77,0x00,0x00};
/**************************** PROTOTYPES *****************************/
void Hi_folks(void);
int Get_target(void);
void Fill_header(int,char **,int);
int Get_release(int);
unsigned long Calc_key0(int,unsigned long *,unsigned long **);
void Calc_coef(int,int,unsigned long ***,unsigned long **,int ***,int **,
int **);
void Calc_pwd_bound(int,int,unsigned long,unsigned long,unsigned long *,
unsigned long **,unsigned long **);
int Check_key1(unsigned long,unsigned long);
void Calc_key0_bound(unsigned long,unsigned long,unsigned long *,
unsigned long *);
void Check_parity(unsigned long,int,int,int *,int *,int **,int **);
void Check_inter(int,int,int *,int **,unsigned long,unsigned long,
unsigned long *,unsigned long *,int **);
void Check_inter4(int,int,int *,int **,int *,unsigned long,
unsigned long,unsigned long *,unsigned long *);
int Next_pwd(int,unsigned long,unsigned long,int,int,int *,
unsigned long **,unsigned long **);
int Adj_parity(int,int,int,int,unsigned long,unsigned long **);
void Adj_char(int,unsigned long,unsigned long,unsigned long,unsigned long,
unsigned long,unsigned long *,unsigned long *,int);
void Wait_key();
void Print_pwd(int,unsigned long *);
unsigned long Get_key_chk(int);
/****************************** MAIN *******************************/
main()
{
int pwd_len_min=1;
int pwd_len_max=56;
unsigned long char_min,char_max;
unsigned long char_min_no_ext=0x20; // SPACE
unsigned long char_max_no_ext=0x7E; // ~
unsigned long char_min_ext=0xFFFFFFE7;
unsigned long char_max_ext=0xFFFFFFF6;
unsigned long char_min_adj,char_max_adj;
unsigned long const_or = 0x06A30DE8;
unsigned long const_mul = 0x000343FD;
unsigned long const_add = 0x00269EC3;
unsigned long mask = 0x7FFF0000;
unsigned long key0,key1,key_chk;
unsigned long key_a,key_b,key_c,key_d,key_e,key_f,key_g,key_tmp; //temp vars
unsigned long key_right,last_key1,step,delta_key;
int done_half,done_all,use_mask,too_high,failed,pwd_found,char_ext;
int const_or_odd,key1_odd,nb_zone_ok,i,len;
float combi;
int fn; //encrypted file'handle
int ver; //26 or 35
unsigned long **Coef;
unsigned long *Coef_sum;
int **Odd;
int *Odd_nb;
int *Last_odd;
int *Parity_ok;
int *Zone_ok;
int *Intersection;
unsigned long *Pwd;
unsigned long *Bound_min;
unsigned long *Bound_max;
unsigned long key0_min,key0_max;
Pwd=(unsigned long *)malloc(sizeof(unsigned long)*pwd_len_max);
Parity_ok=(int *)malloc(sizeof(int)*(pwd_len_max+1));
Zone_ok=(int *)malloc(sizeof(int)*(pwd_len_max+1));
Intersection=(int *)malloc(sizeof(int)*(pwd_len_max+1));
//for Crypto v3.5, 3 steps:
//step 1 : read key_chk from cipher's header
//step 2 : find 1 or more key1 compatible with key_chk
//step 3 : find a Password and a key0 compatible with each key1 found
//for Crypto v2.6, 2 steps only (as key_chk = key1):
//step 1 : read key_chk = key1 from cipher's header
//step 2 : find a Password and a key0 compatible with key1
Hi_folks();
fn=Get_target();
ver=Get_release(fn);
key_chk=Get_key_chk(fn);
//solve for key_chk
Calc_coef(pwd_len_min,pwd_len_max,&Coef,&Coef_sum,&Odd,&Odd_nb,&Last_odd);
//One loop for non-extended characters, one loop for extended characters
for(char_ext=0;char_ext<=1;char_ext++)
{
if(!char_ext) {char_min=char_min_no_ext; char_max=char_max_no_ext;}
else {char_min=char_min_ext; char_max=char_max_ext;}
Calc_pwd_bound(pwd_len_min,pwd_len_max,char_min,char_max,Coef_sum,
&Bound_min,&Bound_max);
const_or_odd=(const_or&0x00000001); //0:even 1:odd
step=((0xFFFFFFFF/(0x00010000+const_mul))+1);
key_right=(key_chk*0x00010000); //with key_chk=12345678 : key_right=56780000
done_half = 0;
done_all = 0;
use_mask = 0;
if(ver==26) {key1=key_chk;}
else
{key1=((key_right+0x00007FFF-const_add+(use_mask*0x80000000))/(0x00010000+const_mul));}
do
{
too_high = 0;
key_tmp=((0x00010000+const_mul)*key1+const_add-(use_mask*0x80000000));
//check if key1 OK
if(((key_tmp >= key_right) && (key_tmp <= (key_right+0x0000FFFF))) || (ver==26))
{
key_a = (const_mul * key1 + const_add);
//check masking
if((((key_a < 0x80000000) && (use_mask == 0)) ||
((key_a >= 0x80000000) && (use_mask == 1))) || (ver==26))
{
key_b = key_a & mask;
key_c = key_b / 0x10000;
key_d = key_a * const_mul + const_add;
key_e = key_d & mask;
key_f = key_c + key_e;
key_g = key_f + key1;
if((key_g == key_chk) || (ver==26))
{
for(i=0;i<=pwd_len_max;i++) {Zone_ok[i]=1;}
if((Check_key1(key1,const_or)) || (ver==26))
{//solve for key1
key1_odd=(key1&0x00000001); //0:even 1:odd
Calc_key0_bound(const_or,key1,&key0_min,&key0_max);
nb_zone_ok=pwd_len_max-pwd_len_min+1;
if(!const_or_odd)
{
Check_parity(key1,pwd_len_min,pwd_len_max,Odd_nb,&nb_zone_ok,&Zone_ok,
&Parity_ok);
}
if(nb_zone_ok)
{
Check_inter(pwd_len_min,pwd_len_max,&nb_zone_ok,&Zone_ok,
key0_min,key0_max,Bound_min,Bound_max,&Intersection);
}
if(nb_zone_ok)
{
Check_inter4(pwd_len_min,pwd_len_max,&nb_zone_ok,&Zone_ok,Intersection,
key1,const_or,Bound_min,Bound_max);
}
if(nb_zone_ok)
{
pwd_found=0;
failed=0;
for(len=pwd_len_min;len<=pwd_len_max;len++)
{//search pwd in each valid zone
if(Zone_ok[len])
{//start iterations
Adj_char(Intersection[len],Coef_sum[len],key0_min,key0_max,
char_min,char_max,&char_min_adj,&char_max_adj,char_ext);
pwd_found=0;
failed=0;
combi=0;
for(i=0;i<len;i++) {Pwd[i]=char_min_adj;}
do
{
combi++;
key0=Calc_key0(len,Pwd,Coef);
if((key0 | const_or) == key1) {pwd_found=1;}
else
{
if(!Next_pwd(len,char_min_adj,char_max_adj,const_or_odd,key1_odd,
Last_odd,Coef,&Pwd))
{
failed=1;
}
}
} while((!pwd_found) && (!failed));
}//stop iterations
if(pwd_found)
{
Print_pwd(len,Pwd);
Wait_key();
//break;
exit(0);
}
}//each len
if(!pwd_found) {printf("\n%08lX : [%02d] : PWD NOT FOUND)",key1,len,combi);}
}
}//each key1 found
}
}
}
//go on searching
if(key_tmp > (key_right+0x0000FFFF))
{
delta_key=(key_tmp-key_right);
too_high=1;
}
else
{
delta_key = ((key_right+0x0000FFFF)-key_tmp);
}
//check delta
if(delta_key >= (0x00010000+const_mul))
{
if(too_high) {key1--; }
else {key1++; }
}
else
{
last_key1=key1;
key1+=step;
if(key1 <= last_key1)
{
if(done_half) {done_all = 1;}
else
{
done_half = 1;
use_mask = 1;
key1=(((key_right+0x00007FFF)-const_add+(use_mask*0x80000000))/(0x00010000+const_mul));
}
}
}
} while(!done_all); //stop when no more key1 to try
}//2 loops
exit(0);
}
/***********************************************************************/
/************************** FUNCTIONS ******************************/
/***********************************************************************/
/***********************************************************************/
/* If Intersection is of type 1 2 3 we increase char_min and/or */
/* decrease char_max so we search only in the useful zone */
/* |------ key0 ------| */
/* before adjust: |-------- search zone --------| */
/* after adjust: |-- search zone --| */
void Adj_char(int intersection,unsigned long coef_sum,
unsigned long key0_min, unsigned long key0_max,
unsigned long char_min,unsigned long char_max,
unsigned long *char_min_adj,unsigned long *char_max_adj,
int char_ext)
{
unsigned long min,max;
if((intersection==0) || (intersection==4) || (char_ext))
{
*char_min_adj=char_min;
*char_max_adj=char_max;
return;
}
//intersection 1 2 3
min=floor(key0_min/coef_sum);
if(min<char_min) {min=char_min;}
max=ceil(key0_max/coef_sum);
if(max>char_max) {max=char_max;}
if(intersection==1)
{*char_min_adj=min; *char_max_adj=max; return;}
if(intersection==2)
{*char_min_adj=min; *char_max_adj=char_max; return;}
if(intersection==3)
{*char_min_adj=char_min; *char_max_adj=max; return;}
}
/***********************************************************************/
/* If key0 must be odd, then we must multiplicate at least 1 odd */
/* coeficient by 1 odd character. */
/* If the character which is multiplied by the odd coeficient is even, */
/* then we add 1 to the character, if possible */
/* e.g: coeficient EVEN ODD EVEN EVEN EVEN */
/* before adjust: character 20 20 20 20 20 */
/* after adjust: character 20 21 20 20 20 */
/* return 0 if can't adjust parity, otherwise return 1 */
int Adj_parity(int const_or_odd,int key0_odd,int key1_odd,int last_odd,
unsigned long char_max,unsigned long **Pwd)
{
if(const_or_odd) {return(1);} //no need to adjust parity
if(key0_odd == key1_odd) {return(1);} //no need to adjust parity
if((*Pwd)[last_odd] == char_max) {return(0);} //can not adjust parity
else {(*Pwd)[last_odd]++; return(1);} //parity adjusted
}
/***********************************************************************/
/* Password is made of n characters, for each character Pwd[i] we have:*/
/* char_min <= Pwd[i] <= char_max */
/* Every possible password is tried, until good password is found. */
/* This function calculates a new password to try. */
/* e.g.: password's lenght=5, char_min=0x41 ("A"), char_max=0x5A ("Z") */
/* 41 41 41 41 41 <--- first password to try */
/* 41 41 41 41 42 */
/* . . . . . */
/* 41 41 41 42 41 */
/* . . . . . */
/* 5A 5A 5A 5A 5A <--- last password to try */
/* Return 1 if there is a new password to try */
/* Return 0 if no more password to try */
int Next_pwd(int len,unsigned long char_min,unsigned long char_max,
int const_or_odd,int key1_odd,int *Last_odd,
unsigned long **Coef,unsigned long **Pwd)
{
int i,found,failed;
int key0_odd;
unsigned long key0;
i=(len-1);
found=0;
failed=0;
do
{
(*Pwd)[i]++;
if( ((*Pwd)[i]<=char_max) && ((*Pwd)[i]!=0))
{
key0=Calc_key0(len,*Pwd,Coef);
key0_odd=(key0&0x00000001); //0:even 1:odd
if(Adj_parity(const_or_odd,key0_odd,key1_odd,Last_odd[len],char_max,Pwd))
{
found=1;
}
else
{
if(i) {(*Pwd)[i]=char_min; i--;}
else {failed=1;}
}
}
else
{
if(i) {(*Pwd)[i]=char_min; i--;}
else {failed=1;}
}
} while((!found) && (!failed));
if(found) {return(1);}
else {return(0);}
}
/***********************************************************************/
/* If Intersection is of type 4, we are not sure that a valid key0 */
/* (i.e. a key0 such as: key0 OR or_const = key1) can be found in zone */
/* because neither key0_min nor key0_max are included in search space */
/* case 4: |------- k0 -------| <-- key0 belongs to this space */
/* |-- key --| <-- we search here B_min<=key<=B_max */
/* so we check that B_min and B_max are not both wrong and similar */
/* for instance: B_min OR const_or != key1 */
/* B_max OR const_or != key1 */
/* high bits low bits */
/* B_min = 000011111001101111000000............... */
/* B_max = 000011111001101111111100............... */
/* < similarity * > */
/* | */
/* wrong bit */
/* B_min and B_max are similar and wrong, so we skip this zone */
void Check_inter4(int pwd_len_min,int pwd_len_max,int *nb_zone_ok,
int **Zone_ok,int *Intersection,unsigned long key1,
unsigned long const_or,unsigned long *Bound_min,
unsigned long *Bound_max)
{
int i,len,bad_bit,bad_bit_pos,same_start;
unsigned long o_v_bit,bound_min_bit,bound_max_bit,key1_bit,mask;
for(len=pwd_len_min;len<=pwd_len_max;len++)
{
if(Intersection[len]==4)
{
bad_bit=0; mask=0x80000000;
for(i=31;i>=0;i--)
{
o_v_bit=(const_or & mask);
if(!o_v_bit)
{
bound_min_bit=(Bound_min[len] & mask);
key1_bit=(key1 & mask);
if(bound_min_bit!=key1_bit)
{
bad_bit=1;
bad_bit_pos=i;
break;
}
}
mask/=2;
}
if(bad_bit)
{
same_start=1; mask=0x80000000;
for(i=31;i>=bad_bit_pos;i--)
{
bound_min_bit=(Bound_min[len] & mask);
bound_max_bit=(Bound_max[len] & mask);
if(bound_min_bit!=bound_max_bit) {same_start=0; break;}
mask/=2;
}
if(same_start)
{
if((*Zone_ok)[len])
{
(*Zone_ok)[len]=0;
(*nb_zone_ok)--;
}
}
}
}
} //each pwd_len
}
/***********************************************************************/
/* We have: */
/* Good Zone (GZ) : k0_min <= key0 <= k0_max */
/* Search Zone (SZ) : B_min <= key0 <= B_max */
/* Given k0_min, k0_max, B_min, B_max, 5 intersection cases possible: */
/* */
/* case 0: |--- GZ ---| or |--- GZ ---| */
/* |--- SZ ---| |--- SZ ---| */
/* */
/* case 1: |--- GZ ---| */
/* |---------- SZ ----------| */
/* */
/* case 2: |------- GZ -------| */
/* |--------- SZ ---------| */
/* */
/* case 3: |----- GZ -----| */
/* |---------- SZ ----------| */
/* */
/* case 4: |------------ GZ ------------| */
/* |-- SZ --| */
/* so: */
/* if case = 0: skip zone, otherwise: keep zone */
void Check_inter(int pwd_len_min,int pwd_len_max,int *nb_zone_ok,
int **Zone_ok,unsigned long key0_min,unsigned long key0_max,
unsigned long *Bound_min,unsigned long *Bound_max,
int **Intersection)
{
int len,key1_odd;
for(len=pwd_len_min;len<=pwd_len_max;len++)
{
if((Bound_max[len]<key0_min) || (Bound_min[len]>key0_max))
{
(*Intersection)[len]=0;
if((*Zone_ok)[len])
{
(*Zone_ok)[len]=0; //null intersection: bad zone
(*nb_zone_ok)--;
}
}
else if(Bound_min[len]<=key0_min)
{
if(Bound_max[len]>=key0_max) {(*Intersection)[len]=1;}
else {(*Intersection)[len]=2;}
}
else
{
if(Bound_max[len]>=key0_max) {(*Intersection)[len]=3;}
else {(*Intersection)[len]=4;}
}
}
}
/***********************************************************************/
/* we have: key0 OR const_or = key1 */
/* remember that: */
/* ODD OR ODD = ODD */
/* ODD OR EVEN = ODD */
/* EVEN OR EVEN = EVEN */
/* key0 = weighted sum of Password's characters */
/* = Coef[len][0]*Pwd[0] + ... + Coef[len][len-1]*Pwd[len-1] */
/* remember too that: */
/* ODD * ODD = ODD ODD + ODD = EVEN */
/* ODD * EVEN = EVEN ODD + EVEN = ODD */
/* EVEN * EVEN = EVEN EVEN + EVEN = EVEN */
/* so if key1 is ODD and const_or is EVEN, key0 must be ODD */
/* and to obtain an ODD key0, you must have at least 1 ODD coeficient */
/* this function checks that key1 can effectively be obtained using */
/* calculated coeficients */
/* Parity_ok = 1: no problem, key1 can be obtained: keep zone */
/* Parity_ok = 0: wrong, key1 can not be obtained: skip zone */
void Check_parity(unsigned long key1,int pwd_len_min,int pwd_len_max,
int *Odd_nb,int *nb_zone_ok,int **Zone_ok,int **Parity_ok)
{
int len,key1_odd;
key1_odd=(key1&0x00000001); //0:even 1:odd
for(len=pwd_len_min;len<=pwd_len_max;len++)
{
if(key1_odd && !Odd_nb[len])
{
(*Parity_ok)[len]=0;
if((*Zone_ok)[len])
{
(*Zone_ok)[len]=0;
(*nb_zone_ok)--;
}
}
else {(*Parity_ok)[len]=1;}
}
}
/***********************************************************************/
/* we look for key0_min and key0_max: key0_min <= key0 <= key0_max */
/* key1 and const_or are known */
/* key0_min: smallest key0 value such as: key0_min OR const_or = key1 */
/* key0_max: largest key0 value such as: key0_max OR const_or = key1 */
void Calc_key0_bound(unsigned long const_or,unsigned long key1,
unsigned long *key0_min,unsigned long *key0_max)
{
*key0_max=key1;
*key0_min=key1-const_or;
}
/***********************************************************************/
/* we have: key0 OR const_or = key1 */
/* at this point, we don't know key0 but we can check that key1 is */
/* compatible with const_or (const_or is a known constant) */
/* so we check, at BIT level, that: const_or[ 0] < or = key1[ 0] */
/* const_or[ 0] < or = key1[ 0] */
/* ... */
/* const_or[31] < or = key1[31] */
/* return 1 if compatible, 0 otherwise */
int Check_key1(unsigned long key1,unsigned long const_or)
{
int i;
unsigned long o_v_bit, key1_bit, mask=1;
for(i=0;i<32;i++)
{
o_v_bit=(const_or & mask);
key1_bit=(key1 & mask);
if(o_v_bit>key1_bit) {return(0); /*no good*/}
mask*=2;
}
return(1); //OK
}
/***********************************************************************/
/* Coeficient depend only on: */
/* - 2 hash tables (H1 and H2) */
/* - password's lenght (len) */
/* - coeficient's position (l) */
/* */
/* Coeficient[len][l] = Hash_1[len+l] * Hash_2[l] * l */
void Calc_coef(int pwd_len_min,int pwd_len_max,unsigned long ***Coef,
unsigned long **Coef_sum,int ***Odd,int **Odd_nb,
int **Last_odd)
{
int i,l,len;
unsigned long h1h2,h1h2l;
(*Coef)=(unsigned long **)malloc(sizeof(unsigned long *)*(pwd_len_max+1));
(*Odd)=(int **)malloc(sizeof(int *)*(pwd_len_max+1));
(*Coef_sum)=(unsigned long *)malloc(sizeof(unsigned long)*(pwd_len_max+1));
(*Odd_nb)=(int *)malloc(sizeof(int)*(pwd_len_max+1));
(*Last_odd)=(int *)malloc(sizeof(int)*(pwd_len_max+1));
for(len=pwd_len_min;len<=pwd_len_max;len++)
{
(*Coef)[len]=(unsigned long *)malloc(sizeof(unsigned long)*len);
(*Odd)[len]=(int *)malloc(sizeof(int)*len);
}
for(len=pwd_len_min;len<=pwd_len_max;len++)
{
(*Odd_nb)[len]=0;
(*Coef_sum)[len]=0;
for(l=0;l<len;l++)
{
h1h2=Hash_1[l+len]*Hash_2[l];
h1h2l=h1h2*(l+1);
(*Coef)[len][l]=h1h2l;
(*Coef_sum)[len]+=h1h2l;
if(h1h2l&0x00000001)
{
(*Odd)[len][l]=1;
(*Odd_nb)[len]++;
(*Last_odd)[len]=l;
}
else {(*Odd)[len][l]=0;}
}
}
}
/***********************************************************************/
/* we have: */
/* key0 = Co[len][0]*Pwd[0] + ... + Co[len][len-1]*Pwd[len-1] */
/* so the smallest value we can obtain for key0 is: */
/* B_min[len] = Co[len][0]*char_min + ... + Co[len][len-1]*char_min */
/* = Coef_sum[len]*char_min */
/* and the greatest value: */
/* B_max[len] = Co[len][0]*char_max + ... + Co[len][len-1]*char_max */
/* = Coef_sum[len]*char_max */
/* B_min and B_max delimit a search zone */
void Calc_pwd_bound(int pwd_len_min,int pwd_len_max,
unsigned long char_min,unsigned long char_max,
unsigned long *Coef_sum,
unsigned long **Bound_min,unsigned long **Bound_max)
{
int len;
unsigned long tmp;
(*Bound_min)=(unsigned long *)malloc(sizeof(unsigned long)*(pwd_len_max+1));
(*Bound_max)=(unsigned long *)malloc(sizeof(unsigned long)*(pwd_len_max+1));
for(len=pwd_len_min;len<=pwd_len_max;len++)
{
(*Bound_min)[len]=Coef_sum[len]*char_min;
(*Bound_max)[len]=Coef_sum[len]*char_max;
}
}
/***********************************************************************/
/* key0 = weighted sum of Password's characters */
/* = Coef[len][0]*Pwd[0] + ... + Coef[len][len-1]*Pwd[len-1] */
/* return key0 */
unsigned long Calc_key0(int len,unsigned long *Pwd,unsigned long **Coef)
{
int i;
unsigned long key0;
key0=0;
for(i=0;i<len;i++)
{
key0+=(Coef[len][i]*Pwd[i]);
}
return(key0);
}
/***********************************************************************/
void Hi_folks(void)
{
printf("\n\nYet Another Password Cracker by CASIMIR {:-)");
printf("\n-> Target: Crypto v2.6/3.5 by Gregory Braun\n");
}
/***********************************************************************/
/* 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: secret.(=txt=) or secret.(_t ]? ");
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 (=txt=) or (_t)!\n");
Wait_key(); exit(0);
default: /*printf("\nOK, FILE FOUND")*/; return(fn);
}
}
/***********************************************************************/
/* Header from encrypted file has following structure: */
/* */
/* v2.6: CryptoHeader????pathfilename.............encryptedfile */
/* v3.5: CryptoHdrBlk????pathfilename.............encryptedfile */
/* <------------- 276 bytes --------------->< original > */
/* size */
/* The ???? is the key_chk we're looking for. */
unsigned long Get_key_chk(int fn)
{
unsigned long *Buffer;
//start reading on byte 12
lseek(fn,12,0);
//read 4 bytes
read(fn,Buffer,4);
close(fn);
return(*Buffer);
}
/***********************************************************************/
/* The 12 first characters from header tell us which release of Crypto */
/* was used to encrypt file: */
/* CryptoHeader <=> v2.6 */
/* CryptoHdrBlk <=> v3.5 */
int Get_release(int fn)
{
char *tmp;
tmp=(char *)malloc(sizeof(char)*13);
read(fn,tmp,12);
tmp[12]='\0';
if(!strcmp(tmp,"CryptoHeader")) {return(26);}
else {return(35);}
}
/***********************************************************************/
/* wait for key pressed */
void Wait_key()
{
printf("\n");
printf(" ******************\n");
printf(" * hit any key... *\n");
printf(" ******************\n");
getch(); {/* wait until key pressed */} //kbhit
}
/***********************************************************************/
/* display password */
void Print_pwd(int pwd_len,unsigned long *Pwd)
{
int i;
int pwd_char;
printf("\n\n ASCII seq: ");
for(i=0;i<pwd_len;i++)
{//normal character : 000000XX extended character : FFFFFFXX
if(Pwd[i]<0x80) {pwd_char=Pwd[i];}
else {pwd_char=(Pwd[i]-0xFFFFFF00);}
printf("[%d]",pwd_char);
if((i+1)%10==0) {printf("\n ");}
}
printf("\n\n PASSWORD: >>>");
for(i=0;i<pwd_len;i++)
{
if(Pwd[i]<0x80) {pwd_char=Pwd[i];}
else {pwd_char=(Pwd[i]-0xFFFFFF00);}
printf("%c",Pwd[i]);
}
printf("<<< (%d characters)\n\n",pwd_len);
printf("(don't type >>> and <<<)\n");
}
Here is the executableCopyright September 1999, January 2000 by Casimir.
Mail Casimir
Converted to hypertext by Joe Peschel September 20, 1999; revised January 8, 2000.