viernes, 31 de mayo de 2013

Saltandose captchas con Shell Scripting

Análisis
Lo primero y PRIMORDIAL es analizar lo que se tiene al enfrentarse a un captcha… hay de muchos tipos, FORMAS, sabores y COLORES. Principalmente los captchas con “formas” son los mas difíciles de abordar y donde se requiere la IA. Al enfrentarnos a captchas tenemos que tener en cuenta los siguientes factores que dependiendo de cada uno de ellos sera como se aborde el reto:

  • Tipografia
  • Colores
  • Ruido
  • Forma
  • Angulos y posiciones
En este caso el captcha que abordaremos es demasiado fácil y con una tipografía muy clara. Lo mas parecido a “Letra molde”, las letras no están movidas (ángulos), no hay ruido…El único factor a vencer son los colores…El captcha tiene un fondo negro con letras con un ligero degradado…Lo cual no sera difícil vencer.

El captcha en cuestion es el siguiente:



El reto es limpiar la imagen…en este punto ustedes se preguntaran…¿Por que carambolas limpiar la imagen? Pues esto es por que muchos programas de OCR son mas precisos al tener una imagen limpia…

El captcha contiene una “vulnerabilidad” en la elección de colores la cual lo hace sumamente fácil de limpiar…¿Pueden verla?…Exacto…usan un fondo único y las letras no contienen este color…Osea: EL fondo es de color negro y las letras no contienen el color negro…

¿Y? – Fácil…¿Qué pasaria si…? Realizamos un programa que CONVIERTA TODO EL COLOR NEGRO EN BLANCO Y TODO LO QUE NO SEA NEGRO EN NEGRO… De este modo obtendríamos una imagen con fondo blanco y letras negras (O en teoría eso se quiere)

Shell Script para limpiar la imagen
Normalmente para esta tarea haría un script en PHP, pero descubrí/invente una forma para hacerlo desde bash…Y se las quiero compartir. Es por ello que lo haré desde bash…Por que muchos creen que para hacer esto es imposible en bash, ya que no hay una librería que lo haga…Y es cierto, pero nos apoyaremos de Imagemagick y todo el poder de bash.

El simple script que realice para esta tarea es el siguiente:



Brevemente explicare que hago:

Obtengo el tamaño de la imagen y lo guardo en variables:


1
2
3
pixelaje=$(convert -identify $image /dev/null | awk '{print $3}')
let px_x="$(echo $pixelaje | cut -d"x" -f1 | tr -d "\n")"
let px_y="$(echo $pixelaje | cut -d"x" -f2 | tr -d "\n")"



Creo un archivo de texto con la configuración que Imagemagick requiere para convertir un archivo de texto con pixeles a una imagen…La primera linea le dice de cuanto por cuanto sera la imagen y el valor máximo del color que se usara.


1
echo "# ImageMagick pixel enumeration: $px_x,$px_y,255,srgb" >
$txt_out

Empiezo a recorrer la imagen.


1
2
for ((y=0;y<$px_y;y++));do
for ((x=0;x<$px_x;x++));do



Obtengo el valor RGB del pixel.



1
rgb=$(convert "$image"[1x1+$x+$y] txt: | grep "(.*)" -wo |
cut -d ")" -f1 | tr -d "(" | tr -d "\n" | tr -d " "| tr "," " ")


Quizás esta sea la linea mas importante del programa, y el truco que se hace para obtener los pixeles de una imagen en bash. Así que la explicare un poco mas.

convert $image[1x1+$x+$y] txt:   Esta linea lo que hace es decirle que obtenga de la imagen, el pixel que esta en la posición ($x,$y) y que me muestre 1×1 solo un pixel y al final le decimos que nos muestre el valor como texto.
Lo demás es solo para limpiar y dejar solo los valores RGB para que al final nos quede algo asi:
Y ya eso lo pasamos a variables independientes y claro las declaramos de tipo numérico.
1
2
3
let r=$(echo $rgb | awk '{print $1}')
let g=$(echo $rgb | awk '{print $2}')
let b=$(echo $rgb | awk '{print $3}')
Hacemos una comprobación diciendo que si el valor de R o G o B es mas grande que “100″ (Osea que no es tan obscuro para llegar al negro Lo pintemos de negro en la coordenada dada…De lo contrario se pintara de blanco.
1
2
3
4
5
if [[ $r -gt 100 || $g -gt 100 || $b -gt 100 ]];then
echo "$x,$y$black" >> $txt_out
else
echo "$x,$y$white" >> $txt_out
fi
Donde por cierto los colores $black y $white valen segun imagemagick esto;
1
2
black="(  0,  0,  0)  #000000  black"
white="(255,255,255)  #FFFFFF  white
Al final se convierte el archivo .txt creado a una imagen .pnm (Se usa este formato ya que el programa de OCR requiere este formato).
1
convert $txt_out captcha_clean.pnm
Y por ultimo se Usa el programa gocr para obtener las letras de la imagen.
1
cracked=$(echo $(gocr captcha_clean.pnm))

Y voila!!!
Captcha Cracked!!! No que los bots no podían leer la imagen?? ¬¬
El codigo lo pueden ver en mi Pastebin AQUÍ!!! Este CÓDIGO SOLO ES DE EJEMPLO!!! Esto igualmente como dije, se puede realizar de un modo mas rápido con PHP…Dejo un código de ejemplo…
Y bien para terminar modifique un poco el script de arriba, para hacerlo generico…llegando con:
Al cual se le pasa como parametro una imagen y se le definen los colores que se quieren discriminar…con esto el la limpiara y la intentara decodificar…Ej:
Este captcha se quiso “crackear” sin limpiarlo y este es el resultado NEGATIVO:
Y con captcha-cracker-neobits.sh

BASH + IMAGEMAGICK + gocr == PWNED!!!
Notas Finales:
  • Y bueno con esto demuestro que con bash podemos seguir haciendo cosas hermosas…Obviamente, en “producción” esta no es ni por cercana la mejor opción…Ya que es lento…
  • PHP es un excelente lenguaje para manejor de imagenes…pero son mas rapidos los lenguajes compilados.
  • Tesseract es otro programa PODEROSISIMO para OCR
  • Este ejemplo es completamente demostrativo, ya que con lo tardado de la limpieza, no sirve para hacer un bot malicioso (Ese nunca fue mi proposito)
Espero haya gustado este nuevo post Y sin mas…
Saludos!

FUENTE:
http://news-technology-learning.blogspot.com/2013/05/saltandose-captchas-con-shell-scripting.html?showComment=1369830772831#c8713352826960060827

No hay comentarios:

Publicar un comentario