Contenido principal

Solución Reto #2: Esteganálisis

Diciembre 31, 2008

El objetivo principal de este reto es crear en el participante conciencia de que estamos en un mundo donde aprender a manejar y analizar las herramientas que se nos dan es importante para poder descubrir nuevas formas de utilizar la información.
Este reto consta principalmente de tres partes que son: Identificación del texto escondido en la primera imagen (Imagen 3D o Estereograma), análisis de la imagen creada por el ejecutable y esteganografía clásica por bit menos significativo, obviando las partes que no se cuentan como reto, como la extracción de los archivos, buscar la clave del comprimido, etc.
En las siguientes páginas se describe la solución oficial del reto, también como una pista y una trampa que se dejó para hacer el reto un poco mas divertido, ya que principalmente estaba ideado para resolver sólo la parte del análisis de la imagen creada por el ejecutable.


¿Cómo proceder?
Bueno, primero descargamos el archivo comprimido msg.zip y lo copiamos a una carpeta que llamaremos "reto", en este punto podemos ver dos archivos: msg_1.txt y msg_2.txt.

Versión unix
Con abrir cualquiera de los dos archivos, podemos ver que se trata del RAW de un correo enviado a una cuenta en gmail, y podemos ver en las líneas siguientes un código parecido al siguiente:

------=_Part_10323_22914386.1228460795112
Content-Type: application/octet-stream; name=archivo
Content-Transfer-Encoding: base64
X-Attachment-Id: f_fochszt80
Content-Disposition: attachment; filename=archivo
...
CÓDIGO
...
------=_Part_10323_22914386.1228460795112--

Vemos también que el codificado del contenido es base64, así que de allí podemos extraer algún fichero. Lo que hacemos ahora es sacar el contenido "bueno" de los archivos que tenemos en estos momentos.

Quitamos el contenido basura el archivo msg_1.txt y nos queda algo parecido a lo siguiente.

UEsDBBQAAgAIAACwaDCD8KLOy/YAABBVAgAMAAAAY29tZGxnMzIuT0NY7Jp/XFRV3sfPwAAjjt5B
oUA05wZrqMSCoKEwNiKOYwIOggNqAiYgsiiEg9H1FzQMOV5H3V0zq10fCWPZfjy5rbVmvXSQjR/l
...
DgAAAA==

Grabamos el nuevo contenido como encoded1, y ejecutamos el comando base64 para decodificar el contenido

base64 -d -i encoded1 > decoded1

Aplicamos el mismo proceso al archivo msg_2.txt

UEsDBBQACwAIAJcChTlv9B/vfXsLAC2TEQAaAAAAbjYzMTM0MzM4OV84ODczODZfNDQ4NS5qcGeM
0EiZi9pnPbv5ZJ31vKLTy26eAibViCL0SnKxUc3gn5XFcxg8V54H8ZUFS+6mEpITdS1joL6M9zoj
...
ZXBpdG8uDQpNZSBsbGFtYXMgc2kgdGllbmVzIGVsIGNvbXBvbmVudGUh
base64 -d -i encoded2 > decoded2

Al observar con un editor hexadecimal el archivo decoded1 y el decoded2, nos damos cuenta que se trata de un archivo .zip, así que los extraemos

unzip decoded1
Archive:  decoded1
  inflating: comdlg32.OCX
  inflating: msvbvm60.dll
  inflating: EsteganoJPEG.exe
unzip decoded2
Archive:  decoded2
Hern�n!
Tienes que tener cuidado con este archivo, no puede caer en manos de nadie!
La clave para extraer la "imagen" es pepito.
Me llamas si tienes el componente!
[decoded2] n631343389_887386_4485.jpg password: pepito
  inflating: n631343389_887386_4485.jpg

Versión Windows
Podemos serguir el mismo procedimiento tratado en la versión unix, con unas pequeñas variaciones.

Guardar el contenido del base64 como un archivo .uue agregando las siguientes cabeceras, y con un compresor extraer normalmente los archivos.

begin 666 decoded1.zip
UEsDBBQAAgAIAACwaDCD8KLOy/YAABBVAgAMAAAAY29tZGxnMzIuT0NY7Jp/XFRV3sfPwAAjjt5B
oUA05wZrqMSCoKEwNiKOYwIOggNqAiYgsiiEg9H1FzQMOV5H3V0zq10fCWPZfjy5rbVmvXSQjR/l
...
DgAAAA==
end

