ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/fcrackzip/main.c
Revision: 1.1
Committed: Mon Aug 4 07:09:51 2008 UTC (15 years, 9 months ago) by root
Content type: text/plain
Branch: MAIN
Log Message:
initial check-in, also 1.0 check-in

File Contents

# Content
1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4
5 #include <stdio.h>
6 #include <stdlib.h>
7 #ifdef HAVE_STDBOOL_H
8 #include <stdbool.h>
9 #else
10 typedef enum { FALSE = 0, TRUE = 1 } bool;
11 #endif
12 #ifdef HAVE_GETOPT_H
13 #include <getopt.h>
14 #else
15 #include "getopt.h"
16 #endif
17 #ifdef HAVE_GETTIMEOFDAY
18 #ifdef HAVE_UNISTD_H
19 #include <unistd.h>
20 #endif
21 #ifdef HAVE_SYS_TIME_H
22 #include <sys/time.h>
23 #endif
24 #endif
25
26 #include <string.h>
27
28 #ifdef USE_UNIX_REDIRECTION
29 #define DEVNULL ">/dev/null 2>&1"
30 #else
31 #define DEVNULL ">NUL 2>&1"
32 #endif
33
34 #include "crack.h"
35
36 int use_unzip;
37
38 static method *crack_method = methods;
39 static int method_number = -1;
40 static int min_length = -1;
41 static int max_length = -1;
42 static int residuent = 0;
43 static int modul = 1;
44
45 static FILE *dict_file;
46
47 int REGPARAM
48 check_unzip (const char *pw)
49 {
50 char buff[1024];
51 int status;
52
53 sprintf (buff, "unzip -qqtP \"%s\" %s " DEVNULL, pw, file_path[0]);
54 status = system (buff);
55
56 #undef REDIR
57
58 if (status == EXIT_SUCCESS)
59 {
60 printf("\n\nPASSWORD FOUND!!!!: pw == %s\n", pw);
61 exit (EXIT_SUCCESS);
62 }
63
64 return !status;
65 }
66
67 /* misc. callbacks. */
68
69 static int
70 false_callback (const char *pw, const char *info)
71 {
72 (void) pw;
73 (void) info; /* suppress warning */
74 return 0;
75 }
76
77 static int
78 true_callback (const char *pw, const char *info)
79 {
80 (void) pw;
81 (void) info; /* suppress warning */
82 return 1;
83 }
84
85 static int
86 print_callback (const char *pw, const char *info)
87 {
88 if (!use_unzip || check_unzip (pw))
89 {
90 printf ("possible pw found: %s (%s)\n", pw, info ? info : "");
91 /*exit(0); */
92 }
93
94 return 0;
95 }
96
97 static int
98 brute_force_gen (void)
99 {
100 u8 *p = pw_end;
101
102 do
103 {
104 u8 o = *--p;
105 *p = bf_next[o];
106 if (o != bf_last)
107 return pw_end - p;
108 }
109 while (p > pw);
110
111 if (pw_end - pw < max_length)
112 {
113 p = ++pw_end;
114 *p = 0;
115
116 while (p > pw)
117 *--p = bf_next[255];
118
119 return -1;
120 }
121 else
122 return 0;
123 }
124
125 static int
126 dictionary_gen (void)
127 {
128 /* should optimize this, comparing prefixes would be a net win.
129 * however, not using fgets but something better might be an
130 * even higher win :(
131 */
132 if (fgets (pw, MAX_PW+1, dict_file))
133 {
134 pw[strlen (pw) - 1] = 0;
135 return -1;
136 }
137 else
138 {
139 if (!feof (dict_file))
140 perror ("dictionary_read_next_password");
141
142 return 0;
143 }
144 }
145
146 static int
147 validate_gen (void)
148 {
149 return 0;
150 }
151
152 static void
153 validate (void)
154 {
155 u8 header[HEADER_SIZE + 1] =
156 {0xf4, 0x28, 0xd6, 0xee, 0xd7, 0xd2,
157 0x3c, 0x1a, 0x20, 0xab, 0xdf, 0x73,
158 0xd6, 0xba, 0}; /* PW: "Martha" */
159 strcpy ((char *) files, (char *) header); /* yeah, dirty... */
160 file_count = 1;
161
162 if (crack_method->desc[0] == 'z')
163 {
164 crack_method->init_crack_pw ();
165
166 strcpy (pw, "Martha");
167 if (crack_method->crack_pw (validate_gen, true_callback))
168 printf ("validate ok (%s == Martha)\n", pw);
169 else
170 printf ("validation error (%s != Martha)\n", pw);
171 }
172 else
173 printf ("validate only works for zip methods, use --method to select one.\n");
174 }
175
176 static void
177 parse_charset (char *cs)
178 {
179 u8 chars[800];
180 u8 map[256];
181 u8 *p = chars;
182
183 while (*cs)
184 switch (*cs++)
185 {
186 case 'a':
187 strcpy ((char *) p, "abcdefghijklmnopqrstuvwxyz");
188 p += 26;
189 break;
190
191 case 'A':
192 strcpy ((char *) p, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
193 p += 26;
194 break;
195
196 case '1':
197 strcpy ((char *) p, "0123456789");
198 p += 10;
199 break;
200
201 case '!':
202 strcpy ((char *) p, "!:$%&/()=?{[]}+-*~#");
203 p += 18;
204 break;
205
206 case ':':
207 while (*cs)
208 *p++ = *cs++;
209 break;
210
211 default:
212 fprintf (stderr, "unknown charset specifier, only 'aA1!:' recognized\n");
213 exit (1);
214 }
215
216 *p = 0;
217
218 p = chars;
219 bf_last = *p++;
220 memset (bf_next, bf_last, sizeof bf_next);
221 memset (map, 0, 256);
222
223 for (; *p; p++)
224 if (!map[*p])
225 {
226 map[*p] = 1;
227 bf_next[bf_last] = *p;
228 bf_last = *p;
229 }
230
231 bf_next[bf_last] = chars[0];
232
233 /* { int i; for (i = 0; i < 255; i++) printf ("bf_next [%3d] = %3d\n", i, bf_next[i]);}; */
234 }
235
236 static int benchmark_count;
237
238 static int
239 benchmark_gen (void)
240 {
241 if (!--benchmark_count)
242 return 0;
243
244 return brute_force_gen ();
245 }
246
247 static void
248 benchmark (void)
249 {
250 #ifdef HAVE_GETTIMEOFDAY
251 int i;
252 long j, k;
253 struct timeval tv1, tv2;
254
255 do
256 {
257 for (i = 0; i < HEADER_SIZE * 3; i++)
258 files[i] = i ^ (i * 3);
259
260 file_count = 3;
261 strcpy (pw, "abcdefghij");
262 parse_charset ("a");
263 benchmark_count = BENCHMARK_LOOPS;
264
265 verbosity = 0;
266
267 printf ("%c%s: ",
268 (crack_method - methods == default_method) ? '*' : ' ',
269 crack_method->desc);
270
271 if (strncmp ("zip", crack_method->desc, 3))
272 printf ("(skipped)");
273 else
274 {
275 fflush (stdout);
276
277 crack_method->init_crack_pw ();
278 gettimeofday (&tv1, 0);
279 crack_method->crack_pw (benchmark_gen, false_callback);
280 gettimeofday (&tv2, 0);
281 tv2.tv_sec -= tv1.tv_sec;
282 tv2.tv_usec -= tv1.tv_usec;
283
284 j = tv2.tv_sec * 1000000 + tv2.tv_usec;
285 k = BENCHMARK_LOOPS;
286
287 printf ("cracks/s = ");
288
289 for (i = 7; i--;)
290 printf ("%ld", k / j), k = (k - k / j * j) * 10;
291 }
292
293 printf ("\n");
294 crack_method++;
295 }
296 while (method_number < 0 && crack_method->desc);
297 #else
298 fprintf (stderr, "This executable was compiled without support for benchmarking\n");
299 exit (1);
300 #endif
301 }
302
303 static void
304 usage (int ec)
305 {
306 printf ("\n"
307 PACKAGE " version " VERSION ", a fast/free zip password cracker\n"
308 "written by Marc Lehmann <pcg@goof.com> You can find more info on\n"
309 "http://www.goof.com/pcg/marc/\n"
310 "\n"
311 "USAGE: fcrackzip\n"
312 " [-b|--brute-force] use brute force algorithm\n"
313 " [-D|--dictionary] use a dictionary\n"
314 " [-B|--benchmark] execute a small benchmark\n"
315 " [-c|--charset characterset] use characters from charset\n"
316 " [-h|--help] show this message\n"
317 " [--version] show the version of this program\n"
318 " [-V|--validate] sanity-check the algortihm\n"
319 " [-v|--verbose] be more verbose\n"
320 " [-p|--init-password string] use string as initial password/file\n"
321 " [-l|--length min-max] check password with length min to max\n"
322 " [-u|--use-unzip] use unzip to weed out wrong passwords\n"
323 " [-m|--method num] use method number \"num\" (see below)\n"
324 " [-2|--modulo r/m] only calculcate 1/m of the password\n"
325 " file... the zipfiles to crack\n"
326 "\n"
327 );
328
329 printf ("methods compiled in (* = default):\n\n");
330 for (crack_method = methods; crack_method->desc; crack_method++)
331 printf ("%c%d: %s\n",
332 (crack_method - methods == default_method) ? '*' : ' ',
333 crack_method - methods,
334 crack_method->desc);
335
336 printf ("\n");
337 exit (ec);
338 }
339
340 static struct option options[] =
341 {
342 {"version", no_argument, 0, 'R'},
343 {"brute-force", no_argument, 0, 'b'},
344 {"dictionary", no_argument, 0, 'D'},
345 {"benchmark", no_argument, 0, 'B'},
346 {"charset", required_argument, 0, 'c'},
347 {"help", no_argument, 0, 'h'},
348 {"validate", no_argument, 0, 'V'},
349 {"verbose", no_argument, 0, 'v'},
350 {"init-password", required_argument, 0, 'p'},
351 {"length", required_argument, 0, 'l'},
352 {"use-unzip", no_argument, 0, 'u'},
353 {"method", required_argument, 0, 'm'},
354 {"modulo", required_argument, 0, 2},
355 {0, 0, 0, 0},
356 };
357
358 int
359 main (int argc, char *argv[])
360 {
361 int c;
362 int option_index = 0;
363 char *charset = "aA1!";
364 enum { m_benchmark, m_brute_force, m_dictionary } mode = m_brute_force;
365
366 while ((c = getopt_long (argc, argv, "DbBc:hVvp:l:um:2:", options, &option_index)) != -1)
367 switch (c)
368 {
369 case 'b':
370 mode = m_brute_force;
371 break;
372
373 case 'D':
374 mode = m_dictionary;
375 break;
376
377 case 'p':
378 strcpy (pw, optarg);
379 break;
380
381 case 'l':
382 pw[0] = 0;
383 switch (sscanf (optarg, "%d-%d", &min_length, &max_length))
384 {
385 default:
386 fprintf (stderr, "'%s' is an incorrect length specification\n", optarg);
387 exit (1);
388 case 1:
389 max_length = min_length;
390 case 2:
391 ;
392 }
393 break;
394
395 case 2:
396 if (sscanf (optarg, "%d/%d", &residuent, &modul) != 2)
397 fprintf (stderr, "malformed --modulo option, expected 'residuent/modul'\n"), exit (1);
398
399 if (residuent < 0 || modul <= 0)
400 fprintf (stderr, "residuent and modul must be positive\n"), exit (1);
401
402 if (residuent >= modul)
403 fprintf (stderr, "residuent must be less than modul\n"), exit (1);
404
405 break;
406
407 case 'B':
408 mode = m_benchmark;
409 benchmark ();
410 exit (0);
411
412 case 'v':
413 verbosity++;
414 break;
415
416 case 'm':
417 {
418 for (method_number = 0; methods[method_number].desc; method_number++)
419 if (!strncmp (methods[method_number].desc, optarg, strlen (optarg)))
420 break;
421
422 if (!methods[method_number].desc)
423 method_number = atoi (optarg);
424
425 crack_method = methods + method_number;
426 }
427 break;
428
429 case 'V':
430 validate ();
431 exit (0);
432
433 case 'c':
434 charset = optarg;
435 break;
436
437 case 'u':
438 use_unzip = 1;
439 break;
440
441 case 'h':
442 usage (0);
443 case 'R':
444 printf (PACKAGE " version " VERSION "\n");
445 exit (0);
446
447 case ':':
448 fprintf (stderr, "required argument missing\n");
449 exit (1);
450
451 case '?':
452 fprintf (stderr, "unknown option\n");
453 exit (1);
454
455 default:
456 usage (1);
457 }
458
459 if (method_number < 0)
460 {
461 method_number = default_method;
462 crack_method = methods + default_method;
463 }
464
465 if (optind >= argc)
466 {
467 fprintf (stderr, "you have to specify one or more zip files (try --help)\n");
468 exit (1);
469 }
470
471 for (; optind < argc; optind++)
472 if (file_count < MAX_FILES)
473 crack_method->load_file (argv[optind]);
474 else if (verbosity)
475 printf ("%d file maximum reached, ignoring '%s'\n", MAX_FILES, argv[optind]);
476
477 if (file_count == 0)
478 {
479 fprintf (stderr, "no usable files found\n");
480 exit (1);
481 }
482
483 crack_method->init_crack_pw ();
484
485 switch (mode)
486 {
487 case m_brute_force:
488 parse_charset (charset);
489
490 if (!pw[0])
491 {
492 if (min_length < 0)
493 {
494 fprintf (stderr, "you have to specify either --init-password or --length with --brute-force\n");
495 exit (1);
496 }
497 else
498 {
499 u8 *p = pw;
500 while (p < pw + min_length)
501 *p++ = bf_next[255];
502
503 *p++ = 0;
504 }
505 }
506
507 if (residuent)
508 {
509 int xmodul = modul;
510 modul = residuent;
511 pw_end = pw + strlen (pw);
512 brute_force_gen ();
513 printf ("%s\n", pw);
514 modul = xmodul;
515 printf ("WARNING: residuent mode NOT supported YET!\n");
516 }
517
518 crack_method->crack_pw (brute_force_gen, print_callback);
519 break;
520
521 case m_dictionary:
522 if (!pw[0])
523 {
524 fprintf (stderr, "you have to specify a file to read passwords from using the -p switch\n");
525 exit (1);
526 }
527
528 if (!(dict_file = fopen (pw, "r")))
529 {
530 perror (pw);
531 exit (1);
532 }
533 else
534 {
535 *(pw_end = pw) = 0;
536 dictionary_gen (); /* fetch first password */
537 crack_method->crack_pw (dictionary_gen, print_callback);
538
539 fclose (dict_file);
540 }
541
542 break;
543
544 default:
545 fprintf (stderr, "specified mode not supported in this version\n");
546 exit (1);
547 }
548
549 return 0;
550 }