Wodax 1.2, empezando...

 

 

Por joapuipe

A principios de enero os presenté un pequeño y sencillo programa que había hecho, que permitía ocultar ficheros de texto plano en imágenes PNG utilizando la técnica "esteganográfica" de Inserción en el Bit Menos Significativo" (aunque realmente usaba el par de bits menos significativos).

Pues bien, hace unos días me puse a perfilar lo que serían las características de la nueva versión. Quizás estoy siendo un poco ambicioso, pero oye, que no sea por optimismo y "que me quiten lo aprendido" si el proyecto no se termina (que espero que sí). Hoy mismo he terminado el último examen del curso y me he dicho: "Vamos a publicar una nota en Kriptópolis para que la gente haga algunas recomendaciones, ahora que puedo trabajar más en serio..."

Y a eso he venido. Lo primero es presentar las características con las que contará la próxima versión. A saber, por el momento (y estoy abierto a sugerencias).

  • Inclusión de ficheros de distintos tipos, no sólo de texto (ésto es trivial).
  • Soporte de múltiples formatos de fichero tapadera (cover files): No sólo imágenes PNG, porqué no también otros formatos de imagen como JPEG y incluso vídeo como Theora o audio como Orbis. La idea es que haya una capa de abstracción entre lo que es el embebido "lógico" de un fichero y el embebido "físico". Cada algoritmo de ocultación implementaría el embebido "lógico" y serían los módulos que den soporte a los distintos formatos los que se encargaran del embebido "físico". De esta forma, no estaría restringido ningún algoritmo a ningún formato en concreto, ni habría ninguna limitación en cuanto a formatos. Simplemente, cuando se tenga el conocimiento suficiente sobre un formato, se programa el módulo encargado de manipular ese tipo de ficheros y listos.
  • Inclusión de uno o múltiples ficheros y directorios en una o varias imágenes. Esto es un concepto bastante novedoso creo yo, ya que no me he encontrado con ningún programa "esteganográfico" que lo implemente. Simplemente permiten embeber un fichero en una imagen. Me surgió la idea de empaquetar múltiples ficheros o directorios en un único fichero y embeber éste. Básicamente lo que uso es una formato de empaquetado basado en el formato Tar. Pero en principio no tendría porqué ser único el formato de empaquetado. Y después veréis porqué. A partir de la lista de ficheros y directorios indicados a ocultar, se crearía un paquete (yo le llamo Package).
  • Compresión de ficheros paquetes. También sería útil que se permitiese comprimir éste paquete para ahorrar espacio. Pues eso, soporte para diversos métodos de compresión (evidentemente, libres... No tengo dinero, ni ganas, para pagar patentes). Había pensado en implementar una versión de DEFLATE (el algoritmo usado por Gzip) o más rápido todavía utilizar la librería Zlib. Aunque igual que con el método de empaquetado, no tendría por qué ser único. El usuario podría elegir entre varios algoritmos.
  • Cifrado del paquete. ¿Qué sucede si se descubre una vulnerabilidad en el algoritmo de ocultación? Pues bien, tenemos nuestros datos cifrados y si descubren que nos comunicamos con alguien, siempre podremos decir que les escribíamos poemas de amor... Oye, si cuela, cuela.
  • Ocultación en múltiples ficheros tapadera. Un problema bastante común en la esteganografía es que necesitamos imágenes muy grandes para ocultar relativamente poca información. Esto puede resultar un problema si queremos por ejemplo ocultar un paquete de, pongamos, 2GB. Una imagen de unos 5 o 6 GB sería sospechosa... Pero, ¿y si dividimos el paquete en múltiples partes y ocultamos cada parte en un conjunto de imágenes? Entonces podríamos enviar alegremente un correo a nuestros amigos con la fotos de las últimas vacaciones, que en realidad esconden los planos de las Centrales Nucleares que nos ha pedido Ahmadineyad

¿Qué estructura debería tener un fichero "esteganográfico" (stego file) para articular todas estas características? Aquí va una propuesta:

