1 /* 2 * main.c 3 * 4 * This file contains the main() function of the PkZip-cracker. 5 * It reads the ciphertext and plaintext files and makes calls to the 6 * actual cracking stages. 7 * 8 * (C) by Peter Conrad <conrad@unix-ag.uni-kl.de> 9 * 10 * $Id: main.c,v 1.15 2002/11/12 16:58:02 lucifer Exp $ 11 * 12 * $Log: main.c,v $ 13 * Revision 1.15 2002/11/12 16:58:02 lucifer 14 * Fixed typo 15 * 16 * Revision 1.14 2002/11/02 15:12:06 lucifer 17 * Integrated RElf's changes (with small mods) from fix2.zip 18 * 19 * Revision 1.14 2002/10/25 17:51:20 RElf 20 * Removed call to initStage3Tab() 21 * 22 * Revision 1.13 2002/01/30 14:35:44 lucifer 23 * Removed DEBUG_KEYS stuff 24 * Incorporated changes by RElf 25 * 26 * Revision 1.12 1999/01/20 20:21:44 lucifer 27 * string.h included 28 * 29 * Revision 1.11 1998/05/08 16:59:20 lucifer 30 * added DEBUG_KEYS stuff to check some improvements 31 * 32 * Revision 1.10.2.1 2002/01/22 20:08:46 lucifer 33 * Change by RElf: ~factory_entryboost::geometry::projections::detail::factory_entry34 * Implemented new options -a and -n 35 * 36 * Revision 1.10 1997/09/23 20:07:31 lucifer 37 * Removed declaration of strdup 38 * 39 * Revision 1.9 1997/09/23 17:33:22 lucifer 40 * Added option -i. 41 * Minor modification of output. 42 * 43 * Revision 1.8 1997/09/18 18:17:22 lucifer 44 * Added comment and patches for windows 45 * 46 * Revision 1.7 1996/08/21 18:14:34 conrad 47 * Some cleanups to suppress some warnings... 48 * 49 * Revision 1.6 1996/08/21 17:36:46 conrad 50 * Added options -C -P -d 51 * 52 * Revision 1.4 1996/08/13 13:17:02 conrad 53 * Parameter list changed to support -o, -c and -p instead of fixed scheme 54 * Modifications to support plaintext in the middle of the ciphertext with 55 * offset (-o). Incomplete, works only if offset+plainlength<MAXFILELEN 56 * 57 * Revision 1.3 1996/06/23 10:36:15 lucifer 58 * Modification for DJGPP: key2i is now allocated dynamically 59 * For improved efficiency we now remember the lowest number of key2i- 60 * values and start stage2 using those. 61 * 62 * Revision 1.2 1996/06/12 09:47:13 conrad 63 * Release version 64 * 65 * Revision 1.1 1996/06/10 17:50:20 conrad 66 * Initial revision 67 * 68 */ 69 70 static char RCSID[]="$Id: main.c,v 1.15 2002/11/12 16:58:02 lucifer Exp $"; 71 72 #include <time.h> 73 #include <stdio.h> 74 75 #ifndef _WIN32 76 #include <unistd.h> 77 #else 78 #include <io.h> 79 #endif 80 81 #include <sys/stat.h> 82 #include <fcntl.h> 83 #include <stdlib.h> 84 #include <string.h> 85 86 #include "pkctypes.h" 87 #include "crc.h" 88 #include "mktmptbl.h" 89 #include "stage1.h" 90 #include "pkcrack.h" 91 #include "stage2.h" 92 #include "stage3.h" 93 #include "headers.h" 94 95 extern int zipdecrypt( char *infile,char *outfile, int k0, int k1, int k2 ); 96 97 #ifndef O_BINARY 98 #define O_BINARY 0 99 #endif 100 101 #define GOODNUM 1000 102 #define VERYGOOD 100 103 104 extern byte *extract(char*, char*, int caseflg); 105 106 byte *plaintext, *ciphertext; 107 uword *key2i; 108 109 static uword bestKey2i[GOODNUM]; 110 111 int numKey2s=0; 112 113 static int bestNum=GOODNUM; 114 115 int bestOffset; 116 117 static void usage( char *myself ) 118 { 119 fprintf( stderr, "Usage: %s -c <crypted_file> -p <plaintext_file> [other_options],\n", myself ); 120 fprintf( stderr, "where [other_options] may be one or more of\n" ); 121 fprintf( stderr, " -o <offset>\tfor an offset of the plaintext into the ciphertext,\n\t\t\t(may be negative)\n" ); 122 fprintf( stderr, " -C <c-ZIP>\twhere c-ZIP is a ZIP-archive containing <crypted_file>\n" ); 123 fprintf( stderr, " -P <p-ZIP>\twhere p-ZIP is a ZIP-archive containing <plaintext_file>\n" ); 124 fprintf( stderr, " -d <d-file>\twhere d-file is the name of the decrypted archive which\n\t\twill be created by this program if the correct keys are found\n\t\t(can only be used in conjunction with the -C option)\n" ); 125 fprintf( stderr, " -i\tswitch off case-insensitive filename matching in ZIP-archives\n" ); 126 fprintf( stderr, " -a\tabort keys searching after first success\n" ); 127 fprintf( stderr, " -n\tno progress indicator\n" ); 128 } 129 130 int main( int argc, char **argv ) 131 { 132 int crypt, plain, cryptlength, plainlength; 133 struct stat filestat; 134 time_t now; 135 int i, offset=12, caseflg=0, sabort=0, noprogress=0; 136 char *cryptname=NULL, *plainname=NULL; 137 char *cFromZIP=NULL, *pFromZIP=NULL, *decryptName=NULL; 138 139 for( i = 1; i < argc; i++ ) 140 { 141 if( !strcmp( "-o", argv[i] ) ) 142 { /* offset */ 143 offset += atoi( argv[++i] ); 144 } 145 else if( !strcmp( "-c", argv[i] ) ) 146 { /* ciphertext filename */ 147 cryptname = argv[++i]; 148 } 149 else if( !strcmp( "-p", argv[i] ) ) 150 { /* plaintext filename */ 151 plainname = argv[++i]; 152 } 153 else if( !strcmp( "-C", argv[i] ) ) 154 { /* ciphertext-ZIPfilename */ 155 cFromZIP = argv[++i]; 156 } 157 else if( !strcmp( "-P", argv[i] ) ) 158 { /* plaintext-ZIPfilename */ 159 pFromZIP = argv[++i]; 160 } 161 else if( !strcmp( "-d", argv[i] ) ) 162 { /* name of decrypted ZIP-archive */ 163 decryptName = argv[++i]; 164 } 165 else if( !strcmp( "-i", argv[i] ) ) 166 { /* case-insensitive filename */ 167 caseflg = FLG_CASE_SENSITIVE; 168 } 169 else if( !strcmp( "-a", argv[i] ) ) 170 { /* abort searching on success */ 171 sabort = 1; 172 } 173 else if( !strcmp( "-n", argv[i] ) ) 174 { /* no progress indicator */ 175 noprogress = 1; 176 } 177 } 178 if( !cryptname || !plainname ) 179 { 180 usage( argv[0] ); 181 exit(1); 182 } 183 if( decryptName && !cFromZIP ) 184 { 185 usage( argv[0] ); 186 exit(1); 187 } 188 189 key2i = malloc( sizeof(uword)*KEY2SPACE ); 190 if( !key2i ) 191 { 192 fprintf( stderr, "Sorry, not enough memory available.\n" ); 193 exit(1); 194 } 195 196 if( !cFromZIP ) 197 { 198 crypt = open( cryptname, O_RDONLY | O_BINARY ); 199 if( crypt == -1 ) 200 { 201 fprintf( stderr, "Cryptfile %s not found!\n", argv[1] ); 202 exit(1); 203 } 204 fstat( crypt, &filestat ); 205 cryptlength = filestat.st_size; 206 ciphertext = malloc( cryptlength ); 207 } 208 else 209 { 210 ciphertext = extract( cFromZIP, cryptname, caseflg ); 211 if( !ciphertext ) 212 exit(1); 213 cryptlength = lh.csize; 214 } 215 216 if( !pFromZIP ) 217 { 218 plain = open( plainname, O_RDONLY | O_BINARY ); 219 if( plain == -1 ) 220 { 221 fprintf( stderr, "Plaintextfile %s not found!\n", argv[2] ); 222 exit(1); 223 } 224 fstat( plain, &filestat ); 225 plainlength = filestat.st_size; 226 plaintext = malloc( plainlength + offset ); 227 } 228 else 229 { 230 plaintext = extract( pFromZIP, plainname, caseflg ); 231 if( !plaintext ) 232 exit(1); 233 plainlength = lh.csize; 234 plaintext -= offset; 235 } 236 237 if( plainlength > cryptlength-offset ) 238 { 239 fprintf( stderr, "Warning! Plaintext is longer than Ciphertext!\n" ); 240 } 241 if( plainlength < 13 ) 242 { 243 fprintf( stderr, "Plaintext must be at least 13 bytes! Aborting.\n" ); 244 exit(1); 245 } 246 247 cryptlength = plainlength + offset; 248 if( !ciphertext || !plaintext ) 249 { 250 fprintf( stderr, "Not enough memory!\n" ); 251 exit(1); 252 } 253 if( !cFromZIP && read( crypt, ciphertext, cryptlength ) != cryptlength ) 254 { 255 fprintf( stderr, "Couldn't read ciphertext!\n" ); 256 exit(1); 257 } 258 if( !pFromZIP && read( plain, &plaintext[offset], plainlength ) != plainlength ) 259 { 260 fprintf( stderr, "Couldn't read plaintext!\n" ); 261 exit(1); 262 } 263 if( !pFromZIP ) 264 close( plain ); 265 if( !cFromZIP ) 266 close( crypt ); 267 268 now = time(NULL); 269 fprintf( stderr, "Files read. Starting stage 1 on %s", ctime(&now) ); 270 271 preCompTemp(); 272 mkCrcTab(); 273 initMulTab(); 274 275 generate1stSetOfKey2s( cryptlength-1 ); 276 fprintf( stderr, "Now we're trying to reduce these...\n" ); 277 fflush( stderr ); 278 for( i = cryptlength-1; i >= offset+13 && numKey2s > 0 && bestNum > VERYGOOD; i-- ) 279 { 280 if(!noprogress) 281 { 282 fprintf( stderr, "Reducing number of keys... %3.1f%%\r", 100.*(cryptlength-i)/(cryptlength-offset-13) ); 283 /* fflush( stderr ); */ 284 } 285 reduceKey2s( i ); 286 if( numKey2s < bestNum ) 287 { 288 memcpy( bestKey2i, key2i, sizeof(uword)*numKey2s ); 289 bestNum = numKey2s; 290 bestOffset = i-1; 291 fprintf( stderr, "Lowest number: %d values at offset %d\n", bestNum, bestOffset ); 292 fflush( stderr ); 293 } 294 } 295 296 if( bestNum < GOODNUM ) 297 { 298 memcpy( key2i, bestKey2i, sizeof(uword)*bestNum ); 299 numKey2s = bestNum; 300 } 301 else 302 bestOffset = i; 303 304 printf( "Done. Left with %d possible Values. bestOffset is %d.\n", numKey2s, bestOffset ); 305 fflush( stdout ); 306 307 now = time(NULL); 308 fprintf( stderr, "Stage 1 completed. Starting stage 2 on %s", ctime(&now) ); 309 310 for( i = 0; i < numKey2s; i++ ) 311 { 312 if(!noprogress) 313 { 314 fprintf( stderr, "Searching... %3.1f%%\r",100.*i/numKey2s); 315 /* fflush( stderr ); */ 316 } 317 buildKey2Lists( key2i[i], cryptlength-bestOffset, offset ); 318 if( sabort && got_keys ) break; 319 } 320 321 322 now = time(NULL); 323 fprintf( stderr, "Stage 2 completed. Starting %s on %s", 324 decryptName?"zipdecrypt":"password search", ctime(&now) ); 325 326 if( !got_keys ) 327 printf( "No solutions found. You must have chosen the wrong plaintext.\n" ); 328 else if( !decryptName ) 329 findPwd( loesung0, loesung1, loesung2 ); 330 else 331 zipdecrypt( cFromZIP, decryptName, loesung0, loesung1, loesung2 ); 332 333 now = time(NULL); 334 fprintf( stderr, "Finished on %s", ctime(&now) ); 335 336 return(0); 337 } 338