source: pwntcha/trunk/src/xanga.c @ 2315

Last change on this file since 2315 was 2315, checked in by Sam Hocevar, 12 years ago
  • Update build system and licensing terms to 2008 standards.
  • Property svn:keywords set to Id
File size: 7.1 KB
RevLine 
[444]1/*
2 * xanga.c: decode Xanga captchas
3 * $Id: xanga.c 2315 2008-04-26 07:25:03Z sam $
4 *
5 * Copyright: (c) 2005 Sam Hocevar <sam@zoy.org>
[2315]6 *  This program is free software. It comes without any warranty, to
7 *  the extent permitted by applicable law. You can redistribute it
8 *  and/or modify it under the terms of the Do What The Fuck You Want
9 *  To Public License, Version 2, as published by Sam Hocevar. See
10 *  http://sam.zoy.org/wtfpl/COPYING for more details.
[444]11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <limits.h>
17#include <math.h>
18
19#include "config.h"
20#include "common.h"
21
[445]22static void fill_white_holes(struct image *img);
[453]23static void find_glyphs(struct image *img);
[444]24
[453]25static char *result;
26
[444]27/* Main function */
28char *decode_xanga(struct image *img)
29{
[445]30    struct image *tmp;
[444]31
[453]32    /* Xanga captchas have 6 characters */
33    result = malloc(7 * sizeof(char));
34    strcpy(result, "      ");
[444]35
[445]36    tmp = image_dup(img);
37image_save(tmp, "xanga1.bmp");
[444]38    /* Clean image a bit */
[482]39//    filter_threshold(tmp, 200);
[445]40    filter_contrast(tmp);
41    //filter_detect_lines(tmp);
42image_save(tmp, "xanga2.bmp");
43    fill_white_holes(tmp);
44//    filter_fill_holes(tmp);
[453]45    filter_smooth(tmp);
46    //filter_median(tmp);
[445]47image_save(tmp, "xanga3.bmp");
48    //filter_detect_lines(tmp);
49//    filter_median(tmp);
50//image_save(tmp, "xanga4.bmp");
[482]51//    filter_threshold(tmp, 128);
[453]52    filter_contrast(tmp);
[445]53image_save(tmp, "xanga4.bmp");
[444]54
[453]55#if 0
[444]56    /* Detect small objects to guess image orientation */
[445]57    filter_median(tmp);
[482]58    filter_threshold(tmp, 200);
[444]59
60    /* Invert rotation and find glyphs */
[445]61    filter_median(tmp);
[453]62#endif
63    find_glyphs(tmp);
64image_save(tmp, "xanga5.bmp");
[444]65
66    /* Clean up our mess */
[445]67    image_free(tmp);
[444]68
69    /* aaaaaaa means decoding failed */
70    if(!strcmp(result, "aaaaaaa"))
71        result[0] = '\0';
72
73    return result;
74}
75
76/* The following functions are local */
77
[445]78static void fill_white_holes(struct image *img)
[444]79{
[445]80    struct image *tmp;
[448]81    int x, y;
[444]82    int r, g, b;
83
[445]84    tmp = image_new(img->width, img->height);
[444]85
86    for(y = 0; y < img->height; y++)
87        for(x = 0; x < img->width; x++)
88        {
89            getpixel(img, x, y, &r, &g, &b);
[445]90            setpixel(tmp, x, y, r, g, b);
[444]91        }
92
93    for(y = 1; y < img->height - 1; y++)
94        for(x = 1; x < img->width - 1; x++)
95        {
96            int count = 0;
97            getpixel(img, x, y, &r, &g, &b);
98            if(r <= 16)
99                continue;
100            getpixel(img, x + 1, y, &r, &g, &b);
101            count += r;
102            getpixel(img, x - 1, y, &r, &g, &b);
103            count += r;
104            getpixel(img, x, y + 1, &r, &g, &b);
105            count += r;
106            getpixel(img, x, y - 1, &r, &g, &b);
107            count += r;
108            if(count > 600)
109                continue;
[445]110            setpixel(tmp, x, y, count / 5, count / 5, count / 5);
[444]111        }
112
[445]113    image_swap(tmp, img);
114    image_free(tmp);
[444]115}
116
[453]117static void find_glyphs(struct image *img)
118{
119#define FONTS 6
120    static struct font *fonts[FONTS];
121    static char *files[] =
122    {
123        "x_font_freemonobold_32_az.bmp", "abcdefghijklmnopqrstuvwxyz",
124        "x_font_freemonobold_24_az.bmp", "abcdefghijklmnopqrstuvwxyz",
125        "x_font_freesansbold_32_az.bmp", "abcdefghijklmnopqrstuvwxyz",
126        //"x_font_freeserifbold_32_az.bmp", "abcdefghijklmnopqrstuvwxyz",
127        "x_font_comic_32_az.bmp", "abcdefghijklmnopqrstuvwxyz",
128        "x_font_comic_24_az_messed.bmp", "abcdefghijklmnopqrstuvwxyz",
129        "x_font_freesansbold_36_az_messed.bmp", "abcdefghijklmnopqrstuvwxyz",
130    };
131    struct image *tmp;
132    int x, y, i = 0, f;
133    int r, g, b;
[460]134    int xmin, xmax, ymin, ymax, cur = 0;
[453]135    int bestdist, bestfont, bestx, besty, bestch;
136
137    for(f = 0; f < FONTS; f++)
138    {
139        if(!fonts[f])
140        {
141            fonts[f] = font_load_variable(files[f * 2], files[f * 2 + 1]);
142            if(!fonts[f])
143                exit(1);
144            //filter_smooth(fonts[f]->img);
145            //filter_contrast(fonts[f]->img);
146        }
147    }
148
149    tmp = image_new(img->width, img->height);
150
151    for(y = 0; y < img->height; y++)
152        for(x = 0; x < img->width; x++)
153        {
154            getpixel(img, x, y, &r, &g, &b);
155            setpixel(tmp, x, y, 255, g, 255);
156        }
157
158    while(cur < 6)
159    {
160        /* Try to find 1st letter */
161        bestdist = INT_MAX;
162        for(f = 0; f < FONTS; f++) for(i = 0; i < fonts[f]->size; i++)
163        {
164            int localmin = INT_MAX, localx, localy;
165int sqr;
166            if(fonts[f]->glyphs[i].c == 'l' || fonts[f]->glyphs[i].c == 'z')
167                continue;
168            xmin = fonts[f]->glyphs[i].xmin - 5;
169            ymin = fonts[f]->glyphs[i].ymin - 3;
170            xmax = fonts[f]->glyphs[i].xmax + 5;
171            ymax = fonts[f]->glyphs[i].ymax + 3;
172sqr = sqrt(xmax - xmin);
173            for(y = -15; y < 15; y++)
174                for(x = 22 - (xmax - xmin) / 2 + 25 * cur; x < 28 - (xmax - xmin) / 2 + 25 * cur; x++)
175                {
176                    int z, t, dist;
177                    dist = 0;
178                    for(t = 0; t < ymax - ymin; t++)
179                        for(z = 0; z < xmax - xmin; z++)
180                        {
181                            int r2;
182                            getgray(fonts[f]->img, xmin + z, ymin + t, &r);
183                            getgray(img, x + z, y + t, &r2);
184                            if(r < r2)
185                                dist += (r - r2) * (r - r2);
186                            else
187                                dist += (r - r2) * (r - r2) * 3 / 4;
188                        }
189    //                printf("%i %i -> %i\n", x, y, dist);
190//                    dist /= (xmax - xmin);
191//                    dist = dist / sqrt((ymax - ymin) * (xmax - xmin)) / (xmax - xmin);
192                    dist = dist / (xmax - xmin) / sqr;
193//                    dist = dist * 128 / fonts[f]->glyphs[i].count;
194                    if(dist < localmin)
195                    {
196                        localmin = dist;
197                        localx = x;
198                        localy = y;
199                    }
200                }
201            if(localmin < bestdist)
202            {
203//printf("  bestch is now %i (%c) in font %i\n", i, fonts[f]->glyphs[i].c, f);
204                bestdist = localmin;
205                bestfont = f;
206                bestx = localx;
207                besty = localy;
208                bestch = i;
209            }
210        }
211//printf("%i (%c) in font %i\n", i, fonts[bestfont]->glyphs[bestch].c, bestfont);
212//printf("%i < %i < %i\n", 10 + 25 * cur, bestx, 30 + 25 * cur);
213
214        /* Draw best glyph in picture (debugging purposes) */
215        xmin = fonts[bestfont]->glyphs[bestch].xmin - 5;
216        ymin = fonts[bestfont]->glyphs[bestch].ymin - 3;
217        xmax = fonts[bestfont]->glyphs[bestch].xmax + 5;
218        ymax = fonts[bestfont]->glyphs[bestch].ymax + 3;
219        for(y = 0; y < ymax - ymin; y++)
220            for(x = 0; x < xmax - xmin; x++)
221            {
222                getpixel(fonts[bestfont]->img, xmin + x, ymin + y, &r, &g, &b);
223                if(r > 128) continue;
224                setpixel(tmp, bestx + x, besty + y, r, g, b);
225            }
226
227        result[cur++] = fonts[bestfont]->glyphs[bestch].c;
228    }
229
230    image_swap(img, tmp);
231    image_free(tmp);
232}
233
Note: See TracBrowser for help on using the repository browser.