+-----------------------------------------+
|      WODAX VERSION MAGIC (2 bytes)      | Identifica la versión del programa.
+-----------------------------------------+
|     EMBEDDING MAGIC NUMBER (2 bytes)    | Identifica el algoritmo de ocultación.
+-----------------------------------------+
|       EMBEDDING HEADER (variable)       | Información necesaria sobre la ocultación.
+-----------------------------------------+
|     CHECKSUM MAGIC NUMBER (2 bytes)     | Identifica el resumen hash utilizado.
+-----------------------------------------+
|           CHECKSUM (variable)           | Valor del resumen de los datos ocultos en el fichero.
+-----------------------------------------+
|      INDEX FILENAME SIZE (2 bytes)      | Longitud del nombre del fichero índice.
+-----------------------------------------+
|        INDEX FILENAME (variable)        | Nombre del fichero índice.
+-----------------------------------------+
|      CIPHER MAGIC NUMBER (2 bytes)      | Identifica el algoritmo de cifrado.
+-----------------------------------------+
|         CIPHER HEADER (variable)        | Información necesaria para el cifrado.
+-----------------------------------------+
|   COMPRESSION MAGIC NUMBER (2 bytes)    | Identifica el algoritmo de compresión.
+-----------------------------------------+
|      COMPRESSION HEADER (variable)      | Información necesaria para la compresión.
+-----------------------------------------+
|      PACKING MAGIC NUMBER (2 bytes)     | Identifica el algoritmo de empaquetado.
+-----------------------------------------+
|        PACKING HEADER (variable)        | Información necesaria para el empaquetado.
+-----------------------------------------+
|    EMBEDDED FILENAME SIZE (2 bytes)     | Longitud del nombre del fichero oculto.
+-----------------------------------------+
|      EMBEDDED FILENAME (variable)       | Nombre del fichero oculto.
+-----------------------------------------+
|      EMBEDDED DATA SIZE (8 bytes)       | Tamaño de los datos embebidos en este fichero.
+-----------------------------------------+
|        EMBEDDED DATA (variable)         | Datos embebidos.
+-----------------------------------------+

Algunas aclaraciones:

  • Los "números mágicos" son de 16 bits para garantizar suficientes valores con un cierto grado de entropía.
  • Los bloques de tamaño variable dependen del valor que hay en el bloque anterior. Por ejemplo, la cabecera específica para el cifrado depende del algoritmo de cifrado. Pudiendo ésta ser nula, si el algoritmo no necesita ninguna información adicional. Aquí se incluiría por ejemplo el modo de cifrado (CFB, EFB, CBC...).
  • El contenido del fichero índice es el del nombre de todas las imágenes que contienen datos ocultos y en orden para poder unir los datos. En el fichero índice, este campo es nulo (longitud del nombre = 0).
  • Todos los bloques referentes a la identificación de algoritmos usados sólo se incluye en el fichero índice.
  • Los campos EMBEDDED FILENAME SIZE y EMBEDDED FILENAME sólo son útiles en el caso de que no se haya creado un paquete (cuando sólo se oculta un fichero simple).
  • Como podéis ver, se pueden esconder un máximo de 2^64 bytes en un fichero tapadera... Suficiente, ¿no?.

Bueno, y después de toda esta lluvia de detalles. Espero impaciente vuestros consejos, preguntas y comentarios.

¡Muchísimas gracias!

PD: Se me olvidaba, el código de todo lo que voy haciendo lo podéis encontrar en: http://svn.assembla.com/svn/wodax/trunk/src/

Comentarios

Selecciona arriba tu forma preferida de visualizar los comentarios y pulsa el botón para guardar tu elección para próximas visitas (sólo si eres usuario registrado).
jorgegv's picture

Por qué reinventar lo que ya esta desarrollado y probado?


