source: pwntcha/trunk/src/scode.c @ 465

Last change on this file since 465 was 465, checked in by Sam Hocevar, 17 years ago
  • Workaround for problems with Gandi captchas.
  • Property svn:keywords set to Id
File size: 5.1 KB
Line 
1/*
2 * scode.c: decode scode captchas
3 * $Id: scode.c 465 2005-01-18 14:34:23Z sam $
4 *
5 * Copyright: (c) 2004 Sam Hocevar <sam@zoy.org>
6 *   This program is free software; you can redistribute it and/or
7 *   modify it under the terms of the Do What The Fuck You Want To
8 *   Public License as published by Banlu Kemiyatorn. See
9 *   http://sam.zoy.org/projects/COPYING.WTFPL for more details.
10 */
11
12#include <stdio.h>
13#include <stdlib.h>
14#include <string.h>
15
16#include "config.h"
17#include "common.h"
18
19static char find_glyph(struct image *img, int xmin, int xmax);
20
21/* Main function */
22char *decode_scode(struct image *img)
23{
24    char *result;
25    int stats[3 * 256];
26    int x, y, i, incell = 0, cur = 0, xmin = 0;
27    int r, g, b;
28    struct image *tmp1;
29
30    /* allocate enough place */
31    result = malloc(1024 * sizeof(char));
32
33    tmp1 = image_dup(img);
34
35    /* Remove border */
36    getpixel(img, 1, 1, &r, &g, &b);
37    for(y = 0; y < img->height; y++)
38    {
39        setpixel(tmp1, 0, y, r, g, b);
40        setpixel(tmp1, img->width - 1, y, r, g, b);
41    }
42
43    for(x = 0; x < img->width; x++)
44    {
45        setpixel(tmp1, x, 0, r, g, b);
46        setpixel(tmp1, x, img->height - 1, r, g, b);
47    }
48
49    /* Detect background: first and last 3 lines */
50    for(i = 0; i < 3 * 256; i++)
51        stats[i] = 0;
52
53    for(y = 0; y < 6; y++)
54    {
55        int y2 = (y & 1) ? img->width - 1 - y / 2 : y / 2;
56        for(x = 0; x < img->width; x++)
57        {
58            getpixel(tmp1, x, y2, &r, &g, &b);
59            if(stats[r + g + b] == 0)
60            {
61                /* Parse middle line to see if this colour can be removed */
62                int available = 0, x2, r2, g2, b2;
63                stats[r + g + b] = 1;
64                for(x2 = 0; x2 < img->width; x2++)
65                {
66                    getpixel(tmp1, x2, img->width / 2, &r2, &g2, &b2);
67                    if(stats[r2 + g2 + b2] == 0)
68                        available = 1;
69                }
70                if(!available)
71                    stats[r + g + b] = 2;
72            }
73        }
74    }
75
76    /* Set non-background colours to 0 */
77    for(y = 0; y < img->height; y++)
78        for(x = 0; x < img->width; x++)
79        {
80            getpixel(tmp1, x, y, &r, &g, &b);
81            if(stats[r + g + b] == 1)
82                setpixel(tmp1, x, y, 255, 255, 255);
83            else
84                setpixel(tmp1, x, y, 0, 0, 0);
85        }
86
87    /* Decode glyphs */
88    for(x = 0; x < img->width; x++)
89    {
90        int found = 0;
91        for(y = 0; y < img->height; y++)
92        {
93            getpixel(tmp1, x, y, &r, &g, &b);
94            if(!r)
95            {
96                found = 1;
97                break;
98            }
99        }
100        if(found && !incell)
101        {
102            incell = 1;
103            xmin = x;
104        }
105        else if(!found && incell)
106        {
107            incell = 0;
108            /* Find glyph */
109            result[cur++] = find_glyph(tmp1, xmin, x);
110        }
111    }
112
113    image_free(tmp1);
114    result[cur] = '\0';
115
116    return result;
117}
118
119static char find_glyph(struct image *img, int xmin, int xmax)
120{
121    int ymin = -1, ymax = -1;
122    int x, y, count = 0;
123    int r, g, b;
124
125    /* Compute vertical bounds of glyph */
126    for(y = 0; y < img->height; y++)
127    {
128        int found = 0;
129        for(x = xmin; x < xmax; x++)
130        {
131            getpixel(img, x, y, &r, &g, &b);
132            if(!r)
133            {
134                found = 1;
135                break;
136            }
137        }
138        if(found)
139        {
140            if(ymin == -1)
141                ymin = y;
142            else
143                ymax = y + 1;
144        }
145    }
146
147    for(x = xmin; x < xmax; x++)
148    {
149        for(y = ymin; y < ymax; y++)
150        {
151            getpixel(img, x, y, &r, &g, &b);
152            if(!r)
153                count += 5 * (y - ymin) ^ 3 * (x - xmin);
154                //count += y - ymin;
155        }
156    }
157
158    switch(count)
159    {
160        /* Scode font */
161        case 778: return '0';
162        case 621: return '1';
163        case 854: return '2';
164        case 784: return '3';
165        case 766: return '4';
166        case 771: return '5';
167        case 976: return '6';
168        case 585: return '7';
169        case 980: return '8';
170        case 896: return '9';
171        /* Small font */
172        case 584: return '0';
173        case 454: return '1';
174        case 517: return '2';
175        case 447: return '3';
176        case 469: return '4';
177        case 472: return '5';
178        case 564: return '6';
179        case 298: return '7';
180        case 560: return '8';
181        case 536: return '9';
182        /* Thin font */
183        case 438: return '0';
184        case 405: return '1';
185        case 485: return '2';
186        case 486: return '3';
187        case 413: return '4';
188        case 509: return '5';
189        case 582: return '6';
190        case 242: return '7';
191        case 579: return '8';
192        case 440: return '9';
193#if 0
194        case 162: return '0';
195        case 131: return '1';
196        case 150: return '2';
197        case 139: return '3';
198        case 155: return '4';
199        case 159: return '5';
200        case 181: return '6';
201        case  90: return '7';
202        case 180: return '8';
203        case 170: return '9';
204#endif
205        default:
206            dprintf("don't know about checksum %i\n", count);
207            return '?';
208    }
209}
210
Note: See TracBrowser for help on using the repository browser.