Para este nuevo reto de esteganografía, partíamos de la siguiente imagen la cual sabíamos que contenía el color del cable que conseguía desactivar la detonación de la bomba en caso de una emergencia. Color que era la solución al reto:
Al abrir la imagen, no observamos nada fuera de lo normal, así que procedemos a realizar un pequeño análisis de la imagen abriéndola con un editor hexadecimal y analizamos su cabecera para ver si efectivamente se trata de una imagen PNG.
Una vez comprobado que efectivamente se trata de una imagen PNG, podemos comprobar si se ha ocultado alguna información mediante la técnica de EOF (End Of File) por ejemplo, que es una de las más sencillas, ya que consiste en añadir la información a ocultar después de la marca de finalización del fichero. Esto se puede realizar con aquellos tipos de archivos cuya estructura utiliza una cadena o conjunto de bytes concretos para indicar el final del mismo, posición a partir de la que ya no existirán más datos referentes al archivo.
Después de esta pequeña introducción a la técnica EOF y volviendo al reto, podemos decir que las imágenes PNG poseen la cabecera descrita anteriormente, y la cadena que indica el final de la imagen es “IEND”, más concretamente el conjunto de bytes “00 00 00 00 49 45 4E 44 AE 42 60 82”. Así que si procedemos a analizar el conjunto hexadecimal, observamos que efectivamente el fichero acaba con “IEND” y no hay información extra después de la misma. Pero si buscamos esta cadena, podemos comprobar que se repite una vez más, y justo después de ésta, existe otra cabecera PNG (como se puede ver en la siguiente imagen), lo cual quiere decir que muy probablemente hayan dos imágenes PNG concatenadas. Siendo la segunda la información oculta de la primera.
Como nota hay que destacar que al abrirla con el visor de imágenes, no hemos notado nada raro porque los editores están preparados para leer hasta el punto donde se indica el final de la imagen y omitir toda la información que exista después.
Si separamos los dos archivos, obtenemos la siguiente imagen de otra bomba distinta, la cual también se corresponde a un archivo PNG como hemos visto anteriormente.
Llegados a este punto tenemos dos imágenes totalmente distintas, y a simple vista ninguna nos aporta ningún dato que nos ayude a descubrir cual es el color del cable que hay que cortar para desactivar la bomba…
Hace unos días, hablamos en el blog sobre la técnica LSB (ver I y II), que nos permitía ocultar información en imágenes PNG. ¿Coincidencia? Vamos a comprobarlo :)
Si usamos el segundo script facilitado en el anterior post, podremos ver si se ha utilizado esta técnica para ocultar algún archivo más en alguna de las imágenes, y obtendremos el resultado siguiente para cada una de las imágenes:
En la primera imagen podemos ver claramente que se esconde algo, ya que a partir de cierto instante no aparece ningún bit menos significativo a 1 (todos los píxeles son blancos), y además vemos que se ha ocultado el archivo recorriendo la imagen por columnas. En la segunda imagen no vemos nada que indique a simple vista que se ha utilizado LSB, pero si nos fijamos más detalladamente, a partir de cierto instante la imagen resultante parece que sea más “clara”, existen menos puntos negros. ¿Será debido a algo o es simplemente que la imagen es así realmente?
Como en la primera imagen parece que tenemos claro lo que hay que hacer vamos a ello.
Ejecutamos el script para obtener el archivo oculto dentro de una imagen en formato PNG especificando el recorrido por columnas: php obtener.php columnas bomba.png archivo_oculto
Con la anterior instrucción, nos aparecerá en nuestro directorio un nuevo fichero del cual desconocemos la extensión, así que haciendo un file del mismo vemos que se trata de un documento de texto de OpenOffice.
Dependiendo del editor que utilicemos al abrirlo, es posible que nos diga que el archivo esta corrupto y pregunte si lo queremos reparar. Si el programa lo repara automáticamente perfecto, pero en el caso de que no lo haga, deberemos hacerlo nosotros manualmente. Para esto, basta con abrir el archivo con un editor hexadecimal y eliminar todos los 0s que existan después de los bytes que indican el final del mismo (0x00 0x00 0x00). Esto es debido a que al extraer los bits menos significativos de la imagen y crear el archivo nuevo, también se han añadido los 0s que indicaban que se había acabado el fichero oculto.
Una vez abierto el documento, vemos que lo único que aparece es la frase “Las instrucciones las puedes encontrar aquí:” y cuatro hojas más sin “nada” escrito. Pero si seleccionamos todo el contenido del documento y cambiamos el color de la letra a negro (por ejemplo), vemos que aparece un texto que antes no veíamos, el cual se corresponde a un texto cifrado en base64.
El texto codificado es:
“QV92M2NFc19MNHNfYzBzQTVfcEVxVTNuNHNfU29uX0xBc19NNHNfMW1QMHJUYW4zc19QZVJvX24wX1MxM21wUmVf
bDBfczBOX1QwZDRzX0VsbEFz”
Y al decodificarlo obtenemos:
“A_v3cEs_L4s_c0sA5_pEqU3n4s_Son_LAs_M4s_1mP0rTan3s_PeRo_n0_S13mpRe_l0_s0N_T0d4s_EllAs”
Si logramos interpretar el texto como se espera, nos da una pista para poder obtener un archivo oculto en la siguiente imagen, ya que nos dice que las cosas pequeñas son importantes, refiriéndose a los bits menos significativos de la imagen, pero que no todas ellas, es decir, no todos los colores ;)
Sabiendo esto, podemos dar sentido a la parte más clara de la imagen obtenida de comprobar_lsb.php de la imagen oculta. Ya que esto es debido a que se han rellenado de 0s uno o dos colores de los tres disponibles (RGB), y por lo tanto el hecho de que los 3 bits menos significativos de cada píxel coincidan en 0 es más probable.
Dicho esto, lo que tenemos que hacer es modificar el script de obtener el archivo oculto mediante LSB para que no obtenga los bits de los tres colores, y comprobar si nos devuelve un fichero válido.
Una vez realizadas las pruebas pertinentes, descubriamos que la única combinación que devolvía un fichero válido era obteniendo únicamente los valores del color verde (G), la cual nos devolvía una bonita imagen JPG de una playa en una puesta de sol. El script utilizado podría ser algo como obtener_versionReto.php, proporcionado en este enlace.
Llegado este punto alguien podrían pensar que la solución del reto era el color verde por el hecho de que la información estuviese oculta ahí, pero como se dijo en la presentación del reto, cuando se descubriera la respuesta se sabría claramente. Así que si ahora tenemos una nueva imagen, querrá decir que deberemos descubrir algo más ¿no? En este caso la solución la encontramos utilizando las funcionalidades que nos aportan algunos programas de edición de imagen como por ejemplo GIMP (aunque también se pueden desarrollar herramientas propias) para la detección de bordes de las imágenes.
Si seleccionamos el filtro de detección de bordes mediante aristas y seleccionamos el algoritmo Prewitt (por ejemplo) con una cantidad de 10 …
Obtendremos la siguiente imagen, en la que podremos leer “RED”, nuestro color tan buscado :)
Espero que hayáis disfrutado una vez más con este tipo de retos y que hayáis practicado y aprendido mucho durante la solución del mismo. Mención especial para Kachakil, que unas horas después de la publicación ya había resuelto el reto y Hecky, que estuvieron cerca de resolver el reto.
Corregimos (de nuevo). Kachakil sí lo resolvió, mientras que Hecky estuvo cerca de la solución :)
Mañana actualizaremos el post para conceder los méritos oportunos :)
El comentario que dejé en el post donde se planteba el reto era porque lo normal era esperar que la solución una vez encontrada fuera muy evidente y posiblemente contenga “rojo”, “azul” o “amarillo” (y no verde, jeje), pero de repente te encuentras con solo 3 letras… Sí, el comentario era muy sutil, pero es porque no quería revelar ningún tipo de pista, para que no pierda gracia para el resto de participantes. ;-)
En cualquier caso, para mí el verdadero mérito es de Rafa (a quien mandé mi solución en privado), en especial porque no es fácil diseñar este tipo de pruebas sin caer en la tentación de tirar por el camino fácil y abusar de la idea feliz.
Saludos!
Algo me dice ese editor hexadecimal esta trabajando sobre el mismo Ubuntu sobre el que realizaste el demás trabajo. ¿Podrías decir cuál es, a modo de recomendación?
Como bien ha corregido Manolo, Kachakil consiguió resolver el reto correctamente pero a Hecky le falto un poco más para llegar a la solución final, ya que como me comentó por privado, se creyó que la solución era otra.
@Kachakil: Muchas gracias por las felicitaciones :) Y lo del color verde ya te expliqué por lo que era jajaj De todas formas, aunque la solución solo fuesen 3 letras, creo que se veía claramente que era la solución del reto no? ^^
@VTacius: El editor que utilizo en Ubuntu es el Bless Hex Editor, que para mi es el mejorcito que he probado :)
Por lo demás, espero que os guste este tipo de retos, ya que considero que es una muy buena forma de aprender/practicar cosas nuevas.
Saludos
fikih888
Gran post Rafa. Menuda currada \m/
Muy bueno el post, solo una pregunta, que has usado para encriptar el mensaje?
@Rafa Me has liado con el reto, ya no tuve tiempo de verlo con mas calma, pero me parecio muy bueno. Concuerdo mucho con el Dr Kachakil, no es fácil hacer este tipo de retos y te mereces mas que una Felicitación!!
@Anónimo el cifrado es Base64
#BTW Rafa yo use Bless mucho tiempo y naahh…Pruebate Okteta (GUI) es de LO MEJOR!!! o en cli “bvi” que es un “vi” para binarios….
O uno nuevo que apenas salio y probe muy vagamente (Aun tiene bugs) http://www.diskeditor.net/ Pero que PROMETE MUCHISIMO!!!!
Saludos!!!
Gracias de nuevo :)
@Anónimo: Si te refieres al texto “RED”, pues yo lo hice con GIMP y con muuuuucha paciencia xD La verdad que desconozco si hay alguna herramienta que te permita realizar eso de una forma más sencilla.
@Hecky: Gracias por las recomendaciones, esos no los había probado, así que les echaré un vistacillo a ver que tal, aunque a mi Bless me gusta bastante :P
Saludos
fikih888