From ba195bbc65ba9fddf598b92d213eb32582a84ea8 Mon Sep 17 00:00:00 2001 From: sam Date: Mon, 3 Jan 2005 21:48:54 +0000 Subject: [PATCH] * use OpenCV rather than Imlib2 if both are available. * cleaned up the slashdot code. * decode phpBB captchas. * added filter_contrast. git-svn-id: file:///srv/caca.zoy.org/var/lib/svn/pwntcha/trunk@389 92316355-f0b4-4df1-b90c-862c8a59935f --- configure.ac | 26 ++++---- share/font_phpbb.png | Bin 0 -> 6379 bytes src/Makefile.am | 10 +-- src/common.h | 13 ++-- src/filters.c | 39 ++++++++++- src/image.c | 84 +++++++++++++---------- src/main.c | 25 ++++++- src/phpbb.c | 136 +++++++++++++++++++++++++++++++++++++ src/slashdot.c | 38 ++++++++--- src/test.c | 155 +++++++++++++++++++++++++++++++++++++++++++ 10 files changed, 456 insertions(+), 70 deletions(-) create mode 100644 share/font_phpbb.png create mode 100644 src/phpbb.c create mode 100644 src/test.c diff --git a/configure.ac b/configure.ac index 3b52bf4..56479cb 100644 --- a/configure.ac +++ b/configure.ac @@ -18,6 +18,19 @@ AC_C_CONST AC_C_INLINE AC_TYPE_SIZE_T +# Use OpenCV? +ac_cv_my_have_opencv="no" +save_CPPFLAGS="${CPPFLAGS}" +AC_PATH_PROG(OPENCV_CONFIG, opencv-config, no) +if test "${OPENCV_CONFIG}" != "no"; then + CPPFLAGS="${CPPFLAGS} `opencv-config --cflags`" +fi +AC_CHECK_HEADERS(cv.h, + [ac_cv_my_have_opencv="yes"], + [ac_cv_my_have_opencv="no"]) +CPPFLAGS="${save_CPPFLAGS}" +AM_CONDITIONAL(USE_OPENCV, test "${ac_cv_my_have_opencv}" = "yes") + # Use Imlib2? ac_cv_my_have_imlib2="no" save_CPPFLAGS="${CPPFLAGS}" @@ -31,19 +44,6 @@ AC_CHECK_HEADERS(Imlib2.h, CPPFLAGS="${save_CPPFLAGS}" AM_CONDITIONAL(USE_IMLIB2, test "${ac_cv_my_have_imlib2}" = "yes") -# Use Imlib2? -ac_cv_my_have_opencv="no" -save_CPPFLAGS="${CPPFLAGS}" -AC_PATH_PROG(OPENCV_CONFIG, opencv-config, no) -if test "${OPENCV_CONFIG}" != "no"; then - CPPFLAGS="${CPPFLAGS} `opencv-config --cflags`" -fi -AC_CHECK_HEADERS(cv.h, - [ac_cv_my_have_opencv="yes"], - [ac_cv_my_have_opencv="no"]) -CPPFLAGS="${save_CPPFLAGS}" -AM_CONDITIONAL(USE_OPENCV, test "${ac_cv_my_have_opencv}" = "yes") - if test "${ac_cv_my_have_imlib2}" = "no" -a "${ac_cv_my_have_opencv}" = "no"; then AC_MSG_ERROR([[cannot find Imlib2 or OpenCV, please install one of them]]) fi diff --git a/share/font_phpbb.png b/share/font_phpbb.png new file mode 100644 index 0000000000000000000000000000000000000000..3544a6bb85b7193cb8269705a486807d5f0a6653 GIT binary patch literal 6379 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 literal 0 HcmV?d00001 diff --git a/src/Makefile.am b/src/Makefile.am index 6a098f0..5dbe48a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -3,16 +3,16 @@ NULL = bin_PROGRAMS = pwntcha pwntcha_CFLAGS = $(ADDITIONAL_CFLAGS) -Wall -O6 pwntcha_LDFLAGS = $(ADDITIONAL_LDFLAGS) -pwntcha_SOURCES = main.c image.c filters.c slashdot.c common.h +pwntcha_SOURCES = main.c image.c filters.c common.h slashdot.c phpbb.c test.c -if USE_IMLIB2 -ADDITIONAL_CFLAGS = `imlib2-config --cflags` -DX_DISPLAY_MISSING=1 -ADDITIONAL_LDFLAGS = `imlib2-config --libs` -else if USE_OPENCV ADDITIONAL_CFLAGS = `opencv-config --cflags` ADDITIONAL_LDFLAGS = `opencv-config --libs opencv highgui` else +if USE_IMLIB2 +ADDITIONAL_CFLAGS = `imlib2-config --cflags` -DX_DISPLAY_MISSING=1 +ADDITIONAL_LDFLAGS = `imlib2-config --libs` +else ADDITIONAL_CFLAGS = ADDITIONAL_LDFLAGS = endif diff --git a/src/common.h b/src/common.h index a980ba2..8abea54 100644 --- a/src/common.h +++ b/src/common.h @@ -18,11 +18,15 @@ struct image }; /* available CAPTCHA decoders */ -char * decode_slashdot(struct image *img); +char *decode_phpbb(struct image *img); +char *decode_slashdot(struct image *img); +char *decode_test(struct image *img); /* image operations */ -struct image * image_load(char *name); -struct image * image_new(int width, int height); +struct image *image_load(char *name); +struct image *image_new(int width, int height); +void image_free(struct image *img); +void image_display(struct image *img); int getgray(struct image *img, int x, int y, int *g); int getpixel(struct image *img, int x, int y, int *r, int *g, int *b); int setpixel(struct image *img, int x, int y, int r, int g, int b); @@ -31,8 +35,9 @@ int setpixel(struct image *img, int x, int y, int r, int g, int b); void filter_flood_fill(struct image *img, int x, int y, int r, int g, int b); struct image *filter_fill_holes(struct image *img); struct image *filter_detect_lines(struct image *img); -struct image *filter_equalize(struct image *img); +struct image *filter_equalize(struct image *img, int threshold); struct image *filter_trick(struct image *img); struct image *filter_smooth(struct image *img); struct image *filter_median(struct image *img); +struct image *filter_contrast(struct image *img); diff --git a/src/filters.c b/src/filters.c index c3aedf0..44501d3 100644 --- a/src/filters.c +++ b/src/filters.c @@ -142,7 +142,7 @@ struct image *filter_detect_lines(struct image *img) return dst; } -struct image *filter_equalize(struct image *img) +struct image *filter_equalize(struct image *img, int threshold) { struct image *dst; int x, y; @@ -154,7 +154,7 @@ struct image *filter_equalize(struct image *img) for(x = 0; x < img->width; x++) { getpixel(img, x, y, &r, &g, &b); - if(r < 200) r = 50; else r = 200; + if(r < threshold) r = 0; else r = 255; setpixel(dst, x, y, r, r, r); } @@ -240,7 +240,7 @@ struct image *filter_smooth(struct image *img) struct image *filter_median(struct image *img) { -#define MSIZE 4 +#define MSIZE 3 struct image *dst; int x, y, i, j, val[MSIZE*MSIZE]; int r, g, b; @@ -278,3 +278,36 @@ struct image *filter_median(struct image *img) return dst; } +struct image *filter_contrast(struct image *img) +{ + struct image *dst; + int histo[256]; + int x, y, i, min = 255, max = 0; + int r, g, b; + + dst = image_new(img->width, img->height); + + for(y = 0; y < img->height; y++) + for(x = 0; x < img->width; x++) + { + getgray(img, x, y, &r); + if(r < min) min = r; + if(r > max) max = r; + } + + if(min == max) + histo[min] = 127; + else + for(i = min; i < max; i++) + histo[i] = (i - min) * 255 / (max - min); + + for(y = 0; y < img->height; y++) + for(x = 0; x < img->width; x++) + { + getgray(img, x, y, &r); + setpixel(dst, x, y, histo[r], histo[r], histo[r]); + } + + return dst; +} + diff --git a/src/image.c b/src/image.c index f580eec..f9d47ac 100644 --- a/src/image.c +++ b/src/image.c @@ -15,79 +15,93 @@ #include "config.h" #include "common.h" -#if defined(HAVE_IMLIB2_H) -# include -#elif defined(HAVE_CV_H) +#if defined(HAVE_CV_H) # include # include +#elif defined(HAVE_IMLIB2_H) +# include #else # error "No imaging library" #endif -struct image * image_load(char *name) +struct image *image_load(char *name) { - struct image * img; -#if defined(HAVE_IMLIB2_H) + struct image *img; +#if defined(HAVE_CV_H) + IplImage *priv = cvLoadImage(name, -1); +#elif defined(HAVE_IMLIB2_H) Imlib_Image priv = imlib_load_image(name); -#elif defined(HAVE_CV_H) - IplImage * priv = cvLoadImage(name, -1); #endif if(!priv) return NULL; img = malloc(sizeof(struct image)); -#if defined(HAVE_IMLIB2_H) +#if defined(HAVE_CV_H) + img->width = priv->width; + img->height = priv->height; + img->pitch = priv->widthStep; + img->channels = priv->nChannels; + img->pixels = priv->imageData; +#elif defined(HAVE_IMLIB2_H) imlib_context_set_image(priv); img->width = imlib_image_get_width(); img->height = imlib_image_get_height(); img->pitch = 4 * imlib_image_get_width(); img->channels = 4; img->pixels = (char *)imlib_image_get_data(); -#elif defined(HAVE_CV_H) - img->width = priv->width; - img->height = priv->height; - img->pitch = priv->widthStep; - img->channels = priv->nChannels; - img->pixels = priv->imageData; #endif img->priv = (void *)priv; return img; } -struct image * image_new(int width, int height) +struct image *image_new(int width, int height) { - struct image * img; -#if defined(HAVE_IMLIB2_H) + struct image *img; +#if defined(HAVE_CV_H) + IplImage *priv = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 3); +#elif defined(HAVE_IMLIB2_H) Imlib_Image priv = imlib_create_image(width, height); -#elif defined(HAVE_CV_H) - IplImage * priv = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 3); #endif if(!priv) return NULL; img = malloc(sizeof(struct image)); -#if defined(HAVE_IMLIB2_H) +#if defined(HAVE_CV_H) + img->width = priv->width; + img->height = priv->height; + img->pitch = priv->widthStep; + img->channels = priv->nChannels; + img->pixels = priv->imageData; +#elif defined(HAVE_IMLIB2_H) imlib_context_set_image(priv); img->width = imlib_image_get_width(); img->height = imlib_image_get_height(); img->pitch = 4 * imlib_image_get_width(); img->channels = 4; img->pixels = (char *)imlib_image_get_data(); -#elif defined(HAVE_CV_H) - img->width = priv->width; - img->height = priv->height; - img->pitch = priv->widthStep; - img->channels = priv->nChannels; - img->pixels = priv->imageData; #endif img->priv = (void *)priv; return img; } +void image_free(struct image *img) +{ +#if defined(HAVE_CV_H) + IplImage *iplimg; + iplimg = (IplImage *)img->priv; + cvReleaseImage(&iplimg); +#elif defined(HAVE_IMLIB2_H) + imlib_context_set_image(img->priv); + imlib_free_image(); +#endif + + free(img); +} + int getgray(struct image *img, int x, int y, int *g) { if(x < 0 || y < 0 || x >= img->width || y >= img->height) @@ -132,19 +146,21 @@ int setpixel(struct image *img, int x, int y, int r, int g, int b) void image_display(struct image *img) { -#if defined(HAVE_IMLIB2_H) +#if defined(HAVE_CV_H) + char name[BUFSIZ]; + sprintf(name, "Image %p (%i x %i)", img, img->width, img->height); + cvNamedWindow(name, 0); + cvShowImage(name, img->priv); + cvResizeWindow(name, img->width * 2, img->height * 2 + 50); + while((unsigned char)cvWaitKey(0) != 0x1b) + ; +#elif defined(HAVE_IMLIB2_H) //char name[BUFSIZ]; //static int i = 0; //sprintf(name, "image%i-%ix%i.png", i++, img->width, img->height); //imlib_context_set_image(img->priv); //imlib_save_image(name); //fprintf(stderr, "saved to %s\n", name); -#elif defined(HAVE_CV_H) - char name[BUFSIZ]; - sprintf(name, "Image %p (%i x %i)", img, img->width, img->height); - cvNamedWindow(name, 0); - cvShowImage(name, img->priv); - cvResizeWindow(name, 320, 120); #endif } diff --git a/src/main.c b/src/main.c index 6c2449d..7a317a8 100644 --- a/src/main.c +++ b/src/main.c @@ -11,6 +11,7 @@ #include #include +#include #include #include "config.h" @@ -87,7 +88,29 @@ int main(int argc, char *argv[]) continue; } - result = decode_slashdot(img); + if(!strcmp(mode, "test")) + result = decode_test(img); + else if(!strcmp(mode, "phpbb")) + result = decode_phpbb(img); + else if(!strcmp(mode, "slashdot")) + result = decode_slashdot(img); + else + { + if(img->width == 320 && img->height == 50) + result = decode_phpbb(img); + else if(img->height == 69) + result = decode_slashdot(img); + else + { + fprintf(stderr, "%s: could not guess CAPTCHA type\n", argv[0]); + printf("\n"); + image_free(img); + continue; + } + } + + image_free(img); + if(!result) { fprintf(stderr, "%s: sorry, decoding failed\n", argv[0]); diff --git a/src/phpbb.c b/src/phpbb.c new file mode 100644 index 0000000..6ae69e4 --- /dev/null +++ b/src/phpbb.c @@ -0,0 +1,136 @@ +/* + * phpbb.c: decode phpBB 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 "config.h" +#include "common.h" + +/* Our macros */ +#define FONTNAME "share/font_phpbb.png" + +static struct image *find_glyphs(struct image *img); + +/* Global stuff */ +char *result; + +/* Main function */ +char *decode_phpbb(struct image *img) +{ + char all[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789"; + struct image *tmp1, *tmp2, *tmp3; + struct image *font = image_load(FONTNAME); + int x, y, i = 0; + int r, g, b; + int xmin, xmax, ymin, ymax, cur, offset = -1; + int distmin, distx, disty, distch; + + /* phpBB captchas have 6 characters */ + result = malloc(7 * sizeof(char)); + + if(!font) + { + fprintf(stderr, "cannot load font %s\n", FONTNAME); + exit(-1); + } + + tmp1 = filter_smooth(img); + tmp2 = filter_equalize(tmp1, 128); + tmp3 = image_new(img->width, img->height); + + for(x = 0; x < img->width; x++) + for(y = 0; y < img->height; y++) + { + getpixel(tmp2, x, y, &r, &g, &b); + if(r == 0 && offset == -1) + offset = x; + getpixel(img, x, y, &r, &g, &b); + setpixel(tmp3, x, y, 255, g, 255); + } + + strcpy(result, " "); + + for(cur = 0; cur < 6; cur++) + { + /* Try to find 1st letter */ + distmin = 999999999; + for(i = 0; i < 35; i++) + { + int localmin = 99999999, localx, localy; + xmin = i * 40; + ymin = 0; + xmax = i * 40 + 40; + ymax = 40; + for(y = 0; y < img->height - 40; y++) + { + x = offset - 3; + if(cur == 0) + x -= 10; + if(x < 0) + x = 0; + for(; x < offset + 3; x++) + { + int z, t, dist; + dist = 0; + for(t = 0; t < ymax - ymin; t++) + for(z = 0; z < xmax - xmin; z++) + { + int r2; + getgray(font, xmin + z, ymin + t, &r); + getgray(tmp2, x + z, y + t, &r2); + dist += (r - r2) * (r - r2); + } + if(dist < localmin) + { + localmin = dist; + localx = x; + localy = y; + } + } + } + if(localmin < distmin) + { + distmin = localmin; + distx = localx; + disty = localy; + distch = i; + } + } + + /* Print min glyph (debug) */ + xmin = distch * 40; + ymin = 0; + xmax = distch * 40 + 40; + ymax = 40; + for(y = 0; y < ymax - ymin; y++) + for(x = 0; x < xmax - xmin; x++) + { + int r2; + getpixel(font, xmin + x, ymin + y, &r2, &g, &b); + if(r2 > 128) continue; + getpixel(tmp3, distx + x, disty + y, &r, &g, &b); + setpixel(tmp3, distx + x, disty + y, r2, g, b); + } + + offset = distx + xmax - xmin; + result[cur] = all[distch]; + } + + image_free(tmp1); + image_free(tmp2); + image_free(tmp3); + image_free(font); + + return result; +} + diff --git a/src/slashdot.c b/src/slashdot.c index 60bfbb4..3ec6c4d 100644 --- a/src/slashdot.c +++ b/src/slashdot.c @@ -30,30 +30,48 @@ static struct image *find_glyphs(struct image *img); /* Global stuff */ struct { int xmin, ymin, xmax, ymax; } objlist[100]; -int objects = 0, first = -1, last = -1; +int objects, first, last; char *result; /* Main function */ char * decode_slashdot(struct image *img) { - struct image *tmp, *tmp2; + struct image *tmp1, *tmp2, *tmp3, *tmp4, *tmp5, *tmp6, *tmp7; + + /* Initialise local data */ + objects = 0; + first = -1; + last = -1; /* Slashdot captchas have 7 characters */ result = malloc(8 * sizeof(char)); /* Clean image a bit */ - tmp = filter_detect_lines(img); - tmp = filter_fill_holes(tmp); + tmp1 = filter_detect_lines(img); + tmp2 = filter_fill_holes(tmp1); /* Detect small objects to guess image orientation */ - tmp2 = filter_median(tmp); - tmp2 = filter_equalize(tmp2); - count_objects(tmp2); + tmp3 = filter_median(tmp2); + tmp4 = filter_equalize(tmp3, 200); + count_objects(tmp4); /* Invert rotation and find glyphs */ - tmp = rotate(tmp); - tmp = filter_median(tmp); - tmp = find_glyphs(tmp); + tmp5 = rotate(tmp2); + tmp6 = filter_median(tmp5); + tmp7 = find_glyphs(tmp6); + + /* Clean up our mess */ + image_free(tmp1); + image_free(tmp2); + image_free(tmp3); + image_free(tmp4); + image_free(tmp5); + image_free(tmp6); + image_free(tmp7); + + /* aaaaaaa means decoding failed */ + if(!strcmp(result, "aaaaaaa")) + result[0] = '\0'; return result; } diff --git a/src/test.c b/src/test.c new file mode 100644 index 0000000..f7f5c59 --- /dev/null +++ b/src/test.c @@ -0,0 +1,155 @@ +/* + * test.c: test captchas + * $Id$ + * + * Copyright: (c) 2004 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" + +/* Our macros */ +#define FONTNAME "share/font_phpbb.png" + +static struct image *find_glyphs(struct image *img); + +/* Global stuff */ +struct { int xmin, ymin, xmax, ymax; } objlist[100]; +int objects, first, last; +char *result; + +/* Main function */ +char * decode_test(struct image *img) +{ + struct image *tmp1, *tmp2, *tmp3, *tmp4, *tmp5, *tmp6, *tmp7; + + /* Initialise local data */ + objects = 0; + first = -1; + last = -1; + + /* phpBB captchas have 6 characters */ + result = malloc(7 * sizeof(char)); + + tmp1 = filter_smooth(img); + tmp2 = filter_median(tmp1); + tmp3 = filter_equalize(tmp2, 130); + tmp4 = filter_median(tmp3); + tmp5 = find_glyphs(tmp3); + + image_free(tmp1); + image_free(tmp2); + image_free(tmp3); + image_free(tmp4); + image_free(tmp5); + + return result; +} + +/* The following functions are local */ + +static struct image *find_glyphs(struct image *img) +{ + char all[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789"; + struct image *dst; + struct image *font = image_load(FONTNAME); + int x, y, i = 0; + int r, g, b; + int xmin, xmax, ymin, ymax, incell = 0, count = 0, cur = 0, offset = -1; + int distmin, distx, disty, distch; + + if(!font) + { + fprintf(stderr, "cannot load font %s\n", FONTNAME); + exit(-1); + } + + dst = image_new(img->width, img->height); + + for(x = 0; x < img->width; x++) + for(y = 0; y < img->height; y++) + { + getpixel(img, x, y, &r, &g, &b); + setpixel(dst, x, y, 255, g, 255); + if(r == 0 && offset == -1) + offset = x; + } + + strcpy(result, " "); + + while(cur < 6) + { + /* Try to find 1st letter */ + distmin = 999999999; + for(i = 0; i < 35; i++) + { + int localmin = 99999999, localx, localy; + xmin = i * 40; + ymin = 0; + xmax = i * 40 + 40; + ymax = 40; + for(y = 0; y < img->height - 40; y++) + { + x = offset - 5; + if(cur == 0) + x -= 15; + if(x < 0) + x = 0; + for(; x < offset + 10; x++) + { + int z, t, dist; + dist = 0; + for(t = 0; t < ymax - ymin; t++) + for(z = 0; z < xmax - xmin; z++) + { + int r2; + getgray(font, xmin + z, ymin + t, &r); + getgray(img, x + z, y + t, &r2); + dist += abs(r - r2); + } + if(dist < localmin) + { + localmin = dist; + localx = x; + localy = y; + } + } + } + if(localmin < distmin) + { + distmin = localmin; + distx = localx; + disty = localy; + distch = i; + } + } + + /* Print min glyph (debug) */ + xmin = distch * 40; + ymin = 0; + xmax = distch * 40 + 40; + ymax = 40; + for(y = 0; y < ymax - ymin; y++) + for(x = 0; x < xmax - xmin; x++) + { + getpixel(font, xmin + x, ymin + y, &r, &g, &b); + if(r > 128) continue; + setpixel(dst, distx + x, disty + y, r, g, b); + } + + offset = distx + xmax - xmin; + result[cur++] = all[distch]; + } + + return dst; +} +