by
CASIMIR
Part C
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
Click here for the executable crack, source code, and a file to crack.#include #include #include #include #include #include #include #include #include #include #include #include #include // 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 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 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[Pos[i]] found */ void Solver_m1(int pwd_len,int *H,int *R,int *Pos,int **Pwd) { int i,sum; for(i=0;i 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 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 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 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 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 >>"); for(i=0;i >> 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 5 */ /* [1] ------> 6 */ /* ... 70123 */ /* [7] ------> 4 */ void Build_pos_m2(int name_len,int pwd_len,int **Pos) { int i; for(i=0;i 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"); }
Copyright December 1998 by Casimir.
Mail Casimir
Converted to hypertext by Joe Peschel December 18, 1998.