(Obviamente los puntos suspensivos conllevan todo el contenido del base64 del archivo msg_1.txt)

Y el mismo proceso para el msg_2.txt

begin 666 decoded2.zip
UEsDBBQACwAIAJcChTlv9B/vfXsLAC2TEQAaAAAAbjYzMTM0MzM4OV84ODczODZfNDQ4NS5qcGeM
0EiZi9pnPbv5ZJ31vKLTy26eAibViCL0SnKxUc3gn5XFcxg8V54H8ZUFS+6mEpITdS1joL6M9zoj
...
ZXBpdG8uDQpNZSBsbGFtYXMgc2kgdGllbmVzIGVsIGNvbXBvbmVudGUh
end

Al guardarlos con la extensión "uue", winzip/winrar tienen la habilidad de decodificar el contenido y extraerlo al mismo tiempo. Si no se disponen de tales herramientas, se puede usar Cryptool para tal fin.

En este paso puede haber un problema al extraer los archivos contenidos en decoded2.zip, ya que está protegido por contraseña, pero si miramos el archivo con un editor hexadecimal, podemos ver un comentario:

Hernán!
Tienes que tener cuidado con este archivo, no puede caer en manos de nadie!
La clave para extraer la "imagen" es pepito.
Me llamas si tienes el componente!

Así que usamos la clave "pepito" para extraer los archivos

**********************************************************

Teniendo los archivos necesarios para ejecutar el reto, ahora podemos empezar el reto verdadero.

Primera parte: Identificación del estereograma
La primera parte se trata de un texto escondido de tal forma que al observar la imagen modificada, esta parece estar en tres dimensiones. A este tipo de imágenes se les llama estereogramas y son prácticamente ilusiones ópticas.

Para solucionar esta primera parte sólo es necesario utilizar nuestros sentidos y desenfocar un poco para poder ver el contenido oculto.
Si el contenido no es observable se puede utilizar herramientas para el decodificado de la imagen, una de ellas (Para windows), se llama estereogram decoder, y puede ser descargada de su página oficial: http://www.c14sw.de/132.html

Ahora bien, las primeras dos palabras escondidas que podemos encontrar son "fine" y "powdered".

Segunda parte: Análisis de la imagen creada por el ejecutable
En esta segunda parte se nos provee con un ejecutable y dos librerías para su correcto funcionamiento.
El ejecutable tiene por nombre “EsteganoJPEG.exe” al igual que el reto, y está protegido por ExeCryptor v2.4.1.0 con las siguientes opciones:

Virtualization level: 100%
Anti-Debug
* Debug messages
* Active watch
Patch protecion: memory
Anti-Trace
Protect entry point
Compression
* Compress resources
* Compres code & data
* Use maximun compression
* Strip relocation info
Dynamic Import
* Delay DLL loading
VMWare/VirtualPC/wine compatible

Así que es mejor no meternos por los lados de la ingeniería inversa porque sería inútil desgastar tiempo desensamblando, además me tome la molestia de poner dos pequeños códigos dentro del ejecutable que harán que al ocultar un archivo dentro de una imagen guarde en sus propiedades una clave errónea.

El ejecutable tiene dos opciones, la primera es la de ocultar un archivo dentro de una imagen JPEG y la segunda opción de extraer el archivo. En las dos opciones se debe ingresar una clave de más o igual a diez caracteres, así que si encontramos alguna clave cifrada descartamos la opción de hacer fuerza bruta.
El asunto principal en esta parte del reto es que en ningún momento se utiliza la clave para cifrar los datos. (Ya se podrán imaginar en que consiste esta parte del reto)
Así que lo que primero hacemos es ocultar cualquier archivo dentro de cualquier imagen. El programa se encarga de recolectar cinco datos que son añadidos al final de la imagen en formato Unicode. Estos cinco datos se listan a continuación:

:arrow: Cabecera: Representado con el atributo “CBERA”, es el que guarda la cabecera del archivo a ocultar. Es importante, ya que luego se comprueba si la
cabecera del archivo ocultado coincide con este atributo. En el caso contrario se nos muestra el mensaje de “Archivo corrupto”. No es necesario comprobar
todo el archivo, porque si en el proceso de descifrado coincide la cabecera, el resto de archivo debe coincidir perfectamente, al menos que sea modificado.

:arrow: Archivo oculto: Representado con el atributo “DACLT”, es el atributo que contiene el archivo oculto cifrado. El proceso de cifrado es un simple xor byte a byte: Archivo oculto ^ Imagen ^ String Oculta

