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 (16 years, 3 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

# 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 #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 }