diff --git a/share/font_stencil_23_AZ.bmp b/share/font_stencil_23_AZ.bmp new file mode 100644 index 0000000..34b74f8 Binary files /dev/null and b/share/font_stencil_23_AZ.bmp differ diff --git a/share/font_stencil_24_AZ.bmp b/share/font_stencil_24_AZ.bmp new file mode 100644 index 0000000..3756ff9 Binary files /dev/null and b/share/font_stencil_24_AZ.bmp differ diff --git a/src/Makefile.am b/src/Makefile.am index ccf1f92..bd4edc0 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -10,6 +10,7 @@ pwntcha_SOURCES = \ authimage.c \ clubic.c \ linuxfr.c \ + paypal.c \ phpbb.c \ scode.c \ slashdot.c \ diff --git a/src/common.h b/src/common.h index 2e37701..f193b2b 100644 --- a/src/common.h +++ b/src/common.h @@ -41,6 +41,7 @@ void dprintf(const char *fmt, ...); char *decode_authimage(struct image *img); char *decode_clubic(struct image *img); char *decode_linuxfr(struct image *img); +char *decode_paypal(struct image *img); char *decode_phpbb(struct image *img); char *decode_scode(struct image *img); char *decode_slashdot(struct image *img); diff --git a/src/main.c b/src/main.c index 51d6065..684ec75 100644 --- a/src/main.c +++ b/src/main.c @@ -138,6 +138,8 @@ int main(int argc, char *argv[]) result = decode_clubic(img); else if(!strcmp(mode, "linuxfr")) result = decode_linuxfr(img); + else if(!strcmp(mode, "paypal")) + result = decode_paypal(img); else if(!strcmp(mode, "phpbb")) result = decode_phpbb(img); else if(!strcmp(mode, "scode")) @@ -160,6 +162,11 @@ int main(int argc, char *argv[]) dprintf("autodetected linuxfr captcha\n"); result = decode_linuxfr(img); } + else if(img->width == 208 && img->height == 26) + { + dprintf("autodetected Paypal captcha\n"); + result = decode_paypal(img); + } else if(img->width == 320 && img->height == 50) { dprintf("autodetected phpBB captcha\n"); diff --git a/src/paypal.c b/src/paypal.c new file mode 100644 index 0000000..310a3c2 --- /dev/null +++ b/src/paypal.c @@ -0,0 +1,135 @@ +/* + * paypal.c: decode Paypal captchas + * $Id$ + * + * Copyright: (c) 2005 Sam Hocevar + * This program is free software; you can redistribute it and/or + * modify it under the terms of the Do What The Fuck You Want To + * Public License as published by Banlu Kemiyatorn. See + * http://sam.zoy.org/projects/COPYING.WTFPL for more details. + */ + +#include +#include +#include +#include + +#include "config.h" +#include "common.h" + +static void find_glyphs(struct image *img); + +/* Our macros */ +char *result; + +/* Main function */ +char *decode_paypal(struct image *img) +{ + struct image *tmp; + + /* paypal captchas have 8 characters */ + result = malloc(9 * sizeof(char)); + strcpy(result, " "); + + tmp = image_dup(img); + find_glyphs(tmp); + + image_free(tmp); + + return result; +} + +static void find_glyphs(struct image *img) +{ +#define DELTA 2 +#define FONTS 2 + static struct font *fonts[FONTS]; + static char *files[] = + { + "font_stencil_23_AZ.bmp", "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ", + "font_stencil_24_AZ.bmp", "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ", + }; + int x, y, i = 0, f; + int r, g, b; + int xmin, xmax, ymin, ymax, startx = 0, cur = 0; + int bestdist, bestfont, bestx, besty, bestch; + + for(f = 0; f < FONTS; f++) + { + if(!fonts[f]) + { + fonts[f] = font_load_variable(files[f * 2], files[f * 2 + 1]); + if(!fonts[f]) + exit(1); + } + } + + while(cur < 8) + { + /* Try to find 1st letter */ + bestdist = INT_MAX; + for(f = 0; f < FONTS; f++) for(i = 0; i < fonts[f]->size; i++) + { + int localmin = INT_MAX, localx, localy; + xmin = fonts[f]->glyphs[i].xmin - DELTA; + ymin = fonts[f]->glyphs[i].ymin; + xmax = fonts[f]->glyphs[i].xmax + DELTA; + ymax = fonts[f]->glyphs[i].ymax; + for(y = -3; y < 1; y++) + { + for(x = startx; x < startx + 15; x++) + { + int z, t, dist; + dist = 0; + for(t = 0; t < ymax - ymin; t++) + for(z = 0; z < xmax - xmin; z++) + { + int r2; + getgray(fonts[f]->img, xmin + z, ymin + t, &r); + getgray(img, x + z, y + t, &r2); + if(r < r2) + dist += abs(r - r2); + else + dist += abs(r - r2) * 3 / 4; + } + //dist = dist * 128 / fonts[f]->glyphs[i].count; + dist = dist * 1024 / (xmax - xmin - 2 * DELTA); + if(dist < localmin) + { + localmin = dist; + localx = x; + localy = y; + } + } + } + if(localmin < bestdist) + { + bestdist = localmin; + bestfont = f; + bestx = localx; + besty = localy; + bestch = i; + } + } + + /* Print min glyph */ +#if 0 + xmin = fonts[bestfont]->glyphs[bestch].xmin - DELTA; + ymin = fonts[bestfont]->glyphs[bestch].ymin; + xmax = fonts[bestfont]->glyphs[bestch].xmax + DELTA; + ymax = fonts[bestfont]->glyphs[bestch].ymax; + for(y = 0; y < ymax - ymin; y++) + for(x = 0; x < xmax - xmin; x++) + { + getpixel(fonts[bestfont]->img, xmin + x, ymin + y, &r, &g, &b); + if(r > 128) + continue; + setpixel(img, bestx + x, besty + y, r, g, b); + } +#endif + + startx = bestx + xmax - xmin; + result[cur++] = fonts[bestfont]->glyphs[bestch].c; + } +} +