:arrow: Nombre: Representado con el atributo “NOMBA”, es el que guarda el nombre del archivo oculto cifrado. El proceso de cifrado es al igual que el anterior atributo un simple xor: Nombre del archivo ^ String Oculta.

:arrow: Contraseña: Representado con el atributo “LACLV”, es el encargado de contener la contraseña cifrada en SHA-1

:arrow: Fecha de modificación de la imagen: Representado con el atributo “LAFCH”, guarda una string en md5 que contiene año, mes, día y hora en que fue generada la imagen. Si la fecha de modificación de la imagen no coincide con esta fecha entonces la imagen fue modificada, mostrando el mensaje de que la imagen fue modificada y el proceso de extracción no puede continuar.

Analizando estos cinco campos en una imagen con algún archivo tenemos esta parte ganada.
Como mencione anteriormente, en ninguna parte se usa la clave para cifrar el contenido del archivo a ocultar, entonces lo que podemos hacer es generar una nueva clave mayor o igual a diez caracteres usando SHA-1, y reemplazándola en la imagen que tenemos. Pero esto nos trae un pequeño problema y es el de la fecha de modificación, ya que a pesar de que completemos correctamente el anterior punto, nos va a salir un mensaje de que fue modificado el archivo. Así que podemos hacer dos cosas, programar una aplicación que cambie la fecha de modificación del archivo, o devolver el tiempo con la hora del sistema y en el momento exacto (Fecha de modificación del archivo) modificar el archivo para que parezca ser el mismo.
Ya con estos dos pasos completos, nos queda una cosa por hacer y es corregir la cabecera del archivo. De “ÿOÿà” a “ÿØÿà”, lo cual representa la cabecera de un archivo JPEG.

Tercera parte: Esteganografía clásica, bit menos significativo.
Llegamos a la última parte, luego de extraer el archivo oculto, que por supuesto es una imagen (La misma imagen), elaboramos una herramienta que compara pixel por pixel en busca de diferencias.
Podemos guiarnos en esta parte de la publicación "esteganografía por bit menos significativo", publicada en esta misma página.

<?php
// @titulo: Script solucionador reto #2
// @autor: http://www.sinfocol.org
//Los dos archivos PARECEN ser iguales, pero NO lo son
$original            = imagecreatefromjpeg('n631343389_887386_4484.jpg'); //Archivo original
$modificado         = imagecreatefromjpeg('nuevo.jpg');  //Archivo extraido
$dimensiones         = getimagesize('n631343389_887386_4484.jpg');
$output              = imagecreate($dimensiones[0],$dimensiones[1]); //Creamos una nueva imagen con el mismo tamaño de las iniciales.
imagecolorallocate($output,255,255,255);
$cnegro             = imagecolorexact($output,0,0,0);
for($i=0;$i<$dimensiones[0];$i++){
  for($j=0;$j<$dimensiones[1];$j++){
    //Recorremos cada uno de los pixeles de la imagen, como son iguales en tamaño, solo debemos usar dos ciclos
    $coriginal      = imagecolorat($original,$i,$j); //Obtenemos el color del pixel (i,j) de la primera imagen
    $cmodificado = imagecolorat($modificado,$i,$j); //Obtenemos el color del pixel (i,j) de la segunda imagen
    if($coriginal!=$cmodificado) imagesetpixel($output,$i,$j,$cnegro); //Comparamos los dos colores, y si son diferentes ponemos un punto negro en la imagen nueva. De no ser así el punto es blanco
  }
}
header('Content-Type: image/png');
imagepng($output); //Mostramos la imagen en blanco y negro con las diferencias entre las dos imágenes iniciales.
?>

Y el output con el anterior script es

Quedando entonces la respuesta a este reto “fine powdered iron oxide

Pista y trampa
La primera y única pista se encuentra en la imagen, esta pista sirve para poder descubrir cual es el método usado pada esconder la primera palabras. Se encuentra en el comentario de la imagen:

"U2kgbGxlZ2FzdGUgYSBlc3RhIHBhcnRlLCBtdXkgYmllbiwgdmFzIHBvciBlbCBjYW1pbm8gaW5jb3JyZWN0by4gTGEgcGlzdGEgZXM6ILLXq3q"