Mi objecion fundamental: para que quieres reimplementar cosas que ya estan hechas y en formatos propios? Usa lo que ya existe, y juntalo mediante media docenita de scripts. Tu funcionalidad basica es ocultar 1 fichero de datos en 1 fichero "portador" (por cierto, tu idea de los backends para ocultar info en distintos formatos "portadores" me parece muy buena). Sobre el resto de funcionalidades:

  • Para que quieres implementar una funcion de introducir varios ficheros en uno solo? Para eso ya esta TAR o ZIP, o cualquiera de los miles de archivadores que hay.
  • Para que quieres implementar funcionalidad de cifrado? ZIP ya lo hace, y si te pones quisquilloso y exigente, GNUPG tambien.
  • Para que quieres dividir 1 fichero en varios trozos y luego juntarlos? split y cat ya lo hacen.
  • Para que quieres implementar compresion si ya lo hacen GZIP, BZIP2, 7ZIP, etc.?

En resumen: que todo lo que quieres hacer yo lo haria mejor mediante scripts que usen herramientas ya existentes, en vez de reimplementar todas esas funcionalidades en tu herramienta particular. Te ahorraras bugs y pruebas, las herramientas que he mencionado estan HIPER probadas.

Franfj's picture

Creo que no has entendido


Creo que no has entendido la utilidad del programa que plantea joapuipe, la principal ventaja de lo que él plantea es poder utilizar un fichero de imagen para contener datos cifrados, la gracia reside en que el fichero de imagen aparentemente sigue siendo eso mismo por lo tanto nadie sospecharía que en él hubiese información extra cifrada.

joapuipe's picture

Explicándome


Hola jorgegv.

Es cierto que se podría primero empaquetar con tar un conjunto de ficheros, comprimir con gzip, cifrar con gnupg, dividirlo en fragmentos y ocultar cada fragmento usando mi programa en imágenes separadas. Correcto, pero ¿no sería más cómodo cara al usuario que todo esto lo hiciese el programa?

No he dicho que evidentemente, no iba a ponerme a escribir mi propia implementación del DEFLATE ni de los algoritmos de cifrado. Voy a usar la librería gzip para el comprimido y la libcrypt para el cifrado. ¿Por qué implementé mi propio formato de empaquetado? Por que veía que había muchas cosas del formato Tar que no necesitaba.

En resumen, no quiero implementar todos los algoritmos que he detallado, para eso están las librerías ya existentes, que como bien indicas son mucho más eficientes y libres de errores. Los únicos algoritmos que tengo intención de implementar por cuenta propia son los puramente esteganográficos.

¿Por qué no hacerlo usando scripts? Por una parte está la eficiencia y por la otra, que tengo ganas de aprender y mucho tiempo libre, llámame friki. Quiero decir, es bueno, muy bueno, reinventar la rueda para saber como funciona ésta realmente. Es decir, no comprendes realmente una cosa hasta que no eres capaz de hacerla y a eso voy. Y si encima aporto algunas utilidades que a alguien le puede resultar mínimamente útil o interesante, mejor que mejor.

Muchas gracias por tu comentario, soy consciente de ello.

jorgegv's picture

Por qué reinventar lo que ya esta desarrollado y probado?


Respondiendote:

¿no sería más cómodo cara al usuario que todo esto lo hiciese el programa?

Por supuesto. Y el que yo te comente que lo hagas todo a base de media docena de scripts no significa que el usuario final tenga que usarlos. El usuario final probablemente tenga 1 solo script que se encargue de llamar al resto en el orden adecuado, y segun la operacion que se le pida, de comprobar que todo esta en su sitio, etc. Es lo que se llama, un script "driver" de otros.

Respecto al tema de la eficiencia: hubo algun famosete de nuestro gremio (me parece que fue Dijkstra, pero a lo mejor me columpio) que digo que la optimizacion prematura es la madre de todos los desastres. Mejor tener primero algo que funciona y funciona bien, y despues preocupate de hacerlo eficiente y optimizarlo. Si tienes una cosa rapida, pero que funciona bien solo a veces, no vale para mucho. Y en cuanto a este caso concreto: ten en cuenta tus casos de utilizacion: si se va a usar en plan personal, esto se utilizará de forma puntual, y ahi importa poco si se tarda en ejecutar 2 o 5 segundos. Si esto lo vas a implantar en un servidor que va a procesar 200 mensajes por minuto, la cosa cambia.

