ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/fcrackzip/main.c
Revision: 1.3
Committed: Sun Jun 20 13:13:45 2010 UTC (13 years, 10 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.2: +1 -1 lines
Log Message:
*** empty log message ***

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 if (strlen (optarg) > MAX_PW)
379 {
380 fprintf (stderr, "'%s' is too long: passwords longer than %d characters not supported\n", optarg, MAX_PW);
381 exit (1);
382 }
383
384 strcpy (pw, optarg);
385 break;
386
387 case 'l':
388 pw[0] = 0;
389 switch (sscanf (optarg, "%d-%d", &min_length, &max_length))
390 {
391 default:
392 fprintf (stderr, "'%s' is an incorrect length specification\n", optarg);
393 exit (1);
394 case 1:
395 max_length = min_length;
396 case 2:
397 ;
398 }
399 break;
400
401 case 2:
402 if (sscanf (optarg, "%d/%d", &residuent, &modul) != 2)
403 fprintf (stderr, "malformed --modulo option, expected 'residuent/modul'\n"), exit (1);
404
405 if (residuent < 0 || modul <= 0)
406 fprintf (stderr, "residuent and modul must be positive\n"), exit (1);
407
408 if (residuent >= modul)
409 fprintf (stderr, "residuent must be less than modul\n"), exit (1);
410
411 break;
412
413 case 'B':
414 mode = m_benchmark;
415 benchmark ();
416 exit (0);
417
418 case 'v':
419 verbosity++;
420 break;
421
422 case 'm':
423 {
424 for (method_number = 0; methods[method_number].desc; method_number++)
425 if (!strncmp (methods[method_number].desc, optarg, strlen (optarg)))
426 break;
427
428 if (!methods[method_number].desc)
429 method_number = atoi (optarg);
430
431 crack_method = methods + method_number;
432 }
433 break;
434
435 case 'V':
436 validate ();
437 exit (0);
438
439 case 'c':
440 charset = optarg;
441 break;
442
443 case 'u':
444 use_unzip = 1;
445 break;
446
447 case 'h':
448 usage (0);
449 case 'R':
450 printf (PACKAGE " version " VERSION "\n");
451 exit (0);
452
453 case ':':
454 fprintf (stderr, "required argument missing\n");
455 exit (1);
456
457 case '?':
458 fprintf (stderr, "unknown option\n");
459 exit (1);
460
461 default:
462 usage (1);
463 }
464
465 if (method_number < 0)
466 {
467 method_number = default_method;
468 crack_method = methods + default_method;
469 }
470
471 if (optind >= argc)
472 {
473 fprintf (stderr, "you have to specify one or more zip files (try --help)\n");
474 exit (1);
475 }
476
477 for (; optind < argc; optind++)
478 if (file_count < MAX_FILES)
479 crack_method->load_file (argv[optind]);
480 else if (verbosity)
481 printf ("%d file maximum reached, ignoring '%s'\n", MAX_FILES, argv[optind]);
482
483 if (file_count == 0)
484 {
485 fprintf (stderr, "no usable files found\n");
486 exit (1);
487 }
488
489 crack_method->init_crack_pw ();
490
491 switch (mode)
492 {
493 case m_brute_force:
494 parse_charset (charset);
495
496 if (!pw[0])
497 {
498 if (min_length < 0)
499 {
500 fprintf (stderr, "you have to specify either --init-password or --length with --brute-force\n");
501 exit (1);
502 }
503 else
504 {
505 u8 *p = pw;
506 while (p < pw + min_length)
507 *p++ = bf_next[255];
508
509 *p++ = 0;
510 }
511 }
512
513 if (residuent)
514 {
515 int xmodul = modul;
516 modul = residuent;
517 pw_end = pw + strlen (pw);
518 brute_force_gen ();
519 printf ("%s\n", pw);
520 modul = xmodul;
521 printf ("WARNING: residuent mode NOT supported YET!\n");
522 }
523
524 crack_method->crack_pw (brute_force_gen, print_callback);
525 break;
526
527 case m_dictionary:
528 if (!pw[0])
529 {
530 fprintf (stderr, "you have to specify a file to read passwords from using the -p switch\n");
531 exit (1);
532 }
533
534 if (!(dict_file = fopen (pw, "r")))
535 {
536 perror (pw);
537 exit (1);
538 }
539 else
540 {
541 *(pw_end = pw) = 0;
542 dictionary_gen (); /* fetch first password */
543 crack_method->crack_pw (dictionary_gen, print_callback);
544
545 fclose (dict_file);
546 }
547
548 break;
549
550 default:
551 fprintf (stderr, "specified mode not supported in this version\n");
552 exit (1);
553 }
554
555 return 0;
556 }