The Cracking of SecurityPlus

by

CASIMIR

Part C

Caz presents : The Crack of SecurityPlus! by SoftByte Labs


(known-plaintext attack on a proprietary cipher)



PART C. 'C' SOURCE CODE FOR CRACKER : CrackSP!

/****************************** BEGIN *******************************/
#include <stdio.h>
#include <string.h>
#include <io.h>
#include <stdlib.h>
#include <dos.h>
#include <conio.h>
#include <fcntl.h>
#include <alloc.h>
#include <malloc.h>
#include <errno.h>
#include <math.h>



/*************************** PROTOTYPES ******************************/
void Read_Key_enc(int,unsigned char **);
void Calc_Pwd_start(unsigned char *,int,unsigned char **);
void Calc_Sum(int,unsigned char *,unsigned char **);
void Calc_Pwd(int,unsigned char *,unsigned char *,unsigned char **);
int Check_Pwd(int,unsigned char *,unsigned char *,unsigned char *);
void Hi_folks(void);
int Get_target(void);
void Wait_key();
void Print_pwd(int,unsigned char *);

/***************************** GLOBALS *******************************/
const int key_start_pos = 61;
const int key_len = 61;

static unsigned char Key_chk[] = "*+*This file encrypted with SecurityPlus! "
				 "(C)SoftByte Labs*+*";

/****************************** MAIN ********************************/
main()
{
int i,fn,extended;
int pwd_len;
int pwd_len_min=5;
int pwd_len_max=60;
unsigned char *Pwd;
unsigned char *Key_enc;
unsigned char *Key_dec;
unsigned char *Sum;

//memory allocation & initialisation
Pwd    =(unsigned char *)malloc(sizeof(unsigned char)*key_len);
Key_enc=(unsigned char *)malloc(sizeof(unsigned char)*key_len);
Key_dec=(unsigned char *)malloc(sizeof(unsigned char)*key_len);
Sum    =(unsigned char *)malloc(sizeof(unsigned char)*key_len);
for(i=0;i<key_len;i++) {Pwd[i]=0; Key_enc[i]=0; Key_dec[i]=0; Sum[i]=0;}

//start searching
Hi_folks();
fn=Get_target();
Read_Key_enc(fn,&Key_enc);
//round 1 of 2 : Pwd's first character NOT extended
//round 2 of 2 : Pwd's first character extended
extended=0;
for(extended=0;extended<=1;extended++)
   {
   Calc_Pwd_start(Key_enc,extended,&Pwd);
   //for each pwd_len
   for(pwd_len=pwd_len_min;pwd_len<=pwd_len_max;pwd_len++)
      {
      Calc_Sum(pwd_len,Pwd,&Sum);
      Calc_Pwd(pwd_len,Sum,Key_enc,&Pwd);
      if(!Check_Pwd(pwd_len,Sum,Key_enc,Pwd))
	 {
	 Print_pwd(pwd_len,Pwd);
	 exit(0);
	 }
      }
   }
}
/***********************************************************************/
/**************************   FUNCTIONS   ******************************/
/***********************************************************************/

/***********************************************************************/
int Check_Pwd(int pwd_len,unsigned char *Sum,unsigned char *Key_enc,
	      unsigned char *Pwd)
{
int i,pos;
unsigned char temp;

temp=(Key_enc[0]-Pwd[0]-Pwd[0]-Pwd[pwd_len-1]-key_len);
if(Key_chk[0]!=temp) return(1);

for(i=pwd_len;i<(key_len-1);i++)
   {
   pos=fmod(i,pwd_len);
   temp=(Key_enc[i+1]-Key_enc[i]-Key_chk[i+1]-(key_len-i-1)-Sum[i+1]);
   if(Pwd[pos]!=temp) return(1);
   }

return(0);
}