Y en cuanto al tema fundamental de no usar scripts para hacerlo tu y así aprender: ahi si que no tengo nada que decir: como profe que soy, te digo adelante y te garantizo que sí, aprenderás un huevo de esa forma. Animo.

joapuipe's picture

En parte tienes razón


[...] la optimizacion prematura es la madre de todos los desastres [...]

En parte tienes razón, pero no me negarás que "Todo lo que empieza mal, sólo puede ir a peor". Así, que mejor empezar las cosas bien hechas. De todas formas, te repito que no voy a ponerme a implementar los algoritmos por mi cuenta, sino que simplemente voy a utilizar librerías (zlib, libgcrypt...). No utilicé una librería para manejar los archivos tar porqué la libtar no soporta trabajar sobre la memoria (sobre un buffer), tienes que crear un fichero físico .tar y eso no me interesaba.

Las razones de no usar scripts las contesté un poco más abajo:
http://www.kriptopolis.org/wodax-esteganografia-2#comment-53868

Saludos!

LlamameX's picture

Imagino que antes que nada por aprender y divertirse


pero también creo que puede ser útil adaptar estas funcionalidades a un entorno específico de esteganografia. No se muy bien como lo hace pero utilizar formatos muy fijos y conocidos puede crear patrones buscables dentro de las imágenes que los alojan y difícilmente se podrán adaptarse a éstas o no hacerlo de manera óptima.

Buena iniciativa. Espero a ver que sale de ella. Me bajo el código y me lo miro a ver si pillo algo XD.

PD. ¿Has pensado en ocultación al vuelo sobre flujos de datos?, es decir, sin basarte en ficheros sinó añadiendo el contenido esteganográfico sobre una emisión. La idea es que no quede nada que analizar fuera del momento de la emisión (a menos que se almacene ésta). De esta manera un servidor de vídeos a partir de un determinado momento podría emitirlos (o re-emitirlos desde youtube, por ejemplo) añadiendo un mensaje oculto y un cliente específico recuperarlo. No se si tendría una utilidad muy marginal, pero bueno, como pides ideas... ;)

joapuipe's picture

Precisamente


creo que puede ser útil adaptar estas funcionalidades a un entorno específico de esteganografia.

Precisamente lo que me anima con el proyecto es que no existe un "estándar" en esteganografía. Quiero decir, sí, hay muchos programas de esteganografía por Internet, pero cada uno trabaja sobre un formato específico (PNG o JPG o BMP) y utilizando su propio algoritmo de embebido (usualmente la ocultación en el Bit Menos Significativo). Uno de los objetivos de Wodax es aunar todas las técnicas que un sólo programa y que el usuario elija cuál utilizar.

utilizar formatos muy fijos y conocidos puede crear patrones buscables dentro de las imágenes que los alojan

Existe el mismo problema si se cifra un fichero de texto. El atacante podría buscar el carácter "e", "a", "s"... en el fichero esteganográfico para encontrar patrones. Para evitar esto utilizo un generador aleatorio que repartirá el "paquete" a ocultar entre todas las imágenes a utilizar.

Imaginemos que en principio sólo utilizamos una imagen tapadera porque el fichero que queremos ocultar (uno sólo y por eso no creamos un paquete) es pequeño. Entonces, la idea es "ver" el fichero a ocultar como un vector de bits.

La idea es no ocultar los bytes de forma secuencial en la imagen ni con ningún orden lógico, sino utilizar el generador de número aleatorios para que nos diga el lugar donde de ocultará un conjunto de bits. De esta forma, si usamos, por ejemplo, la técnica LSB Insertion, los dos primeros bits de la "a" están en el píxel 1, los dos siguientes en el 4423, los dos siguientes en el 92421... ¿Qué sirve como semilla para el generador? La contraseña del usuario (que se utilizará para cifrar también el fichero si así lo desea).

