ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/fcrackzip/gen.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
CVS Tags: HEAD
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     #include <errno.h>
28    
29     #include "crack.h"
30    
31     static int use_unzip;
32     static method *crack_method = methods;
33     static int method_number = -1;
34     static int min_length = -1;
35     static int max_length = -1;
36     static int residuent = 0;
37     static int modul = 1;
38    
39     int brute_force_gen(void)
40     {
41     u8 *p = pw_end;
42    
43     do
44     {
45     u8 o = *--p;
46     *p = bf_next [o];
47     if (o != bf_last)
48     return pw_end - p;
49     }
50     while (p > pw);
51    
52     if (pw_end - pw < max_length)
53     {
54     p = ++pw_end;
55     *p = 0;
56    
57     while (p > pw)
58     *--p = bf_next [255];
59    
60     return -1;
61     }
62     else
63     return 0;
64     }
65    
66     void parse_charset (char *cs)
67     {
68     u8 chars[800];
69     u8 map[256];
70     u8 *p = chars;
71    
72     while (*cs)
73     switch (*cs++)
74     {
75     case 'a':
76     strcpy ((char *)p, "abcdefghijklmnopqrstuvwxyz"); p+=26;
77     break;
78    
79     case 'A':
80     strcpy ((char *)p, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); p+=26;
81     break;
82    
83     case '1':
84     strcpy ((char *)p, "0123456789"); p+=10;
85     break;
86    
87     case '!':
88     strcpy ((char *)p, "!:$%&/()=?{[]}+*~#"); p+=18;
89     break;
90    
91     case ':':
92     while (*cs)
93     *p++ = *cs++;
94     break;
95    
96     default:
97     fprintf (stderr, "unknown charset specifier, only 'aA1!:' recognized\n");
98     exit (1);
99     }
100    
101     *p = 0;
102    
103     p = chars;
104     bf_last = *p++;
105     memset (bf_next, bf_last, sizeof bf_next);
106     memset (map, 0, 256);
107    
108     for (; *p; p++)
109     if (!map [*p])
110     {
111     map [*p] = 1;
112     bf_next [bf_last] = *p;
113     bf_last = *p;
114     }
115    
116     bf_next [bf_last] = chars[0];
117    
118     /* { int i; for (i = 0; i < 255; i++) printf ("bf_next [%3d] = %3d\n", i, bf_next[i]);};*/
119     }
120    
121     static int benchmark_count;
122    
123     static int benchmark_gen(void)
124     {
125     if (!--benchmark_count)
126     return 0;
127    
128     return brute_force_gen ();
129     }
130    
131     static void benchmark (void)
132     {
133     #ifdef HAVE_GETTIMEOFDAY
134     int i;
135     long j, k;
136     struct timeval tv1, tv2;
137    
138     do {
139     for (i = 0; i < HEADER_SIZE*3; i++)
140     files[i] = i ^ (i*3);
141    
142     file_count = 3;
143     strcpy (pw, "abcdefghij");
144     parse_charset ("a");
145     benchmark_count = BENCHMARK_LOOPS;
146    
147     verbosity = 0;
148    
149     printf ("%c%s: ", (crack_method - methods == default_method) ? '*' : ' ',
150     crack_method->desc);
151     fflush (stdout);
152    
153     crack_method->init_crack_pw ();
154     gettimeofday (&tv1, 0);
155     crack_method->crack_pw (benchmark_gen, false_callback);
156     gettimeofday (&tv2, 0);
157     tv2.tv_sec -= tv1.tv_sec;
158     tv2.tv_usec -= tv1.tv_usec;
159    
160     j = tv2.tv_sec * 1000000 + tv2.tv_usec;
161     k = BENCHMARK_LOOPS;
162    
163     printf ("cracks/s = ");
164    
165     for (i=7; i--; )
166     printf ("%d", k/j), k = (k-k/j*j)*10;
167    
168     printf ("\n");
169     crack_method++;
170     } while (method_number < 0 && crack_method->desc);
171     #else
172     fprintf (stderr, "This executable was compiled without support for benchmarking\n");
173     exit (1);
174     #endif
175     }
176    
177     static u32 fgetu32 (FILE *f)
178     {
179     register u32 r;
180    
181     r = fgetc(f) << 0;
182     r |= fgetc(f) << 8;
183     r |= fgetc(f) << 16;
184     r |= fgetc(f) << 24;
185    
186     return r;
187     }
188    
189     static u32 fgetu16 (FILE *f)
190     {
191     register u32 r;
192    
193     r = fgetc(f) << 0;
194     r |= fgetc(f) << 8;
195    
196     return r;
197     }
198    
199     static void parse_zip (char *path)
200     {
201     FILE *f = fopen (path, "rb");
202    
203     if (!f)
204     {
205     fprintf (stderr, "skipping '%s': %s\n", path, strerror (errno));
206     goto out;
207     }
208    
209     while (!feof (f))
210     {
211     u32 id = fgetu32 (f);
212    
213     if (id == 0x04034b50UL)
214     {
215     u16 version = fgetu16 (f);
216     u16 flags = fgetu16 (f);
217     u16 compression_method = fgetu16 (f);
218     u16 lastmodtime = fgetu16 (f);
219     u16 lastmoddate = fgetu16 (f);
220     u32 crc32 = fgetu32 (f);
221     u32 compr_size = fgetu32 (f);
222     u32 uncompr_size = fgetu32 (f);
223     u16 name_len = fgetu16 (f);
224     u16 extra_field_len = fgetu16 (f);
225    
226     char zip_path [1024];
227    
228     /* these are unused. */
229     (void) lastmoddate;
230     (void) lastmodtime;
231     (void) compression_method;
232     (void) version;
233    
234     if (name_len < 1024)
235     {
236     fread (zip_path, name_len, 1, f);
237     zip_path [name_len] = 0;
238     }
239     else
240     {
241     fprintf (stderr, "filename too long (>1023 bytes), skipping zipfile\n");
242     goto out;
243     }
244    
245     fseek (f, extra_field_len, SEEK_CUR);
246    
247     if (flags & 1)
248     {
249     if (compr_size >= 12)
250     {
251     u8 *file = files + HEADER_SIZE * file_count;
252     fread (file, FILE_SIZE, 1, f);
253     file[FILE_SIZE ] = crc32 >> 24;
254     file[FILE_SIZE+1] = crc32 >> 16;
255     file_path [file_count] = strdup (path);
256    
257     if (verbosity)
258     printf ("found encrypted file '%s', (size cp/uc %ld/%ld)\n", zip_path, compr_size, uncompr_size);
259    
260     if (++file_count >= MAX_FILES)
261     {
262     if (verbosity)
263     printf ("%d file maximum reached, skipping further files\n", MAX_FILES);
264    
265     goto out;
266     }
267    
268     compr_size -= 12;
269     }
270     else
271     {
272     fprintf (stderr, "'%s' is corrupted, skipping zipfile\n", zip_path);
273     goto out;
274     }
275     }
276     else if (verbosity)
277     printf ("'%s' is not encrypted, skipping\n", zip_path);
278    
279     fseek (f, compr_size, SEEK_CUR);
280     }
281     else if (id == 0x08074b50UL) /* extended local sig (?) */
282     {
283     fseek (f, 12, SEEK_CUR);
284     }
285     else if (id == 0x30304b50UL)
286     {
287     /* ignore */
288     }
289     else if (id == 0x02014b50UL || id == 0x06054b50UL)
290     {
291     goto out;
292     }
293     else
294     {
295     fprintf (stderr, "found id %08lx, '%s' is not a zipfile ver 2.xx, skipping\n",
296     (unsigned long)id, path);
297     goto out;
298     }
299     }
300    
301     out:
302     fclose (f);
303     }
304    
305     static void usage (int ec)
306     {
307     fprintf (stderr, "\n"
308     PACKAGE " version " VERSION ", a fast/free zip password cracker\n"
309     "written by Marc Lehmann <pcg@goof.com> You can find more info on\n"
310     "http://www.goof.com/pcg/marc/\n"
311     "\n"
312     "USAGE: fcrackzip [-bchvpium]\n"
313     " [--brute-force] use brute force algorithm\n"
314     " [--benchmark] execute a small benchmark\n"
315     " [--charset characterset] use characters from charset\n"
316     " [--help] show this message\n"
317     " [--validate] sanity-check the algortihm\n"
318     " [--verbose] be more verbose\n"
319     " [--init-password string] use strings as initial password\n"
320     " [--length min-max] check password with length min to max\n"
321     " [--use-unzip] use unzip to weed out wrong passwords\n"
322     " [--method num] use method number \"num\" (see below)\n"
323     " [--modulo r/m] only calculcate 1/m of the password\n"
324     " file... the zipfiles to crack\n"
325     "\n"
326     );
327    
328     fprintf (stderr, "methods compiled in (* = default):\n\n");
329     for (crack_method = methods; crack_method->desc; crack_method++)
330     fprintf (stderr, "%c%s\n", (crack_method - methods == default_method) ? '*' : ' ', crack_method->desc);
331    
332     fprintf (stderr, "\n");
333     exit (ec);
334     }
335    
336     static struct option options[] = {
337     { "brute-force" , no_argument , 0, 'b' },
338     { "benchmark" , no_argument , 0, 'B' },
339     { "charset" , required_argument , 0, 'c' },
340     { "help" , no_argument , 0, 'h' },
341     { "validate" , no_argument , 0, 'V' },
342     { "verbose" , no_argument , 0, 'v' },
343     { "init-password" , required_argument , 0, 'p' },
344     { "length" , required_argument , 0, 'l' },
345     { "use-unzip" , no_argument , 0, 'u' },
346     { "method" , required_argument , 0, 'm' },
347     { "modulo" , required_argument , 0, 2 },
348     { 0 , 0 , 0, 0 },
349     };
350    
351     int main (int argc, char *argv[])
352     {
353     int c;
354     int option_index = 0;
355     char *charset = "aA1!";
356     enum { m_benchmark, m_brute_force } mode = m_brute_force;
357    
358     while ((c = getopt_long (argc, argv, "bc:p:l:m:vu", options, &option_index)) != -1)
359     switch (c)
360     {
361     case 'b':
362     mode = m_brute_force;
363     break;
364    
365     case 'p':
366     strcpy (pw, optarg);
367     break;
368    
369     case 'l':
370     pw[0] = 0;
371     switch (sscanf (optarg, "%d-%d", &min_length, &max_length))
372     {
373     default:
374     fprintf (stderr, "'%s' is an incorrect length specification\n", optarg);
375     exit (1);
376     case 1:
377     max_length = min_length;
378     case 2:
379     }
380     break;
381    
382     case 2:
383     if (sscanf (optarg, "%d/%d", &residuent, &modul) != 2)
384     fprintf (stderr, "malformed --modulo option, expected 'residuent/modul'\n"), exit (1);
385    
386     if (residuent < 0 || modul <= 0)
387     fprintf (stderr, "residuent and modul must be positive\n"), exit (1);
388    
389     if (residuent >= modul)
390     fprintf (stderr, "residuent must be less than modul\n"), exit (1);
391    
392     break;
393    
394     case 'B':
395     mode = m_benchmark;
396     benchmark ();
397     exit (0);
398    
399     case 'v':
400     verbosity++;
401     break;
402    
403     case 'm':
404     method_number = atoi (optarg);
405     crack_method = methods + method_number;
406     break;
407    
408     case 'V':
409     validate ();
410     exit (0);
411    
412     case 'c':
413     charset = optarg;
414     break;
415    
416     case 'u':
417     use_unzip = 1;
418     break;
419    
420     case 'h':
421     usage (0);
422    
423     case ':':
424     fprintf (stderr, "required argument missing\n");
425     exit (1);
426    
427     case '?':
428     fprintf (stderr, "unknown option\n");
429     exit (1);
430    
431     default:
432     usage (1);
433     }
434    
435     if (optind >= argc)
436     {
437     fprintf (stderr, "you have to specify one or more zip files (try --help)\n");
438     exit (1);
439     }
440    
441     for (; optind < argc; optind++)
442     if (file_count < MAX_FILES)
443     parse_zip (argv[optind]);
444     else if (verbosity)
445     printf ("%d file maximum reached, ignoring '%s'\n", MAX_FILES, argv[optind]);
446    
447     if (file_count == 0)
448     {
449     fprintf (stderr, "no usable files found\n");
450     exit (1);
451     }
452    
453     crack_method->init_crack_pw ();
454    
455     switch (mode)
456     {
457     case m_brute_force:
458     parse_charset (charset);
459    
460     if (!pw[0])
461     {
462     if (min_length < 0)
463     {
464     fprintf (stderr, "you have to specify either --init-password or --length with --brute-force\n");
465     exit (1);
466     }
467     else
468     {
469     u8 *p = pw;
470     while (p < pw + min_length)
471     *p++ = bf_next [255];
472    
473     *p++ = 0;
474     }
475     }
476    
477     if (residuent)
478     {
479     int xmodul = modul;
480     modul = residuent;
481     pw_end = pw + strlen (pw);
482     brute_force_gen ();
483     printf ("%s\n",pw);
484     modul = xmodul;
485     }
486    
487     crack_method->crack_pw (brute_force_gen, print_callback);
488     break;
489    
490     default:
491     fprintf (stderr, "specified mode not supported in this version\n");
492     exit (1);
493     }
494    
495     return 0;
496     }