ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/fcrackzip/cpmask.c
Revision: 1.1
Committed: Mon Aug 4 07:09:50 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

# Content
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <assert.h>
4
5 /* CP mask code */
6
7 /* The original CP code was written by Hirotsuna Mizuno and is
8 * Copyright (c) 1998 Hirotsuna Mizuno <s1041150@u-aizu.ac.jp>
9 *
10 * I heavily modified his code.
11 * as for speed, this algorithm could be improved without end,
12 * and alternative algorithms might exist that might be several orders
13 * of magnitude faster.
14 */
15
16 /* this is faster */
17 typedef unsigned int UI;
18
19 static UI image_width;
20 static UI image_height;
21 static u8 *image_data;
22 static UI transform_width;
23 static UI transform_height;
24 static u8 *transform_data;
25
26 typedef struct
27 {
28 UI dst_x, dst_y;
29 int mirror;
30 }
31 cp_cell;
32
33 static UI cp_cells;
34 static cp_cell *cp_trans;
35 static int *cp_table;
36 static UI cp_width;
37 static UI cp_height;
38
39
40 #define CP_CODE_MAX_LENGTH 16
41 #define CP_CELL_SIZE 8
42 #define CP_BPP 3
43 #define OFFSET_X 0
44 #define OFFSET_Y 0
45
46 /* the maximum size of the transformed image in cells */
47 #define MAX_SIZE 4
48
49 #define MAX_CP_WIDTH 2048
50
51 #define src_pixel(x,y,c) image_data [((y)*image_width +(x)) * CP_BPP + (c)]
52 #define dst_pixel(x,y,c) transform_data [((y)*transform_width+(x)) * CP_BPP + (c)]
53
54 static void
55 load_img (const char *name)
56 {
57 FILE *img;
58 UI image_depth;
59
60 if (image_data)
61 fprintf (stderr, "cannot load more than one image\n");
62 else
63 {
64 img = fopen (name, "rb");
65 if (img)
66 {
67 if (fscanf (img, "P6 ") == EOF)
68 perror ("no BINARY PPM header detected");
69 else
70 {
71 fscanf (img, "#%*[^\012\015] "); /* comment */
72 if (fscanf (img, "%u ", &image_width) != 1)
73 fprintf (stderr, "unable to read image width\n");
74 else
75 {
76 fscanf (img, "#%*[^\012\015] "); /* comment */
77 if (fscanf (img, "%u ", &image_height) != 1)
78 fprintf (stderr, "unable to read image height\n");
79 else
80 {
81 fscanf (img, "#%*[^\012\015] "); /* comment */
82 if (fscanf (img, "%u%*[ \012\015] ", &image_depth) != 1)
83 fprintf (stderr, "unable to read image depth\n");
84 else
85 {
86 if (image_depth != 255)
87 fprintf (stderr, "pixel maxval %d (!= 255) is not supported\n", image_depth);
88 else
89 {
90 image_data = (u8 *) malloc (image_width * image_height * CP_BPP);
91 if (!image_data)
92 fprintf (stderr, "unable to allocate memory for image\n");
93 else
94 {
95 if (fread (image_data, image_width * image_height * CP_BPP, 1, img) != 1)
96 fprintf (stderr, "unable to read image data\n");
97 else
98 {
99 /*fprintf (stderr, "read image %dx%d, %d\n", image_width, image_height, image_depth); */
100 file_path[file_count++] = name;
101 }
102 }
103 }
104 }
105 }
106 }
107 fclose (img);
108 }
109 }
110 }
111 }
112
113 /* if you are interested, the following code can detect hidden passwords
114 * stored in CP-masked-JPEG files.
115 */
116
117 /*
118 * sorry, the detect code was removed ;)
119 */
120
121 /*----------------------------------------------------------------------------*/
122
123 static u8 cp_key[] =
124 {
125 0x10, 0x17, 0x13, 0x15, 0x09, 0x08, 0x0a, 0x14, 0x06, 0x05, 0x16, 0x02, 0x0d,
126 0x03, 0x01, 0x04, 0x19, 0x0c, 0x0f, 0x0e, 0x12, 0x07, 0x0b, 0x18, 0x11, 0x1a
127 };
128
129 static cp_table_lu1[MAX_CP_WIDTH];
130 static cp_table_lu2[MAX_CP_WIDTH];
131
132 /* this is a bottleneck */
133 static void
134 cp_set_pw (u8 * pw, u8 * pw_end)
135 {
136 u8 *cursor;
137 int i, j, x, y, len;
138 int *table;
139 cp_cell *trans;
140
141 len = pw_end - pw;
142
143 for (i = x = y = 0, table = cp_table, trans = cp_trans;
144 i < cp_cells;
145 i++)
146 {
147 *table++ = -1;
148 trans->dst_x = x;
149 trans->dst_y = y;
150 trans->mirror = 0;
151 trans++;
152
153 if (++x == cp_width)
154 {
155 x = 0;
156 y++;
157 }
158 }
159
160 x = cp_cells - 1;
161 y = len + cp_cells % len;
162
163 for (i = 0, cursor = pw; i < cp_cells; i++)
164 {
165 x = cp_key[*cursor - 'A'] + x + y;
166
167 if (++cursor == pw_end)
168 cursor = pw;
169
170 if (x >= cp_cells)
171 x -= cp_cells;
172
173 if (x >= cp_cells)
174 x -= cp_cells;
175
176 while (cp_table[x] != -1)
177 {
178 ++x;
179 if (x >= cp_cells)
180 x = 0;
181 }
182
183 cp_table[x] = i;
184 y++;
185
186 if (++i >= cp_cells)
187 break;
188
189 x = cp_key[*cursor - 'A'] + x + y;
190
191 if (++cursor == pw_end)
192 cursor = pw;
193
194 if (x >= cp_cells)
195 x -= cp_cells;
196
197 if (x >= cp_cells)
198 x -= cp_cells;
199
200 while (cp_table[x] != -1)
201 {
202 if (x == 0)
203 x = cp_cells;
204
205 x--;
206 }
207
208 cp_table[x] = i;
209 y++;
210 }
211
212 for (i = 0, j = cp_cells - 1; i < j; i++, j--)
213 {
214 cp_trans[cp_table[i]].dst_x = cp_table_lu1[j];
215 cp_trans[cp_table[i]].dst_y = cp_table_lu2[j];
216 cp_trans[cp_table[j]].dst_x = cp_table_lu1[i];
217 cp_trans[cp_table[j]].dst_y = cp_table_lu2[i];
218
219 if ((cp_table[i] ^ cp_table[j]) & 1)
220 {
221 cp_trans[cp_table[i]].mirror = 1;
222 cp_trans[cp_table[j]].mirror = 1;
223 }
224 }
225 }
226
227 /*----------------------------------------------------------------------------*/
228
229 static void
230 cp_do_mask (void)
231 {
232 UI x, y, src_x, src_y;
233 UI u, v, dst_x, dst_y;
234 UI xx;
235 int rot;
236 cp_cell *cell = cp_trans;
237
238 for (y = 0; y < cp_height; ++y)
239 {
240 for (x = 0; x < cp_width; ++x)
241 {
242 {
243 u = cell->dst_x;
244 v = cell->dst_y;
245 rot = cell->mirror;
246 cell++;
247 dst_x = x * CP_CELL_SIZE + OFFSET_X;
248 dst_y = y * CP_CELL_SIZE + OFFSET_Y;
249 src_x = u * CP_CELL_SIZE + OFFSET_X;
250 src_y = v * CP_CELL_SIZE + OFFSET_Y;
251 }
252
253 #define COPY(sx,sy,dx,dy) do { \
254 u8 *s = &src_pixel (src_x + (sx), src_y + (sy), 0); \
255 u8 *d = &dst_pixel (dst_x + (dx), dst_y + (dy), 0); \
256 *d++ = *s++; \
257 *d++ = *s++; \
258 *d++ = *s++; \
259 } while(0)
260
261 if (dst_x + CP_CELL_SIZE <= transform_width &&
262 dst_y + CP_CELL_SIZE <= transform_height)
263 {
264 if (rot)
265 {
266 /* this is shit */
267 for (xx = CP_CELL_SIZE - 1; xx--;)
268 {
269 COPY (xx + 1, 0, 0, xx + 1);
270 COPY (0, xx, xx, 0);
271 COPY (xx, CP_CELL_SIZE - 1, CP_CELL_SIZE - 1, xx);
272 COPY (CP_CELL_SIZE - 1, xx + 1, xx + 1, CP_CELL_SIZE - 1);
273 }
274 }
275 else
276 {
277 for (xx = CP_CELL_SIZE; xx--;)
278 {
279 COPY (xx + 1, 0, xx + 1, 0);
280 COPY (0, xx, 0, xx);
281 COPY (xx, CP_CELL_SIZE - 1, xx, CP_CELL_SIZE - 1);
282 COPY (CP_CELL_SIZE - 1, xx + 1, CP_CELL_SIZE - 1, xx + 1);
283 }
284 }
285 }
286
287 #undef COPY
288 }
289 }
290 // {FILE *f=fopen("x.ppm","wb"); fprintf (f,"P6 %d %d %d ",transform_width,transform_height,255); fwrite(transform_data,transform_width*transform_height*CP_BPP,1,f); fclose(f); }
291 }
292
293 static void
294 cp_cleanup (void)
295 {
296 if (cp_table)
297 free (cp_table);
298
299 if (cp_trans)
300 free (cp_trans);
301 }
302
303 static void
304 init_cpmask (void)
305 {
306 UI i;
307
308 assert (image_data);
309 cp_width = image_width / CP_CELL_SIZE;
310 cp_height = image_height / CP_CELL_SIZE;
311 cp_cells = cp_width * cp_height;
312 cp_table = (int *) malloc (sizeof (int) * cp_cells);
313 cp_trans = (cp_cell *) malloc (sizeof (cp_cell) * cp_cells);
314
315 if (cp_width > MAX_CP_WIDTH)
316 {
317 printf ("maximum image width in this version is %d\n", MAX_CP_WIDTH * CP_CELL_SIZE);
318 exit (1);
319 }
320
321 for (i = 0; i < MAX_CP_WIDTH; i++)
322 {
323 cp_table_lu1[i] = i % cp_width;
324 cp_table_lu2[i] = i / cp_width;
325 }
326
327 transform_width = image_width < CP_CELL_SIZE * MAX_SIZE ? image_width : CP_CELL_SIZE * MAX_SIZE;
328 transform_height = image_height < CP_CELL_SIZE * MAX_SIZE ? image_height : CP_CELL_SIZE * MAX_SIZE;
329
330 transform_data = (u8 *) malloc (transform_width * transform_height * CP_BPP);
331 }
332
333 static int
334 crack_cpmask (gen_func genfunc, callback_func cbfunc)
335 {
336 unsigned long minimum = 1 << 31;
337 unsigned long current;
338 int changed = -1;
339 int x, y;
340
341 do
342 {
343 if (changed >= 4 && verbosity)
344 printf ("checking pw %s\r", pw), fflush (stdout);
345
346 if (changed < 0)
347 pw_end = pw + strlen (pw);
348
349 cp_set_pw (pw, pw_end);
350 cp_do_mask ();
351
352 #define P(x,y,c) (UI)dst_pixel((x),(y),(c))
353 current = 0;
354
355 for (x = CP_CELL_SIZE; x < transform_width; x += CP_CELL_SIZE)
356 for (y = transform_height; y--;)
357 {
358 current += abs (P (x - 1, y, 0) - P (x, y, 0));
359 current += abs (P (x - 1, y, 1) - P (x, y, 1));
360 current += abs (P (x - 1, y, 2) - P (x, y, 2));
361
362 if (current > minimum)
363 goto overflow;
364 }
365
366 for (y = CP_CELL_SIZE; y < transform_height && current < minimum; y += CP_CELL_SIZE)
367 for (x = transform_width; x-- && current < minimum;)
368 {
369 current += abs (P (x, y - 1, 0) - P (x, y, 0));
370 current += abs (P (x, y - 1, 1) - P (x, y, 1));
371 current += abs (P (x, y - 1, 2) - P (x, y, 2));
372
373 if (current > minimum)
374 goto overflow;
375 }
376 #undef P
377
378 overflow:
379 if (current < minimum)
380 {
381 char info[80];
382
383 minimum = current + 99;
384
385 sprintf (info, "badness %ld", current);
386
387 if ((changed = cbfunc (pw, info)))
388 return changed;
389 }
390
391 }
392 while ((changed = genfunc ()));
393
394 return 0;
395 }