Zipcrack Source Code
by Nickle of Group42
This is a zipcrack program I wrote a few years ago. It only cracks
v1.1 zip files and requires you to rename pkunzip.exe unzip.exe. It
uses an interesting way to check if the password is correct that could
be used on a version 2.0 cracker that would allow you to hack on
a zipped file that only contains 1 zipped file.
/////////////////////////////////////////////////////////////////////
// Zipcrack.c
//
// This program tries to crack password protected Zip(v1.1) files.
//
// (c)1991 By Nickle/Group42 group42@sonic.net
//
// Please send me any cool enhancements for this code.
//
// Compiled with microsquishy C 6.0 with max optimization.
//////////////////////////////////////////////////////////////////////
#include "stdio.h"
#include "string.h"
unsigned char dos_string[128];
unsigned char delete_file[128];
#define DWORD unsigned long
#define WORD unsigned int
#define BYTE unsigned char
#define USGC unsigned char
#define USGI unsigned
#define USGL unsigned long
#define MAXDIGHACK 8
#define GOOD_CRC32_RESIDUAL 0xdebb20e3L
USGL crctable[256]; // global accessible //
USGI crc2find; // crc 2 find //
BYTE sig[] = {0x50,0x4b,0x03,0x04};
BYTE error_sig[] ={'e','r','r','o','r','s','!'};
unsigned long crc32();
void generatetable();
unsigned char decrypt_byte();
int maxdighack = MAXDIGHACK;
//unsigned char preamble[10];
//unsigned char postamble[10];
int ffflag=0;
main(argc, argv)
int argc;
char *argv[];
{
unsigned char passcode[25];
unsigned char buffer[25];
unsigned char lookfile[25];
unsigned char inbuff[25];
unsigned char zipname[25];
FILE *zipfile;
int end,i,j,skip,len;
printf("\nZipcrack V0.1b - (c)1991 by Mycal Johnson - mycal@netacsys.com\n\n");
if(argc==1)
{
printf("\n Usage: 'zipcrack zipfile crackfile'");
printf("\n zipfile = filename.zip ");
printf("\n crackfile = file in the zipfile to crack\n\n");
exit(2);
}
i=strlen(argv[1]);
if(i>8)
{
printf("\n Filename must be 8 characters or less, do not incude .zip extention \n\n");
exit(2);
}
strcpy(zipname,argv[1]);
strcat(zipname,".zip");
i=strlen(argv[2]);
if(i>12)
{
printf("\n Filename to hack cannot be more than 12 characters including extention\n\n");
exit(2);
}
strcpy(lookfile,argv[2]);
strupr(lookfile);
strupr(zipname);
//
// make unzip try string
//
strcpy(dos_string,"unzip ");
strcat(dos_string,argv[1]);
strcat(dos_string," ");
strcat(dos_string,lookfile);
strcat(dos_string," -s");
strcpy(delete_file,"del ");
strcat(delete_file,lookfile);
//
// check to see if target already exists
//
if((zipfile = fopen(lookfile,"r+b")) != NULL)
{
close(zipfile);
printf("\nWarning %s already exists on disk.",lookfile);
printf("\n Delete this file and try again.");
exit(1);
}
if ((zipfile = fopen(zipname,"r+b")) == NULL )
{
printf("fopen failed. Cannot find/open %s.\n",zipname);
exit(2);
}
i = 0;
end=0;
//
// Here we search for file to hack on inside the zip file. First we
// look for the local file sig then we check to see if its our file.
//
while(!end)
{
if(fread(buffer, sizeof(char),1,zipfile))
{
if(buffer[0] == sig[i])
i = i + 1;
else
i = 0;
if (i == 4)
{ // sig is 4 digits
len=strlen(lookfile);
skip = 26;
if(fseek(zipfile, (long)skip, SEEK_CUR)!=0)
{
printf("fseek fail\n");
exit(1);
}
if(fread(inbuff, sizeof(char),len,zipfile))
{
if(!memcmp(lookfile,inbuff,len))
end=1;
else
i=0;
}
else
{
printf("read failed\n");
exit(1);
}
}
}
else
end = 2; // end of file
}
//
// We couldn't find the file to hack if end = 2;
//
if(end == 2) {
printf("File to hack not in found in Zipfile.\n");
exit(2);
}
//
// Read encryption header
//
if(!fread(buffer, sizeof(char),12,zipfile))
{
printf("Cannot read from Zipfile. fread fail\n");
exit(2);
}
skip = -(len+16+12); // - len of filename + crc offset + encript headder
if(fseek(zipfile, (long)skip, SEEK_CUR)!=0)
{
printf("fseek fail\n");
exit(1);
}
if(fread(inbuff, sizeof(char),4,zipfile))
{
printf(" crc from file = %x : %x \n",((inbuff[3]<<8)|inbuff[2]),
((inbuff[1]<<8)|inbuff[0]));
crc2find = ((inbuff[3]<<8)|inbuff[2]);
}
else
{
printf("fread2 fail");
exit(2);
}
close(zipfile);
buffer[12]=0;
if(crackzip(passcode,buffer))
{ // buffer contains encription header //
// returns hacked key in passcode //
printf("\nWe hack success!\n\nKey is '%s'\n\n",passcode);
printf("Thanx to your pal mycal@netacsys.com\n");
exit(0);
}
else
{
printf("\nBummer, I couldn't hack it.\n");
exit(1);
}
}
crackzip(passcode, buffer)
char *passcode;
char *buffer;
{
unsigned long key[3];
unsigned char hackbuff[19];
unsigned char password[50];
unsigned char dos_try[128];
unsigned int i,end, result,slen;
generatetable(); // generate 32-bit crc table //
//
// Set password to 'a' and the rest nil, set up end flag
//
end = 0;
for(i=0;i<50;i++) // init password to nil //
password[i]=0;
strcpy(password,"a");
//
// this is where the main hack loop is, we loop here tell we crack the
// password or forever, whichever is first.
//
while(!end){
memcpy(hackbuff,buffer,15); // reset buffer to origin
key[0] = 305419896L; // reset key to start
key[1] = 591751049L;
key[2] = 878082192L;
//
// initilize key with password
//
slen = strlen(password);
for(i=0; i<slen;i++)
update_keys(key,password[i]);
//
// try the decript
//
if(!decript_head(hackbuff,key))
{
//
// no CRC match, get next password to try, try again
//
update_password(password);
if(strlen(password)>maxdighack)
{
return(0);
end=2;
}
}
else
{
//
// We have a CRC match, so lets try to unzip the file
//
printf(" -- possible password is %s. Trying it now... \n",password);
strcpy(dos_try,dos_string);
strcat(dos_try,password);
strcat(dos_try," > zipcrack.err");
result=system(dos_try);
if(!chk_4_errors())
{
// we hack success!
strcpy(passcode,password);
return(1);
}
printf("...failed\n");
system(delete_file);
update_password(password);
if(strlen(password)>maxdighack){
return(0);
end=2;
}
}
}// end while //
}
//////////////////////////////////////////////////////////////////////////
//
// chk_4_errors() - search the zipcrack.err file for the error_sig -
// "error!". If found return 1 else return 0
//
/////////////////////////////////////////////////////////////////////////
int
chk_4_errors()
{
FILE *errfile;
int end;
int i;
char buffer[10];
if ((errfile = fopen("zipcrack.err","r+b")) == NULL )
{
printf("\nCannot find zipcrack.err file.");
printf("\nCannot continue.\n");
exit(1);
}
i=0;
end=0;
while(!end)
{
if(fread(buffer, sizeof(char),1,errfile))
{
if(buffer[0] == error_sig[i])
i = i + 1;
else
i = 0;
if (i == 7)
{ // sig is 4 digits
close(errfile);
return(1);
}
}
else
end=1;
}
close(errfile);
return(0);
}
//////////////////////////////////////////////////////////////////////////
// update_password(password) - we get the next password to try here.
// This is the routine you would modify to make a dictionary or
// other than sequential hack. Also you can modify the range
// of char's to try here.
///////////////////////////////////////////////////////////////////////
update_password(password)
char *password;
{
int g,i,len,err;
char newlen[12];
err=0;
len = strlen(password);
i = len-1;
g = 0;
while(!err){
password[i] = password[i] + 1; // inc to next char in series
if(password[i] > 'z') {
password[i] = 'a';
i = i - 1;
g = g + 1;
if(g==2)
printf("password = %s \015",password);
}else
err = 1;
if(i<0) { // we need to increase the length by one
// strcpy(newlen,preamble); // I was thinking about a pre and
// postamble in case you knew the
// first or las couple of letters
// of the password
strcpy(newlen,"a"); // new start of string //
strcat(newlen,password);
strcpy(password,newlen);
err = 1;
}
}
}
////////////////////////////////////////////////////////////////////////////
// decript_head(buffer,key) - this is where the actual work takes place,
// We decript the buffer with the key generated with our password and
// check if we have a CRC match, if we do return with a 1.
////////////////////////////////////////////////////////////////////////////
decript_head(buffer,key)
unsigned char *buffer;
unsigned long *key;
{
int i;
unsigned int crc1;
char c;
for(i = 0; i<12 ; i++)
{
c = buffer[i] ^ decrypt_byte(key); /* buffer xor decrypt_byte */
update_keys(key,c);
buffer[i] = c;
}
crc1 = ((buffer[11]<<8)|(buffer[10]));
/* crc1 = ~crc1; */
if(crc1 == crc2find)
{
printf("Yippi Ki-aye M*&!#R F*^@#R ");
return(1);
}
return(0);
}
update_keys(key,val)
unsigned long *key;
char val;
{
key[0] = crc32(key[0],val);
key[1] = key[1] + (key[0] & 0x000000ff);
key[1] = key[1] * 134775813 + 1;
key[2] = crc32(key[2],(key[1] >> 24));
}
unsigned char
decrypt_byte(key)
unsigned long *key;
{
unsigned short temp;
temp = key[2] | 2;
return((temp*(temp^1))>>8);
}
//
// cRc routine
//
unsigned long
crc32(oldcrc, newchar)
USGL oldcrc;
char newchar;
{
int i,index;
USGL Crc;
Crc = oldcrc;
index = ((Crc ^ newchar) & 0x000000ffL);
Crc = ((Crc >> 8) & 0x00ffffffL) ^ crctable[index];
return Crc; /* return a 1's complement */
}
void generatetable() /* generate the crc look-up table */
{
union
{ USGI i;
struct
{
USGI i1 :1; /* MSC low order bit */
USGI i2 :1;
USGI i3 :1;
USGI i4 :1;
USGI i5 :1;
USGI i6 :1;
USGI i7 :1;
USGI i8 :1; /* MSC high order bit */
USGI :8; /* unused bits */
}bit;
}iUn;
union
{ USGL entry;
struct
{
USGI b1 :1; /* MSC low order bit */
USGI b2 :1;
USGI b3 :1;
USGI b4 :1;
USGI b5 :1;
USGI b6 :1;
USGI b7 :1;
USGI b8 :1;
USGI b9 :1;
USGI b10:1;
USGI b11:1;
USGI b12:1;
USGI b13:1;
USGI b14:1;
USGI b15:1;
USGI b16:1;
USGI b17:1;
USGI b18:1;
USGI b19:1;
USGI b20:1;
USGI b21:1;
USGI b22:1;
USGI b23:1;
USGI b24:1;
USGI b25:1;
USGI b26:1;
USGI b27:1;
USGI b28:1;
USGI b29:1;
USGI b30:1;
USGI b31:1;
USGI b32:1; /* MSC high order bit */
} entrybit;
}entryun;
for (iUn.i = 0; iUn.i < 256; iUn.i++)
{
entryun.entry = 0; /* zero out the value */
entryun.entrybit.b32 = (iUn.bit.i2 ^ iUn.bit.i8);
entryun.entrybit.b31 = (iUn.bit.i1 ^ iUn.bit.i2 ^
iUn.bit.i7 ^ iUn.bit.i8);
entryun.entrybit.b30 = (iUn.bit.i1 ^ iUn.bit.i2 ^
iUn.bit.i6 ^ iUn.bit.i7 ^
iUn.bit.i8);
entryun.entrybit.b29 = (iUn.bit.i1 ^ iUn.bit.i5 ^
iUn.bit.i6 ^ iUn.bit.i7);
entryun.entrybit.b28 = (iUn.bit.i2 ^ iUn.bit.i4 ^
iUn.bit.i5 ^ iUn.bit.i6 ^
iUn.bit.i8);
entryun.entrybit.b27 = (iUn.bit.i1 ^ iUn.bit.i2 ^
iUn.bit.i3 ^ iUn.bit.i4 ^
iUn.bit.i5 ^ iUn.bit.i7 ^
iUn.bit.i8);
entryun.entrybit.b26 = (iUn.bit.i1 ^ iUn.bit.i2 ^
iUn.bit.i3 ^ iUn.bit.i4 ^
iUn.bit.i6 ^ iUn.bit.i7 );
entryun.entrybit.b25 = (iUn.bit.i1 ^ iUn.bit.i3 ^
iUn.bit.i5 ^ iUn.bit.i6 ^
iUn.bit.i8);
entryun.entrybit.b24 = (iUn.bit.i4 ^ iUn.bit.i5 ^
iUn.bit.i7 ^ iUn.bit.i8);
entryun.entrybit.b23 = (iUn.bit.i3 ^ iUn.bit.i4 ^
iUn.bit.i6 ^ iUn.bit.i7);
entryun.entrybit.b22 = (iUn.bit.i3 ^ iUn.bit.i5 ^
iUn.bit.i6 ^ iUn.bit.i8);
entryun.entrybit.b21 = (iUn.bit.i4 ^ iUn.bit.i5 ^
iUn.bit.i7 ^ iUn.bit.i8);
entryun.entrybit.b20 = (iUn.bit.i2 ^ iUn.bit.i3 ^
iUn.bit.i4 ^ iUn.bit.i6 ^
iUn.bit.i7 ^ iUn.bit.i8 );
entryun.entrybit.b19 = (iUn.bit.i1 ^ iUn.bit.i2 ^
iUn.bit.i3 ^ iUn.bit.i5 ^
iUn.bit.i6 ^ iUn.bit.i7 );
entryun.entrybit.b18 = (iUn.bit.i1 ^ iUn.bit.i2 ^
iUn.bit.i4 ^ iUn.bit.i5 ^
iUn.bit.i6 );
entryun.entrybit.b17 = (iUn.bit.i1 ^ iUn.bit.i3 ^
iUn.bit.i4 ^ iUn.bit.i5 );
entryun.entrybit.b16 = (iUn.bit.i3 ^ iUn.bit.i4 ^
iUn.bit.i8);
entryun.entrybit.b15 = (iUn.bit.i2 ^ iUn.bit.i3 ^
iUn.bit.i7);
entryun.entrybit.b14 = (iUn.bit.i1 ^ iUn.bit.i2 ^
iUn.bit.i6);
entryun.entrybit.b13 = (iUn.bit.i1 ^ iUn.bit.i5);
entryun.entrybit.b12 = (iUn.bit.i4);
entryun.entrybit.b11 = (iUn.bit.i3);
entryun.entrybit.b10 = (iUn.bit.i8);
entryun.entrybit.b9 = (iUn.bit.i2 ^ iUn.bit.i7 ^
iUn.bit.i8);
entryun.entrybit.b8 = (iUn.bit.i1 ^ iUn.bit.i6 ^
iUn.bit.i7);
entryun.entrybit.b7 = (iUn.bit.i5 ^ iUn.bit.i6 );
entryun.entrybit.b6 = (iUn.bit.i2 ^ iUn.bit.i4 ^
iUn.bit.i5 ^ iUn.bit.i8);
entryun.entrybit.b5 = (iUn.bit.i1 ^ iUn.bit.i3 ^
iUn.bit.i4 ^ iUn.bit.i7 );
entryun.entrybit.b4 = (iUn.bit.i2 ^ iUn.bit.i3 ^
iUn.bit.i6);
entryun.entrybit.b3 = (iUn.bit.i1 ^ iUn.bit.i2 ^
iUn.bit.i5);
entryun.entrybit.b2 = (iUn.bit.i1 ^ iUn.bit.i4);
entryun.entrybit.b1 = (iUn.bit.i3);
crctable[iUn.i] = entryun.entry;
}
}