You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

238 lines
5.2 KiB

  1. /*
  2. * ticketmaster.c: decode ticketmaster captchas
  3. * $Id$
  4. *
  5. * Copyright: (c) 2006 Sam Hocevar <sam@zoy.org>
  6. * This program is free software. It comes without any warranty, to
  7. * the extent permitted by applicable law. You can redistribute it
  8. * and/or modify it under the terms of the Do What The Fuck You Want
  9. * To Public License, Version 2, as published by Sam Hocevar. See
  10. * http://sam.zoy.org/wtfpl/COPYING for more details.
  11. */
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <limits.h>
  16. #include "config.h"
  17. #include "common.h"
  18. #define WIDTH 290
  19. #define HEIGHT 80
  20. int grid_y[HEIGHT], grid_x[WIDTH];
  21. int dx_top[WIDTH], dy_top[WIDTH];
  22. int dx_bottom[WIDTH], dy_bottom[WIDTH];
  23. int perturbation_color(struct image *img, int x, int y);
  24. int real_color(struct image *img, int x, int y);
  25. int detect_grid(struct image *img);
  26. int detect_lines(struct image *img, int top);
  27. static inline int fastgetgray(struct image *img, int x, int y)
  28. {
  29. int r, g, b;
  30. getpixel(img, x, y, &r, &g, &b);
  31. return (r + g + b + 1) / 3;
  32. }
  33. /* Main function */
  34. char *decode_ticketmaster(struct image *img)
  35. {
  36. struct image *tmp;
  37. int x, y;
  38. if(detect_grid(img))
  39. pwnprint("image has vertical grid\n");
  40. detect_lines(img, 1);
  41. detect_lines(img, 0);
  42. tmp = image_dup(img);
  43. /* Remove perturbations */
  44. for(y = 1; y < HEIGHT - 1; y++)
  45. {
  46. for(x = 1; x < WIDTH - 1; x++)
  47. {
  48. int i, j, ok = 1;
  49. if(perturbation_color(img, x, y) != 0)
  50. continue;
  51. for(j = -1; j <= 1; j++)
  52. {
  53. for(i = -1; i <= 1; i++)
  54. {
  55. if(i == 0 && j == 0)
  56. continue;
  57. if(real_color(img, x + i, y + j)
  58. != perturbation_color(img, x + i, y + j))
  59. goto lol;
  60. }
  61. }
  62. if(!ok)
  63. continue;
  64. setpixel(tmp, x, y, 255, 255, 255);
  65. lol: continue;
  66. }
  67. }
  68. /* Lol, display lines */
  69. for(x = 1; x < WIDTH - 1; x++)
  70. {
  71. if(dy_top[x])
  72. for(y = 0; y < HEIGHT; y++)
  73. {
  74. int newx = (x * 1024 + dx_top[x] + (y * dy_top[x])) / 1024;
  75. setpixel(tmp, newx, y, 0, 255, 0);
  76. }
  77. if(dy_bottom[x])
  78. for(y = 0; y < HEIGHT; y++)
  79. {
  80. int newx = (x * 1024 + dx_bottom[x] + (y * dy_bottom[x])) / 1024;
  81. setpixel(tmp, newx, (HEIGHT - y - 1), 0, 255, 0);
  82. }
  83. }
  84. image_save(tmp, "ticketmaster-output.bmp");
  85. image_free(tmp);
  86. return strdup("lol");
  87. }
  88. int real_color(struct image *img, int x, int y)
  89. {
  90. return fastgetgray(img, x, y) < 40 ? 0 : 255;
  91. }
  92. int perturbation_color(struct image *img, int x, int y)
  93. {
  94. if(grid_x[x]) return 0;
  95. if(grid_y[y]) return 0;
  96. return 255;
  97. }
  98. int detect_lines(struct image *img, int top)
  99. {
  100. int x, y, i, j;
  101. int dx, dy;
  102. int *mydx, *mydy;
  103. if(top)
  104. {
  105. mydx = dx_top;
  106. mydy = dy_top;
  107. }
  108. else
  109. {
  110. mydx = dx_bottom;
  111. mydy = dy_bottom;
  112. }
  113. /* Detect top-bottom line candidates */
  114. for(x = 0; x < WIDTH; x++)
  115. {
  116. int candidate = 0, worstmissed;
  117. y = top ? 0 : HEIGHT - 3;
  118. for(j = 0; j < 3; j++)
  119. {
  120. for(i = -1; i <= 1; i++)
  121. {
  122. if(fastgetgray(img, x + i, y + j) < 40)
  123. {
  124. candidate++;
  125. break;
  126. }
  127. }
  128. }
  129. if(candidate < 3)
  130. continue;
  131. mydx[x] = mydy[x] = 0;
  132. worstmissed = 30;
  133. /* Refine slope, in 1/1024th of a pixel steps */
  134. for(dx = -1024; dx < 1024; dx += 128)
  135. {
  136. for(dy = 700; dy < 1300; dy += 16)
  137. {
  138. int missed = 0;
  139. for(y = 0; y < HEIGHT; y++)
  140. {
  141. int newx = (x * 1024 + dx + (y * dy)) / 1024;
  142. int gray = fastgetgray(img, newx, top ? y : (HEIGHT - y - 1));
  143. if(gray > 40)
  144. {
  145. missed++;
  146. if(missed >= worstmissed)
  147. break;
  148. }
  149. }
  150. if(missed < worstmissed)
  151. {
  152. worstmissed = missed;
  153. mydx[x] = dx;
  154. mydy[x] = dy;
  155. }
  156. }
  157. }
  158. if(worstmissed == 30)
  159. continue;
  160. pwnprint("found a line at %i (+ %i), slope %i/1024\n", x, mydx[x], mydy[x]);
  161. }
  162. return 1;
  163. }
  164. int detect_grid(struct image *img)
  165. {
  166. int x, y;
  167. int lines = 0, columns = 0;
  168. memset(grid_y, 0, sizeof(grid_y));
  169. memset(grid_x, 0, sizeof(grid_x));
  170. for(y = 0; y < HEIGHT; y++)
  171. {
  172. for(x = 0; x < WIDTH; x++)
  173. {
  174. if(fastgetgray(img, x, y) < 40)
  175. {
  176. grid_x[x]++;
  177. grid_y[y]++;
  178. }
  179. }
  180. }
  181. for(y = 0; y < HEIGHT; y++)
  182. if((grid_y[y] = (grid_y[y] > WIDTH * 90 / 100))) lines++;
  183. for(x = 0; x < WIDTH; x++)
  184. if((grid_x[x] = (grid_x[x] > HEIGHT * 90 / 100))) columns++;
  185. return lines * columns > 3 * 20;
  186. }