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

# User Rev Content
1 root 1.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     }