domingo, 23 de enero de 2011

Montando un sistema de descargas oculto ( 1 ): las bases

La idea era mostrar primero un posible escenario de control total de internet, pero se volvió demasiado post-apocalíptico. Na' , imaginaos simplemente que queremos distribuir eh...código fuente, pero sin que nadie se dé cuenta de que su servidor lo aloja.
Una opción es utilizar algo conocido como esteganografía, como dice en la Wikipedia:

La esteganografía es la disciplina en la que se estudian y aplican técnicas que permiten el ocultamiento de mensajes u objetos, dentro de otros, llamados portadores, de modo que no se perciba su existencia. Es una mezcla de artes y técnicas que se combinan para conformar la práctica de ocultar y enviar información sensible en un portador que pueda pasar desapercibido.

Vamos, que así como la criptografía intenta que los datos no sean recuperables sin una contraseña, la esteganografía apunta a pasar mensajes sin que se interpreten como tales.

Por ejemplo, hay imágenes en casi cualquier página de Internet, podemos introducir nuestros datos en una imágen y después subirla a un foro, un host de imágenes o donde nos de la gana.


La técnica de esteganografía probablemente más utilizada con las imágenes es la llamada LSB ( "Least Significant Bit", el Bit Menos Significativo ), que se basa en lo siguiente:

Las imágenes típicas ( BMP, PNG, GIF, JPEG ... ) son gráficos raster, es decir, que un archivo se reduce a un conjunto de valores de píxeles ( con cabeceras y quizá algún tipo de compresión ), y por cada pixel un número para cada color, por ejemplo BMP, PNG y JPEG usan un esquema llamado RGB o RGBA si hay transparencia, donde un pixel se codifica como tres números, uno que representa la cantidad de rojo ( "R" ), otro para el verde ( "G" ) y otro para el azul ( "B" ), y uno más para la transparencia, si la hay ( alpha "A" ), normalmente cada uno puede ir de 0 a 255, un byte, o 8 bits.

La técnica LSB substituye el bit menos significativo de cada pixel por uno del archivo a incluir, si cada pixel tiene 8 bits, cambiar el bit menos significativo hace que el color cambie en 1/256 en el peor de los casos, cambio que el ojo no es capaz de apreciar, decidme, sin tener que buscar cambios en una imágen compleja, encontrais la diferencia entre:

y:
 Indistinguibles verdad?, pues ese esa es la mayor diferencia que puede haber.

A la hora de escribir el código, si utilizamos python, Python Imaging Library allana el camino permitiendonos ver la imágen como un array bidimensional de pixeles, solo hay que abrirla


from PIL import Image
img = Image.open( archivo de imágen )



Ahora si vamos a manipular mucho los pixels lo más eficiente es cargarlos en memoria

fst_img = img.load( )


Y podemos acceder a ellos como si fuera un array de tuplas

pixel = fst_img[ x, y ]


Otra propiedad muy útil es el ancho y alto de la imágen, están en el atributo size de la imágen

dim = img.size# Poniendo todos los pixels a negro
for x in xrange( dim[ 0 ] ):
    for y in xrange( dim[ 1 ] ):
        fst_img[ x, y ] = ( 0, 0, 0 )


Solo queda guardar la imágen:

img.save( nombre del archivo guardado )


El resto está en manos del programador, este es el que añade el archivo [ stego_add.py ] y este el que lo extrae [ stego_extract.py ], el que extrae, extrae todos los bits, lo que hace que el archivo acabe con ruido, con compresiones como gzip esto no es un problema ya que simplemente lo ignora, si el formato que piensas usar tiene problemas con estas cosas puedes simplemente añadir unos cuantos bytes al principio que indique el tamaño del archivo para solo leer lo necesario.

Nota: obviamente no se pueden cambiar alegremente los pixeles de una imagen JPEG ( que comprime con pérdidas ) y esperar que funcione, ya que al codificarla se pierde la información, para este formato hay que usar otros métodos.

Por ejemplo:

$ ./stego_add.py llcat2.jpg freenet07.tar.gz test.png
Tamaño del archivo: 40879 bytes
Imágen:
500 x 374
70125 bytes
68.4814453125 Kb
$

Imágen original:

Imágen con el tar.gz de freenet en los bits menos significativos:
( El formato pasó de ser JPEG a PNG por lo dicho antes. )



$ ./stego_extract.py test.png fnet.tar.gz
$ gunzip fnet.tar.gz

gzip: fnet.tar.gz: decompression OK, trailing garbage ignored
$


Se puede abrir el archivo tar y comprobar que los archivos siguen intactos

En la siguiente más y mejor ...

[ Montando un sistema de descargas oculto ( 2 ): cifrando y pensando a lo grande ]

2 comentarios:

  1. Me ha gustado mucho el artculo... me trae recuerdos e inquietudes de poder hacer algo ms grande con esto. :)

    ResponderEliminar
  2. Me alegro, se ve que esto de mandar datos "invisibles" es un tema que despierta interes.

    ResponderEliminar