source: pwntcha/trunk/src/vbulletin.c @ 421

Last change on this file since 421 was 421, checked in by Sam Hocevar, 16 years ago
  • keep the font loaded across decodings.
  • Property svn:keywords set to Id
File size: 3.7 KB
Line 
1/*
2 * vbulletin.c: decode vbulletin captchas
3 * $Id: vbulletin.c 421 2005-01-05 00:18:49Z sam $
4 *
5 * Copyright: (c) 2005 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#include <limits.h>
16
17#include "config.h"
18#include "common.h"
19
20#define FONTNAME "share/font_vbulletin.png"
21static struct image *font = NULL;
22
23/* Main function */
24char *decode_vbulletin(struct image *img)
25{
26    char all[] = "2346789ABCDEFGHJKLMNPRTWXYZ";
27    char *result;
28    struct image *tmp1, *tmp2, *tmp3;
29    int limits[6] = { 26, 53, 80, 107, 134, 160 };
30    int x, y, r, g, b, i, j;
31
32    if(!font)
33    {
34        font = image_load(FONTNAME);
35        if(!font)
36        {
37            fprintf(stderr, "cannot load font %s\n", FONTNAME);
38            exit(-1);
39        }
40    }
41
42    /* vBulletin captchas have 6 characters */
43    result = malloc(7 * sizeof(char));
44    strcpy(result, "      ");
45
46    /* half the captchas are inverse video; we set them back to normal */
47    getpixel(img, 0, 0, &r, &g, &b);
48    if(r < 50)
49        tmp1 = filter_equalize(img, 128);
50    else
51        tmp1 = filter_equalize(img, -128);
52
53    /* Remove garbage around the cells */
54    for(x = 0; x < img->width; x++)
55    {
56        for(y = 0; y < 15; y++)
57            setpixel(tmp1, x, y, 255, 255, 255);
58        for(y = 45; y < img->height; y++)
59            setpixel(tmp1, x, y, 255, 255, 255);
60    }
61
62    for(x = 0; x < img->width; x++)
63    {
64        for(i = 0; i < 6; i++)
65            if(x == limits[i])
66                break;
67        if(i == 6)
68            for(y = 15; y < 45; y++)
69                setpixel(tmp1, x, y, 255, 255, 255);
70        else
71            x += 11;
72    }
73
74    tmp2 = filter_black_stuff(tmp1);
75    tmp3 = filter_black_stuff(tmp2);
76
77    /* Fill letters in gray */
78    for(x = 26; x < 172; x++)
79    {
80        getpixel(tmp3, x, 15, &r, &g, &b);
81        if(r == 0)
82            filter_flood_fill(tmp3, x, 15, 127, 0, 255);
83    }
84
85    /* Find remaining black parts and remove them */
86    for(x = 26; x < 172; x++)
87        for(y = 15; y < 45; y++)
88        {
89            getpixel(tmp3, x, y, &r, &g, &b);
90            if(r == 0)
91                filter_flood_fill(tmp3, x, y, 255, 255, 255);
92        }
93
94    /* Fill letters in black */
95    for(x = 26; x < 172; x++)
96    {
97        getpixel(tmp3, x, 44, &r, &g, &b);
98        if(r == 127)
99            filter_flood_fill(tmp3, x, 44, 0, 0, 0);
100    }
101
102    /* Find remaining gray parts and remove them */
103    for(x = 26; x < 172; x++)
104        for(y = 15; y < 45; y++)
105        {
106            getpixel(tmp3, x, y, &r, &g, &b);
107            if(r == 127)
108                filter_flood_fill(tmp3, x, y, 255, 255, 255);
109        }
110
111    /* Guess all glyphs */
112    for(i = 0; i < 6; i++)
113    {
114        struct image *new;
115        int mindist = INT_MAX, min = -1;
116        new = filter_crop(tmp3, limits[i], 15, limits[i] + 11, 45);
117        for(j = 0; j < 27; j++)
118        {
119            int dist = 0;
120            for(y = 0; y < new->height; y++)
121                for(x = 0; x < new->width; x++)
122                {
123                    int r2, g2, b2;
124                    getpixel(font, 12 * j + x, y, &r, &g, &b);
125                    getpixel(new, x, y, &r2, &g2, &b2);
126                    dist += (r - r2) * (r - r2);
127                }
128            if(dist < mindist)
129            {
130                mindist = dist;
131                min = j;
132            }
133        }
134        image_free(new);
135        result[i] = all[min];
136    }
137
138    image_free(tmp1);
139    image_free(tmp2);
140    image_free(tmp3);
141
142    return result;
143}
144
Note: See TracBrowser for help on using the repository browser.