/***********************************************************************/
void Calc_Pwd(int pwd_len,unsigned char *Sum,unsigned char *Key_enc,
	      unsigned char **Pwd)
{
int i;

for(i=1;i<pwd_len;i++)
   {
   (*Pwd)[i]=(Key_enc[i+1]-Key_enc[i]-Key_chk[i+1]-(key_len-i-1)-Sum[i+1]);
   }
}

/***********************************************************************/
void Calc_Sum(int pwd_len,unsigned char *Pwd,unsigned char **Sum)
{
int i,pos;

(*Sum)[0]=Pwd[0];
for(i=1;i<key_len;i++)
   {
   pos=fmod(i,pwd_len);
   if(!pos)
      {
      pos=pwd_len;
      }
   (*Sum)[i]=((*Sum)[i-1] + pos);
   }
}

/***********************************************************************/
void Calc_Pwd_start(unsigned char *Key_enc,int extended,unsigned char **Pwd)
{
(*Pwd)[0] = ((Key_enc[1] - Key_enc[0] - Key_chk[1] - key_len));
(*Pwd)[0] /=2;
if(extended) (*Pwd)[0]+=0x80;
}

/***********************************************************************/
void Read_Key_enc(int fn,unsigned char **Key_enc)
{
int i;
unsigned char Buffer[key_len];

lseek(fn,key_start_pos,0);
read(fn,Buffer,key_len);
for(i=0;i<key_len;i++)
   {
   (*Key_enc)[i]=Buffer[i];
   }
}

/***********************************************************************/
void Hi_folks(void)
{
printf("\n\nYet Another Password Cracker by CASIMIR {:-)");
printf("\n-> Target: SecurityPlus! v4.32 by SoftByte Labs\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.sp$]?   ");
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: SP$ or SP% ) !\n");
   Wait_key(); exit(0);
   default: /*printf("\nOK, FILE FOUND")*/; return(fn);
   }
}

/***********************************************************************/
/*                   wait for key pressed                              */
void Wait_key()
{
printf("\n");
printf("              ******************\n");
printf("              * hit any key... *\n");
printf("              ******************\n");
getch();       //kbhit
}

/***********************************************************************/
/*                        display password                             */
void Print_pwd(int pwd_len,unsigned char *Pwd)
{
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 >>> or <<<)\n");
}

/******************************* END ********************************

And now, for those who are still with me:

* BONUS TRACKS * BONUS TRACKS * BONUS TRACKS *

3 crypto-software which deserve, IMO, the Snake-Oil award. They require no programming in order to break them, only a patch.

I just put them here, in case someone cares...

Rocny! v3.4 (Evaluation) by NIZAR Developers

Here is Rocny! 3.4

This one decrypts password from encrypted file in order to compare it to input... Bad idea. Even worst, it uses a VisualBasic function to perform the check (__vbaStrCmp)!!!

module RO34EVAL.EXE

:446034    mov eax , [ebp-44]            <--- good password

           push eax

           mov ecx , [44A09C]            <--- our input

           push ecx

           call [MSVBVM50!__vbaStrCmp]   <--- sic!

Look at the help file: on every footer, you'll see this sentence:

                You Are the Most Important for Us

Pathetic...

Exe Protect by Frederic Collin

Here is Exe Protect

Same mistake, but without the VB function. Here lays the password checking mechanism of main window:

module EXEPROT.EXE

:403BC1    mov ecx , [esi]   <--- our input

           mov ebx , [edi]   <--- good password

           cmp ecx , ebx

Once you're in, you can unlock every file previously locked.

Encryption Lock Magic! v1.0 by Kaboom JSP

Here is Encryption Lock Magic

Yeap, you guessed it, the same old mistake again...

module ENCLOCKMAGIC.EXE

:4510DB    mov edx , [ebp-2c]     <--- good password

           mov eax , [ebp-1c]     <--- our input

           call 403D38            <--- comparaison routine

Hope you enjoyed!

Caz

Copyright December 1999 by Casimir.

Mail Casimir

Converted to hypertext by Joe Peschel December 14, 1999.