Y como todos pensaron (Eso creo), se trata de base64, así que decodificamos el contenido y nos queda:
“Si llegaste a esta parte, muy bien, vas por el camino incorrecto. La pista es: 2׫zˆ”
Y si codificamos con base64 la cadena “2׫zˆ”, nos queda “stereog”, así que el resto es buscar en google algo con “stereog” y la palabra oculto, que en inglés es “hidden”.
Así tras una pequeña búsqueda llegamos a las imágenes en 3D o estereogramas.
Y la primera y única trampa se trata de la cabecera en la imagen creada, la cabecera originalmente es ÿOÿà, y la debemos cambiar a la cabecera de la imagen jpg que es ÿØÿà, no hay mucha diferencia, y es precisamente para que el participante pueda encontrar el error en tal cabecera.

Es todo, mas adelante publico la solución a la segunda parte, por medio de análisis criptográfico.

Archivado en: Esteganografía, Retos informáticos |

8 comentarios

  1. kmykc Enero 2, 2009 @ 4:44 pm

    Dios, bastante bueno, pero aun me hace falta nivel para llegar a solucionar este tipo de retos brother.

    Salu2...

  2. ender Febrero 17, 2009 @ 5:08 pm

    TGEgcmVzcHVlc3RhIHF1ZSBidXNjYXMgcGFyYSBlc3RlIG5pdmVsLCBlczogQ3VhbnRvIHNhYmVz
    y cual seria la respuesta a este siendo la pista b64!?

  3. Sysroot Febrero 19, 2009 @ 6:10 pm

    La respuesta que buscas para este nivel, es: Cuanto sabes

  4. Blackubay Noviembre 19, 2009 @ 10:29 am

    para la parte de decodificacion del base64

    yo hice un script en php :)

    y con eso esta hecho esa parte del reto

  5. zarek Diciembre 30, 2010 @ 1:31 am

    Listo!! despues de mucho esfuerzo y pregunadera se logro hacer todo lo que ud hizo alli arriba!!! se le aprendio bastante!!!.
    solo me asalta una duda como se le ocurre a alguien programar eso en php si "lsb" lo saca un programa "StegSecret" de forma automatica!! lo coloque como por hacerlo de otra forma por ahorrar el "ctrl + c" pero no salio no hizo "lsb" en dicha imagen. esa es mi gran duda de este tutorial.
    Muchisimas gracias!!!

  6. zarek Diciembre 30, 2010 @ 1:41 am

    Huy ya vi!!! no es puro "lsb" sobre una imagen es un "lsb" de la diferencia de las dos imagenes, haciendo mostrar en negro la diferencia en algun pixcel que tengan modificadas las dos imagenes porque si bien son las mismas no deverian tener ningun pixcel distinto.
    Muchas gracias!!!
    se le aprende muchisimo!!!

  7. hecky Diciembre 30, 2010 @ 2:37 pm

    zarek asi es, la idea es comparar las dos imagenes y ver las diferencias. HaDeS me desmentira pero un programa que puede hacer esta comparacion a nivel de pixeles me parece es Imagemagick.

    Este seria el software equivalente para la "automatizacion" de este proceso.

    Pero contestando lo de por que programarlo en vez de usar el software.

    FACIL!!!

    Tanto a Daniel como ami nos gusta la Esteganografia MANUAL, todo hecho por nosotros(o lo que se pueda.)

    Y me atrevo a contestar en nombre de HaDeS por que de el aprendi eso (entre muchas otras cosas) que de nada sirve usar un software si no se entiende que se hace, si no se aprende...Asi que por eso Daniel programa (aparte de que le gusta la mala vida jeje)

    Saludos ;)

  8. Sysroot Diciembre 31, 2010 @ 7:14 pm

    Así es Zarek, no es un LSB cualquiera. La idea de programar es conocer la esencia de como se estan ocultando los datos, como dice Hecky, no es lo mismo usar un software sin tener los conocimientos a usarlo y conocer como funciona internamente el programa, es el caso típico de StegHide, todo el mundo lo usa pero muchos obvian su funcionamiento interno y creen que es la única forma de ocultar datos en una imagen o en audio. Conociendo el funcionamiento del programa se pueden conocer sus debilidades (Caso expuesto en la resolución de los niveles del WarCamp).

    TAmbién como lo afirma Hecky, con la suite de ImageMagick viene un ejecutable llamado Compare el cual realiza la misma tarea del código anteriormente mostrado.

    El programa stegsecret para descubrir LSB funciona perfectamente con imágenes de poco color, en imágenes vívidas y con muchos colores es imposible detectar LSB si no se conoce el algoritmo aplicado.
    compare imagen1.png imagen2.png comparacion.png

Deja un comentario