En la versión anterior cometí el error de utilizar las funciones rand() y srand() para esta tarea, esto es un fallo de seguridad importante. Para esta versión utilizaré algún CSPRNG.

Me bajo el código y me lo miro a ver si pillo algo XD.

El código está en una versión muy inicial, pues acabo de empezar.

Gracias por comentar.

xblasco's picture

Mejora contínua


Porque eso es lo que caracteriza a los humanos.

Coger algo que tenemos, adaptarlo y mezclarlo con otras opciones para obtener una mejora contínua.

Para que quieres implementar una funcion de introducir
varios ficheros en uno solo? Para eso ya esta TAR o ZIP,
o cualquiera de los miles de archivadores que hay.

Porque no toda la gente es experta en informática. A la gente le gusta los interfaces amigables. Si lo que quieren es ocultar tres ficheros en una imagen prefieren usar una aplicación que tres. Además por motivos de seguridad es mejor no crear ficheros temporales con la información en claro.

Para que quieres implementar funcionalidad de cifrado?
ZIP ya lo hace, y si te pones quisquilloso y exigente,
GNUPG tambien.

Porque los ficheros cifrados con ZIP o GPG tienen una cabecera perfectamente conocida. Quien quisiera averiguar si has metido uno de ellos en una imagen tendría un texto claro que buscar, y eso faciliota el ataque.

Para que quieres dividir 1 fichero en varios trozos y
luego juntarlos? split y cat ya lo hacen.

Si, pero te digo lo mismo que en el punto uno.

Para que quieres implementar compresion si ya lo
hacen GZIP, BZIP2, 7ZIP, etc.?

Porque llamar a libreriías que realizan la compresión es fácil ya acabes generando una aplicación. No un conjunto de scripts que hay que ir encadenando.

joapuipe's picture

En el clavo


xblacso ha dado en el clavo.

Fíjate que si utilizase un conjunto de scripts para hacer todo el proceso de empaquetado (tar), compresión (gzip, bzip, zip...), cifrado (gnupg) y división (split) y después usase mi programa para ocultar en una imagen tendría que crear un mogollón de ficheros temporales:

1. el .tar
2. el .tar.gz
3. el .tar.gz.gnupg
4. los distintos .tar.gz.gnupg.X

... y finalmente las imágenes finales. Y esto supone dos problemas:

1. Seguridad (todos sabemos que el rm -rf no borra físicamente los datos).
2. Eficiencia (leer y escribir CUATRO veces en el disco duro o pendrive es MUY ineficiente).

Por eso, quiero que el programa lo haga todo "al vuelo" (utilizando librerías más que probadas, eso sí).

Por qué no utilicé la librería libtar, por ejemplo, para empaquetar, porqué todas las funciones que tiene son para crear "paquetes" en un fichero en el disco. No puedo crear un paquete a partir de un vector de bytes. Como el formato Tar es muy sencillo me dije: "voy a terminar antes implementando un par de funciones para empaquetar y desempaquetar que indagando por los interiores de la librería". Y así fué.

Antonio Calatrava's picture

iStego


No conocía Wodax y eso que la esteganografía es algo que me encanta... De hecho he desarrollado una utilidad para iPhone que utiliza la técnica del bit menos significativo para esconder texto u otra imagen dentro de una. Se llama iStego y si queréis probarla os puedo facilitar algún código de descarga gratuita (aunque solo funcionan si tienes cuenta iTunes Store de USA).

Estoy de acuerdo con jorgegv, pienso que reinventar la rueda es absurdo. Es más interesante integrarlo con tecnologías existentes.

Desafortunadamente en el iPhone sólo pude hacerlo con imágenes PNG ya que la técnica del bit menos significativo no se puede implementar en JPG, por ello las imágenes que creas no puedes guardarlas en la librería de fotos (ya que al utilizar la API de guardado ésta la convierte a JPG automáticamente) pero sí que puedes enviar el PNG por email a otra persona y que ésta copie la imagen y la recupere usando iStego...

La verdad es que la esteganografía me encanta...