Преглед на файлове

* 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
master
sam преди 20 години
родител
ревизия
ba195bbc65
променени са 10 файла, в които са добавени 456 реда и са изтрити 70 реда
  1. +13
    -13
      configure.ac
  2. Двоични данни
      share/font_phpbb.png
  3. +5
    -5
      src/Makefile.am
  4. +9
    -4
      src/common.h
  5. +36
    -3
      src/filters.c
  6. +50
    -34
      src/image.c
  7. +24
    -1
      src/main.c
  8. +136
    -0
      src/phpbb.c
  9. +28
    -10
      src/slashdot.c
  10. +155
    -0
      src/test.c

+ 13
- 13
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


Двоични данни
share/font_phpbb.png Целия файл

Преди След
Ширина: 1400  |  Височина: 40  |  Големина: 6.2 KiB

+ 5
- 5
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


+ 9
- 4
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);


+ 36
- 3
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;
}


+ 50
- 34
src/image.c Целия файл

@@ -15,79 +15,93 @@
#include "config.h"
#include "common.h"

#if defined(HAVE_IMLIB2_H)
# include <Imlib2.h>
#elif defined(HAVE_CV_H)
#if defined(HAVE_CV_H)
# include <cv.h>
# include <highgui.h>
#elif defined(HAVE_IMLIB2_H)
# include <Imlib2.h>
#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
}


+ 24
- 1
src/main.c Целия файл

@@ -11,6 +11,7 @@

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>

#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]);


+ 136
- 0
src/phpbb.c Целия файл

@@ -0,0 +1,136 @@
/*
* phpbb.c: decode phpBB captchas
* $Id$
*
* Copyright: (c) 2005 Sam Hocevar <sam@zoy.org>
* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>

#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;
}


+ 28
- 10
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;
}


+ 155
- 0
src/test.c Целия файл

@@ -0,0 +1,155 @@
/*
* test.c: test captchas
* $Id$
*
* Copyright: (c) 2004 Sam Hocevar <sam@zoy.org>
* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#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;
}


Зареждане…
Отказ
Запис