Documentos de Académico
Documentos de Profesional
Documentos de Cultura
me/librosdehacking
SECCIÓN 2
“En un mundo en el que la totalidad del cono
cimiento humano se duplica aproximadament
e cada diez años, nuestra seguridad solament
e puede descansar en nuestra capacidad de a
prender.”
-Nathaniel Branden
basándonos en él.
Este libro contiene un contenido teórico acotado, pero suficiente, para que el
alumno puede entender todos los conceptos explicados: desde la base hasta
CAPÍTULO 1
Introducción A Scapy
descubrimiento de redes.”
Fuente: Proyecto Scapy
http://www.secdev.org/projects/scapy/
SECCIÓN 1
“Todas las piezas deben unirse sin ser forzad
as. Debe recordar que los componentes que e
stá reensamblando fueron desmontados por u
sted, por lo que si no puede unirlos debe exist
ir una razón. Pero sobre todo, no use un mart
illo”
-Manual de mantenimiento de IBM, año 1925
de redes.
¿Qué Es Scapy?
Descripción breve
Scapy es un software especializado en la manipulación de paquetes y tramas
de red.
Como base para crear el software necesario para poder trabajar con
librerías no lo permiten.
existe una versión extraoficial que funciona para el nuevo Python 3.X.
Scapy puede ser usado como una librería más de Python. Esto es muy
Scapy como base para la manipulación del tráfico de red, pero teniendo
Funcionamiento de Scapy y el
bajo nivel
El funcionamiento y concepción de Scapy es su propia piedra angular: Da
Esto no ha de asustar el lector. Una vez haya hecho unas pocas pruebas, verá
varias dependencias.
características de Scapy.
oficial de instalación:
http://www.secdev.org/projects/scapy/portability.html
SECCIÓN 3
El Modo Interactivo
El interactivo.
El programático.
El modo interactivo consiste en un intérprete de comandos con la funcionalidad de Scapy inline. Su aspecto es muy
cuando usamos Scapy como librería en nuestro propio programa. No ejecutaremos Scapy directamente, sino que
será nuestro código quien se encargue de cargarlo y utilizarlo conforme le hayamos indicado.
La llamada a éste será igual que cuando ejecutamos cualquier otro programa en Python:
Permisos y usuarios
Es importante destacar que cuando trabajamos con la red a bajo nivel hay ciertas tareas que solo están permitidas o
Esto es así para evitar un uso fraudulento de la red, como podría ser el limitar que cualquier usuario pueda leer toda
la comunicación que circula por la tarjeta de red. De no se así, supondría un grave fallo de seguridad para todos los
Por este motivo Scapy necesita privilegios de administrador para ejecutarse con todas sus funcionalidades. Este es
un detalle importante que muchas personas olvidan y no consiguen hacer funcionar Scapy a pleno rendimiento.
Para ejecutar Scapy en modo administrador bastará hacerlo con el domando del sistema sudo antes de ejecutar
Scapy.
Qué es un intérprete
Cuando trabajamos con Scapy en modo interactivo, lo que realmente estamos haciendo es interactuar con un
En este modo de funcionamiento tendremos pre-cargadas la mayor parte de las funciones y librerías de las que
consta Scapy. Además, el modo interactivo, cuenta con autocompletado (usando la tecla tabulador <TAB>)
Este modo es muy útil, y tremendamente rápido, para pruebas muy cambiantes que no tiene un patrón fijo o en las
que una prueba depende del resultado de la anterior. Nos permite hacer test al vuelo y analizar lo resultados desde
el propio terminal.
Si tienes conocimientos de Python, probablemente te resulte familiar. El CLI de Scapy es el mismo que el Python,
pero “vitaminado”.
siguiente terminal:
Si el lector se encuentra con los warnings que aparecen en la captura, es que necesita instalar librerías adicionales
que Scapy requiere. No son imprescindibles para la mayor parte de las tareas, pero sin ellas no podrá ejecutar
ciertas acciones.
No se preocupe por el mensaje de IPv6. Éste se debe a una configuración errónea de IPv6 en sus tarjetas de red.
Nos es necesario preocuparse por él, salvo que queramos trabajar con IPv6.
En el intérprete también podemos observar la versión en ejecución de Scapy. Asegúrese que es la 2.3 o superior.
Observamos el comienzo del cursor y punto de inicio de comandos donde escribiremos nuestras órdenes para el
intérprete:
Auto-completado
Al igual que ocurre la línea de comandos tradicional de Linux, Python y Scapy también disponen de
Tras escribir algún carácter, si pulsamos 2 veces seguidas el tabulador nos aparecerán las funciones o estructuras
disponibles que comiencen por esos caracteres. Si escribimos una carácter más, se recibirá el número de elementos
a autocompletar hasta que solo quede uno, que se acabará de escribir por nosotros:
El autocompletado nos será de gran ayuda para ahorrar tiempo y no tener que recordar exactamente el nombre d
de Python. Eso significa que tenemos toda la potencia de heredada de Python en el intérprete de Scapy.
La definición de variables, elementos de control de flujo, condicionales, listas, cadenas de texto o cualquier otra
SECCIÓN 4
Funciones De Ayuda
necesitemos.
ls()
lsc()
help()
Doble tabulación
Por ese motivo, Scapy nos proporciona una función para listar todas las
función lsc():
Scapy dispone de multitud de tipos de datos (de los que se hablará más
Recordar que para salir de la ayuda, tendremos que pulsar la tecla “q”, al
podemos usar la función help(), ésta no nos aportará información útil para el
lugar.
SECCIÓN 5
sencilla: https://www.wireshark.org/download.html
Nuestro primer paquete
Construir un paquete básico en Scapy es tan básico como hacer lo siguiente:
ICMP.
Capa 1: IP.
Capa 2: ICMP.
Configurando el paquete
Cuando construimos un paquete tendremos que indicar cierta información
Enviando un paquete
Para enviar un paquete en Scapy tenemos varias funciones. La más básica es
la función send().
Esta función necesita, como mínimo, el paquete que se quiere enviar a la red
el ping.
está activo:.
CAPÍTULO 2
que desea. Aunque crea que apilar una capa 802.1q sobre
tradicionales.”
SECCIÓN 1
“Una vez un ordenador me venció jugando al
ajedrez, pero no me opuso resistencia cuand
o pasamos al kick boxing”
-Emo Philips
En este capítulo aprenderá qué es un layer en Scapy: tipos y los más usados.
Veremos los conceptos básicos para poder crear nuestros propios layers, así
Qué Es Un Layer
Definición
En Scapy un layer (o capa) representa, por lo general, un protocolo. Los protocolos de red se estructuran en pilas,
Un paquete de red está compuesta por múltiples layers, donde cada capa se encarga de una parte de la
comunicación:
La pila de protocolos de red más conocida es la TCP/IP. En ella se asientan gran parte de las comunicaciones a día
Acceso a la red.
Internet.
Transporte.
Aplicación.
El orden es importante
Cada protocolo de comunicaciones se sustenta en una pila de protocolos, que usa como base.
Esta pila de protocolos permiten aislar las capas entre si, aislándolas de lo que por lo que ocurre en la capa superior
Usted se encarga de redactar el texto y de decir a quien quiere enviarlo. Aquí acaba su cometido.
El correo es recibido por el proveedor de internet, que se encarga de hacérselo llegar al proveedor de correo de
destino.
En suministrador de internet destino recibe la información y se la hace llegar al proveedor de correo electrónico
destino.
Lo más interesante de este proceso es que cada interlocutor no ha preocuparse del siguiente paso. Solo ha de
Pues bien, para que este proceso funcione correctamente cada paso tiene que estar en el orden correcto. Sino, el
receptor del mensaje no sabrá que hacer con él, porque no está prepara para ello.
Los protocolos de comunicaciones funcionan igual. Para que una comunicación TCP/IP funcione correctamente,
las capas tiene que estar “apiladas” en un orden determinado. Este orden lo establece cada protocolo.
Esta forma de implementar protocolos tiene la ventaja de que, si queremos desarrollar un protocolo nuevo,
podemos usar otro existente como base. Solo tendremos que poner “encima” las capas que definan nuestro
protocolo (se verá más adelanta cómo definir un nuevo layer, para implementar un protocolo).
SECCIÓN 3
de ordenadores y protocolos para que todos los elementos conectados a una red fueran capaces de comunicarse
En 1984 se presentó el modelo de referencia OSI como un estándar ISO. Éste fue publicado con la intención de que
Paralelamente, la agencia DARPA (Defense Advanced Research Projects Agency) comenzó a desarrollar un sistema
En 1982 el DoD (Department of Defense) Estadounidense anunció la adopción de TCP/IP como estándar para las
comunicaciones militares, y 2 años más tarde reunió a más de 250 fabricantes para promover la adopción de dicho
protocolo.
El resultado fue que OSI quedó como modelo teórico para el estudio de protocolos de comunicaciones y TCP/IP la
OSI consta de 7 capas y nos referiremos habitualmente a ella por su número: “Capa 2” o “capa 7”:
Í
VÍDEO 2.2 - Modelo OSI
Como ya se ha visto en varias ocasiones, un paquete enviado a la red ha de pasar por todas las capas: de más arriba
a más abajo.
El siguiente video nos muestra un caso más práctico, en el que abrimos el navegador y solicitamos la web de
google:
Í
VÍDEO 2.3 - Conexión a Google capa a capa.
Í
VÍDEO 2.4 - Capas TCP/IP y Scapy.
Cuando construimos un paquete desde cero, hemos de tener cuidado de construir un paquete que tenga sentido a
nivel de protocolo. Si no cumplimos esta premisa, el sistema destino no será capaz de interpretar el paquete
recibido.
Para que se asimile mejor este concepto, haremos una prueba enviando un paquete ICMP Echo Request, en el que
No todas las capas encajan con todas. Solo ciertas combinaciones son válidas, al igual que un puzzle.
Por ejemplo, para enviar un paquete del tipo ping, no es necesaria la capa TCP. Además, el protocolo ICMP (en el
que se basa el ping) dice que la capa inferior ha de ser la capa IP y que no puede tener capas superiores.
Sino se cumplen estas reglas, el paquete creado no tendrá sentido y el receptor no será capaz de entenderlo:
Í
VÍDEO 2.5 - Simulación de compatibilidad entre capas.
A pesar de que pueda parecer muy complicado, en la práctica es tremendamente sencillo y muy intuitivo. No te
preocupes si te encuentras algo perdido. Conforme avancemos verás que es mucho más natural de lo que parece.
SECCIÓN 4
nombre con el del protocolo en cuestión salgo alguna excepción, como puede ser la
creación de VLAN (redes de área local virtuales). VLAN es el término popular usado,
parte del prefijo, 802, es común a gran cantidad de protocolo, por eso Scapy
Í
VÍDEO 2.7 - Protocolos más usados y Scapy.
SECCIÓN 5
como se comporta.
Las casas que construyéramos a partir de dicho plano serían las instancias u
caso decimos que la clase acepta parámetros. Todos los layers en Scapy son
Tan solo tenemos que acceder a sus propiedades, que corresponden con los
Para facilitarnos su uso, Scapy pondrá valores por defecto a los campos
cabecera:
Los campos como: versión, flags o TTL (Time To Live), con la
definición del layer, pero si lo que queremos es ver cómo quedará nuestra
instancia del layer, una vez construido con los parámetros que deseemos,
propiedades con el valor None: como chksum o len. Esto es así, porque el
nuestra IP.
BitField: 4 bits.
ByteField: 8 bits.
IntField: 4 bytes.
hexadecimal: 0x05.
LE: El tipo de dato está en representación Litte Endian. Por defecto es Big
Endian.
oficial:
http://www.secdev.org/projects/scapy/doc/build_dissect.html#simple-
datatypes
Parámetros binarios o
hexadecimales
Para establecer los valores de los campos de BitField, ByteField o campos
fabricantes.
Se recomienda leer los RFC de los protocolos más comunes o, al menos, los
IP: https://www.ietf.org/rfc/rfc791.txt
TCP: https://tools.ietf.org/rfc/rfc793.txt
UDP: https://www.ietf.org/rfc/rfc768.txt
ICMP: https://tools.ietf.org/rfc/rfc792.txt
ARP: https://tools.ietf.org/rfc/rfc826.txt
SECCIÓN 6
Modos De Envío
garantizará que:
Antes de continuar es interesante aclarar un término que se ha usado en varias ocasiones: “envío a la red”. Usamos
esta terminología en lugar de “es enviada a internet” porque puede que la información no salga de nuestra red local
y que su destino sea otra subred o que el paquete sea enviado pero la circuitería de red no sepa como tratarlo y no
progrese.
Anteriormente se ha visto el uso básico de la función send. Aunque en la mayoría de las ocasiones será suficiente
su uso básico, hay ocasiones que puede que necesitemos indicar más parámetros para que la información sea
enviada correctamente.
Í
VÍDEO 2.8 - Uso de la función send(...) y sus parámetros.
loop: Si es diferente de 0 envía el paquete, o lista de paquetes, en bucle de forma infinita hasta que lo paremos
pulsando CTRL+C.
inter: Tiempo, en segundos, que queremos que pase entre paquete y paquete enviado.
verbose: Nos permite cambiar el nivel de log o, incluso, desactivarlo por completo (con el valor 0).
Esto significa que no son necesarias las rutas del sistema, la información será enviada directamente a través del
adaptador de red indicado como parámetro de la función. La información será enviada aunque aparentemente no
Esta función, además, nos permite especificar las direcciones físicas o MAC de la tarjeta de red de destino. Sino
Cuando construimos un paquete podemos empezar a hacerlo a partir de la capa de protocolos que deseemos:
Si lo hacemos a partir de la capa 3 o IP y confiamos en las rutas del propio sistema operativo para enviarla, será
Si, por el contrario, necesitamos un control a más bajo nivel: capa 2 (Ethernet o PPP, por ejemplo) debemos de usar
la función sendp(…).
SECCIÓN 7
Análisis De Respuestas
Hay muchas formas de recibir las respuestas de los paquetes que generamos, pero la más útil para el modo
Éstas funciones nos permiten enviar un paquete, tal y como lo hacíamos con las funciones send y sendp, pero
además se quedan esperando la respuesta para que podamos tratarla como necesitemos.
Es importante señalar que no conviene abusar de esta función y solo debería usarse cuando realmente se necesita el
sr(…): Envía y recibe un paquete, o lista de paquetes a la red. Espera hasta que se se ha recibido respuesta a todos
los paquetes enviados. Es importante señalar que esta función trabaja en capa 3. Es decir: para saber cómo enviar
los paquetes usa las rutas del sistema. Sino hay ruta para enviar el paquete/s al destino deseado, no podrá ser
enviado.
sr1(…): Funciona igual que la función sr(…) con la salvedad de que solo captura la primera respuesta recibida
srp(…): Funciona igual que la función sr(…) pero en capa 2. Es decir: nos permite enviar la información por una
tarjeta de red en concreto. La información será enviada siempre, aunque no haya ruta para ello.
srloop(…): Nos permita enviar y recibir información N veces. Es decir: podemos indicarle que envíe 1 paquete 3
veces y, por lo tanto, recibiremos la respuesta a los 3 paquetes, en orden consecutivo. Además nos permite
especificar las acciones a tomar cuando se recibe un paquete y cuando no se recibe respuesta.
tan solo necesitamos asignar a una variable el resultado de una función del tipo sr.
Las funciones sr que devuelven más de un paquete deberemos de tratarlos como una lista de paquetes:
Í
VÍDEO 2.9 - Uso de la función sr(...) y análisis de respuesta.
variable y pulsamos enter, veremos por pantalla un resumen del contenido del paquete:
Podemos usar el método .show() para mostrar la información de respuesta más ordenada y fácil de leer,
Disección de un paquete
Cuando tenemos un paquete completo con todas las capas necesarias para ser enviadas, o cuando recibimos uno,
Podemos acceder a cada una de las capas, como si fuera un diccionario de Python normal. Tomemos este paquete
como ejemplo:
Este paquete es la respuesta a de una conexión TCP a Google. Podemos observar que tiene 3 capas. Ahora
Í
VÍDEO 2.10 - Disección de una conexión TCP.
Cuando tenemos una capa o capas separadas, podemos acceder a sus propiedades, consultarlas, modificarlas y
Í
VÍDEO 2.11 - Análisis con Wireshark de un paquete.
SECCIÓN 8
Por analogía, la información capturada usando esta técnica se guarda en un fichero con extensión .pcap. Este
Estos ficheros son muy útiles si necesitamos guardar el resultado de un análisis de red para su posterior procesado o
La información almacenada en un fichero .pcap podremos analizarla tantas veces como necesitemos sin que se vea
lo usan:
TCPDump/WinDump.
Wireshark/TShark.
Ettercap.
Snort.
Dsniff.
Además, existen librerías para prácticamente todos los lenguajes de programación que nos permiten manipular los
ficheros PCAP, con lo que podremos usarlo en nuestros propios programas de manera realmente sencilla.
Í
VÍDEO 2.12 - Generar archivo PCAP con Wireshark.
Para poder realizar pruebas, realizaremos una captura con Wireshark y lo guardaremos con formato .pcap en un
rdcap(…) indica la ubicación del fichero. La ruta al fichero debe de ser absoluta, o bien posicionarnos en le mismo
Í
VÍDEO 2.13 - Lectura/escritura de fichero PCAP.
Cuando cargamos el contenido en una variable y la imprimimos por el pantalla, podemos ver que Scapy nos
presenta un pequeño resumen de número de paquetes TCP, UDP, ICMP y otros que contiene el fichero PCAP.
operación, como si la información contenida en el fichero la hubiésemos generado con el propio Scapy.
Además, también podemos extraer estadísticas, listar los paquetes, sesiones o ver el contenido tal y como se vería
en TCPDump:
Í
VÍDEO 2.14 - Análisis de un fichero PCAP.
Acceso a las sesiones de conexiones: Una sesión está compuesta por todos los paquetes que forman parte de una
misma conexión lógica. Es decir: Si hemos hecho una búsqueda en Google, la sesión constaría de todos los
paquetes necesarios para recibir esa información. Es importante destacar que Scapy se encarga de ordenar y
unificar los paquetes en función de cada sesión, ya que probablemente la información no se haya recibido en orden.
Las sesiones son guardadas en un diccionario de Python y el contenido en crudo en una lista.
En el siguiente ejemplo veremos cómo buscar sesiones TCP web sin cifrar (puerto TCP 80) y cómo extraer su
contenido:
Í
VÍDEO 2.15 - Búsqueda de conexiones TCP sin cifrar.
necesitemos en él.
Estos son unos pocos ejemplos de lo que podríamos hacer con Scapy:
Í
VÍDEO 2.16 - Búsqueda avanzada de información en PCAP.º
SECCIÓN 9
Qué es el Flooding
Cuando hablamos de flooding (inundación) estamos haciendo referencia a una afluencia masiva de información en
En el caso de la auditoría de redes nos referirnos a enviar muchos paquetes a un mismo destino en un corto periodo
de tiempo.
Si enviamos mucha información a un mismo destino en un tiempo muy pequeño podemos provocar una denegación
Colapso de la red de comunicaciones del objetivo, por lo que no podría establecer más comunicaciones con más
clientes.
Causar un fallo del sistemas operativo o el software destino. Éstos pueden no estar preparados para este tipo de
comportamientos y provocar un comportamiento inesperado, que se suele traducir en una caída del sistema o del
software.
de envío es crucial, por lo que deberíamos de tener toda la información preparada antes del envío.
Scapy está desarrollado en Python. Python es un lenguaje interpretado y no fue concebido para un proporcionar un
alto rendimiento.
Scapy genera la información en el momento de enviarla. Si queremos mandar 100.000 paquetes, el tiempo de
conversión será demasiado alto, por lo que no conseguiríamos un flujo de información lo suficientemente elevado.
Para solventar estos problemas podemos optar por las siguientes soluciones:
Generar una cantidad de paquetes pequeña, pero indicar a la función de envío que re-use esa información en lugar
Pre-generar todos los paquetes que deseemos enviar, guardarlos en un fichero PCAP y después pasar el contenido
Para esto podemos hacer uso del parámetro count de las funciones de envío. Se recomienda usar la funciones de
capa 2, ya que suelen dar un mayor rendimiento al no tener que usar la tablas de resolución de direcciones del
sistema.
Además, para incrementar el número de paquetes por segundo, desactivaremos la salida por pantalla cada vez que
Generar PCAP
Un PCAP contiene información de paquetes y tramas de red ya generadas. En crudo podríamos decir. Si logramos
generar un fichero PCAP y después cargarlo, Scapy no tendría que gastar tiempo en generar los paquetes al vuelo,
Hemos de tener cuidado cuando generemos listas de paquetes muy grandes ya que, sino, podemos llegar a
consumir mucha memoria. En su lugar, usaremos generadores de Python (que usaremos igual que una lista, pero
Í
VÍDEO 2.18 - Generar PCAP con información re-usable.
Las limitaciones intrínsecas de Python no permiten enviar información de manera más óptima, usando Python
puro.
Scapy está preparado para solventar este problema y nos proporciona un método todavía más rápido para enviar
TCP Replay es una herramienta, escrita en C, que es capaz de generar tráfico a una velocidad increíblemente
rápida. Aunque podemos usarla desde su propia línea de comandos, Scapy nos da la posibilidad de usarla desde
código de Python, usando la función sendpfast(…). Esta función es una capa de abstracción sobre tcpreplay.
Le indicaremos la información a enviar, bien sea desde un fichero PCAP o una lista de paquetes.
Cuando la función sendpfast(…) termina, nos muestra un pequeño resumen con información interesante sobre el
envío, como: cantidad de paquetes enviados por segundo, numero de paquetes o cantidad total de información
enviada, en bytes:
necesitaremos añadir un nuevo layer, existen circunstancias en las que nos puede ser realmente útil saber crear
Existen muchos fabricantes que desarrollan sus propios protocolos de comunicaciones, por diversos motivos:
El estándar no se adapta a sus necesidades y, tomándolo como base, lo extienden con sus propias funcionalidades.
No existe estándar para el sistema que se está implementando. Esto es muy habitual en entornos I+D e
infraestructuras críticas y SCADA, como pueden ser: presas, centrales nucleares, sistemas de control mecánico, etc.
Desean que su protocolo sea propietario y forme parte de su propiedad intelectual e industrial. Suele desembocar
en patentes.
Un layer no es ni más ni menos que implementar la definición de un protocolo en formato Scapy. Para esto
Una forma de encontrar el directorio, es utilizar los comandos de Linux locate, grep y head, en el siguiente orden:
Redireccionar la salida anterior y filtrar por la palabra “site-packages”. Éste es un directorio especial en Python,
Nos aparecerán muchos directorios con resultados, pero realmente todos cuelgan de la misma raíz, que es la que
nos interesa. Por eso, podemos usar el comando head para obtener solo 2 dos primeros elementos.
Una vez localizado el directorio de Scapy, nos dirigiremos a él. Hay muchas carpetas, pero nos interesan solamente
contrib: Los layers incluidos en este paquete no serán cargados automáticamente cuando Scapy se inicie. Los
tendremos que cargar manualmente, como cualquier otra librería de Python. Este paquete suele contener layers de
layers: Todos los layers ubicados en este paquete son cargados automáticamente cuando se inicia Scapy. De esta
forma es muy cómo trabajar con ellos, ahorrándonos la tediosa labor de cargarlos uno por uno, ya que hay decenas
de ellos.
Í
VÍDEO 2.20 - Localizando directorios de layers de Scapy.
Scapy tiene diversos tipos de elementos que pueden contener una capa o layer:
Tipos básicos
LE: El tipo de dato está en representación Litte Endian. Por defecto es Big Endian.
Tipos Complejos
Los tipos complejos están formados por la composición de tipos básicos que, además de la información que
contienen, incluyen la lógica de comprobación para validar que el tipo dato es correcto. Por ejemplo, el tipo IPField
Comprueba que cada valor numérico es mayor o igual que cero y menor o igual que 255.
En caso de proporcionarse un nombre de dominio como parámetro, automáticamente lo resuelve y obtiene su IP.
Los tipos complejos son muy útiles para construir nuestras propias capas porque nos ahorran gran cantidad de
trabajo.
Se puede consultar la lista de todos los tipos de datos disponibles en la web oficial:
http://www.secdev.org/projects/scapy/doc/build_dissect.html#simple-datatypes
Un layer es una clase que hereda de la clase especial: Packet. Scapy es capaz de buscar y detectar todas las clases
que heredan de esta clase. Cuando las encuentra, asume que son layers.
class SemaforoProtocol(Packet):
name = "Semaforo"
fields_desc = [
IntField("tiempo_verde", 20),
IntField("tiempo_rojo", 15),
IntField("tiempo_amarillo", 2),
LongField("contador_ciclos", 0),
IntEnumField("luz_on", 1,
{
1: "rojo",
2: "verde",
3: "amarillo"
})
En el ejemplo vemos un layer simulado de un semáforo. El semáforo hereda de la clase Packet, como se ha
comentado.
fields_desc: esta es la lista de tipos de datos que contendrá nuestra capa. En el caso de nuestro semáforo, hemos
contador_ciclos: contador del número de veces que ha tenido lugar el ciclo de luces:
verde-amarillo-rojo.
Por último, tendremos que añadir nuestro nuevo layer a la lista de layers que son cargados por defecto cuando Scapy
Guardaremos nuestra capa en el directorio “layers/”, en el punto de instalación de Scapy, con un nombre descriptivo
Editamos el fichero fichero “config.py”, en el directorio de instalación de Scapy, y añadiremos nuestra capa a la
lista de Python “load_layers”. En dicha lista, añadiremos un elemento más, que será el nombre del fichero con el
Í
VÍDEO 2.21 - Creación de un Layer de Scapy.
SECCIÓN 11
información.
Los exploit son programas capaces de aprovechar fallos de seguridad de sistemas o software. Suelen constar de 2
partes:
La parte encargada de aprovechar el fallo de seguridad y que logra ejecutar código (como comandos del sistema) en
el sistema remoto.
El payload: el código que queremos ejecutar en el sistema. Se suelen enviar en el formato más cercano al código
Ahora que ya sabemos como funciona un exploit, imaginemos que queremos ejecutar un ataque masivo a un
objetivo A. Queremos realizar una denegación de servicio, por lo que necesitamos lanzar gran cantidad de paquetes
al objetivo.
Utilizamos uno o varios exploits para buscar máquinas vulnerables en internet o nuestra red local. En el payload del
La generación del código hexadecimal en Scapy es realmente fácil. Tan solo tenemos que crear el paquete y utilizar
Llevar a cabo este ataque es algo más complejo de lo explicado, pero no ha servido por ser ilustrativo.
Exportar paquetes en base64
Del mismo modo que la exportación a hexadecimal en Scapy nos puede ayudar en para a la hora de la preparación
de otros tipos de ataques, la exportación en formato base64 nos abre otro abanico de posibilidades:
Imaginemos, por ejemplo, un sitio web con un parámetro vulnerable una URL. Y que, a través de dicho parámetro,
Al igual que en el caso de la exportación hexadecimal, queremos usar esa máquina para realizar una ataque de
denegación de servicio contra otra máquina. En este caso, el payload del exploit tendríamos que pasarlo en formato
Para generar un base64 de salida, tan solo tendremos que usar la función export_object(…).
Es muy importante para que no obtengamos errores, es que a la función deberemos de pasarle una cadena de texto
como entrada. Por lo tanto, tendremos que usar la función str(…) previamente:
Exportar a PDF
Scapy incorpora la funcionalidad de exportar la información de un paquete a un PDF.
El PDF resultante es un mapa con la representación binaria del paquete y sus correspondientes capas en Scapy. Está
función es tremendamente didáctica y nos será de gran utilidad para el estudio y comprensión de protocolos.
Para generar el PDF deberemos tener instalada la librería PyX de Python, así como sus dependencias.
Generar el documento es muy sencillo, tan solo tendremos que usar el método .pdfdump(…), que tienen todos los
paquetes construidos con Scapy, e indicarle la ruta donde queremos almacenar el fichero:
El resultado es un PDF como el que se puede ver en la imagen:
Para poder usar dicha funcionalidad tendremos que asegurarnos que tenemos instalada la librería gnuplot-py.
Las gráficas nos pueden ser de utilidad para realizar estudios de comportamientos y representar la información de
forma visual.
Antes de mostrar los ejemplos reales, es conveniente que recordemos algunos conceptos e introduzcamos algunos
nuevos:
Como ya sabemos, la función sr(…) envía un paquete o lista de paquetes.
La función sr(…) devuelve 2 valores: los paquetes a los que se ha obtenido respuesta y a los que no la han
obtenido.
Scapy nos proporciona la función sniff(…): que nos permite crear un sniffer y guardar la información obtenida en
Hay ciertas capas de Scapy, como TCP, cuyos parámetros podemos establecerlos con listas, en lugar de con un
único valor. Scapy lo reconocerá y generará todos los paquetes con esa información. Es decir: si en el layer TCP, en
puerto de destino establecemos la lista: [1, 22, 80, 8080]; TCP(dport=[1,22,80,8080]), Scapy automáticamente
generará 1 paquete diferente por cada puerto. En este caso 4 paquetes TCP.
.sent_time: Nos indica cuando ha sido enviado el paquete. Esta propiedad estará a 0
en los paquete que recibamos de un sistema remoto, ya que, realmente solo podemos
Los paquetes que no han obtenido respuesta se devuelven en una estructura interna de Scapy, pero que se comporta
Í
VÍDEO 2.22 - Creación de listas de paquetes con listas de valores.
Vamos a estudiar un par ejemplos sobre con los que poder apreciar su potencial:
Para esta práctica se usarán las propiedades .time y .sent_time, explicadas anteriormente, a fin de determinar el
Í
VÍDEO 2.23 - Estudio de tiempos de respuesta en conexiones TCP.
Cada paquete TCP tiene un número de identificador de secuencia que es usado por el protocolo para controlar el
correcto orden en el que se envían y reciben los paquetes entre emisor y receptor.
Estos valores deberían de ser lo más aleatorios posibles ya que, si un atacante pudiera predecir el valor del siguiente
identificador de secuencia y lo enviara antes que emisor legítimo, no solo lograría hacerse pasar por el emisor, sino
Antiguamente este fue un problema muy grave y muchos sistemas operativos tuvieron que ser parcheados de
Como segunda práctica, analizaremos los identificadores de secuencia de una comunicación TCP a un web http,
analizando la aleatoriedad de estos valores. Crearemos una gráfica con estas respuestas:
Í
VÍDEO 2.24 - Análisis de números de secuencia TCP.
CAPÍTULO 3
“El único sistema seguro es aquél que está a
pagado en el interior de un bloque de hormig
ón protegido en una habitación sellada rodea
da por guardias armados”
-Gene Spafford
con los que podrá crear sus propias librerías y software en muy poco tiempo
Python. Sus problemas de diseño. Sus ventajas. Cómo y cuándo usarlos, así
Por último, estudiaremos teoría de autómatas finitos deterministas sin
Funciones Y Llamadas
Cuando se inicia Scapy en línea de comandos, todas las funciones son importadas automáticamente, no así cuando
La llamada a una función de Scapy, será del mimo modo que en el terminal:
Í
VÍDEO 3.1 - Uso de la función sniff.
Importar Layers
Del mismo modo que importamos funciones, habremos de importar aquellos layers con los que queramos trabajar.
El uso de los layers, será idéntico al que hacíamos de ellos en el modo interactivo:
Í
VÍDEO 3.2 - Envío y recepción de paquetes.
básico común (int, float…). Aunque pueda parecer un concepto un tanto enrevesado, lo cierto es que es realmente
útil.
Imaginemos, por ejemplo, la función de Scapy sniff(…). Si mostramos su ayuda, nos aparecerá la siguiente
información:
Nos fijamos en el parámetro prn. Este parámetro estará presente en otras muchas funciones y, tal y como se puede
ver en la documentación, hace referencia a una función como parámetro de entrada, como comentamos
anteriormente.
En el caso de la función sniff(…), está función será aplicada a cada paquete capturado. O, dicho de otro modo, cada
vez que la sniff(…) intercepte un paquete llamará a esta función con el paquete interceptado como parámetro.
Esta funcionalidad nos da una gran potencia: imaginemos que queremos hacer un pequeño programa que intercepte
todas las comunicaciones y que vaya almacenando todos los host detectados en la red. Usando esta característica
Í
VÍDEO 3.3 - Creación de sniffer descubridor de hosts.
SECCIÓN 3
Envío De Información
Creación de paquetes
Ya hemos visto en varias ocasiones cómo construir un paquete en Scapy. En este punto ampliaremos un poco más
los conceptos de construcción e incluiremos algunos trucos que nos resultarán de gran ayuda.
Hasta ahora, construíamos un paquete para recibir un respuesta a un PING como sigue:
if __name__ == '__main__':
pkg = IP(dst="google.com")/ICMP()
No es necesario que construyamos todo el paquete de una vez. Podemos hacerlo por partes, según nos convenga:
if __name__ == '__main__':
ip_layer = IP(dst="google.com")
icmp_layer = ICMP()
pkg = ip_layer/icmp_layer
Otra parte olvidada de los paquetes es el payload final. Existen ciertos protocolos que nos permiten poner cualquier
tipo de información y añadir un payload u otro puede ser tan sencillo como añadir un texto:
ip_layer = IP(dst="google.com")
tcp_layer = TCP(dport=80)
pkg = ip_layer/icmp_layer/payload
Esto último nos puede resultar de utilidad para crear paquetes con firmas de validación diferentes. Es decir: que con
un pequeña variación (un carácter más, por ejemplo) el paquete será diferente. Esto es muy útil para ciertos ataques
de fuzzing.
entrada de un sistema.
En el caso del análisis y auditoría de redes, consistirá en la generación de gran cantidad de paquetes de red,
variando y combinando los valores de cada una de los layers de los paquetes enviados. De esta manera lograremos
La finalidad es analizar la respuesta y comportamiento del sistema auditado ante este tipo de técnicas, ya que puede
darse el caso (y de hecho se da a menudo) que ante ciertas combinaciones de valores, los sistemas remotos tienden
a comportamientos extraños o dejan de funcionar a pleno rendimiento hasta que sean reiniciados o, incluso, hasta
Scapy incorpora capacidades para facilitarnos el fuzzing. Alguna ya se han visto en otros apartados, pero las
Í
VÍDEO 3.4 - Creación de fuzzer con Scapy.
Los campos que usaremos más comúnmente usados para fuzzing serán:
Flags TCP.
IPs de origen.
Para ello podemos ayudarnos de algunas clases que Scapy proporciona para generar valores aleatorios:
flexibilidad nos dará en nuestro trabajo, si sabemos cómo parametrizar ciertos valores.
Es muy molesto y poco productivo tener que cambiar nuestro código cada vez que queramos cambiar la IP de
destino, modificar el puerto destino u origen o cualquier otro valor. En su lugar podemos hacer un interfaz en línea
de comandos que nos permita cambiar estos valores cuando llamamos a nuestro programa.
Para hacer esta interfaz, usaremos la librería nativa de Python argparse. Ésta nos permite configurar cada
parámetro de manera muy sencilla. Incluso construye la ayuda para el uso de nuestro programa de manera
automática.
Para aprender mejor la potencia de esta funcionalidad, hagamos un ejemplo que nos permitirá especificar:
import argparse
# ----------------------------------------------------------------------
def send_pkg(args):
"""
target = args.target
port = args.port
tcp_flags = args.tcp_flags
ip_layer = IP(dst=target)
send(ip_layer/tcp_layer)
def main():
args = argparse.ArgumentParser(description="Interfaz de
linea de comandos")
destino")
destino")
args.add_argument("--tcp-flags", dest="tcp_flags",
help="flags TCP activos cuando sea enviado el paquete")
parsed_args = args.parse_args()
send_pkg(parsed_args)
if __name__ == '__main__':
main()
SECCIÓN 4
Scapy Y Multithreading
Hilos en Python
Los hilos son una de las mejoras maneras de paralelizar trabajos costosos o de poder realizar tareas de forma
Lamentablemente Python no fue diseñado para tareas de alto rendimiento, sino para hacer extremadamente sencilla
Guido Van Rossum (creador de Python) tomo la decisión de que Python no implementara hilos reales, porque de
esta manera el diseño del lenguaje y su motor de ejecución sería mucho más sencillo de implementar y era menos
probable a que aparecieran errores típicos del desarrollo concurrente, como las condiciones de carrera.
Limitaciones
Debido a que a que el motor de ejecución de Python (también llamado máquina virtual) no fue diseñada con la
Podemos usar hilos en Python, pero la ejecución de éstos es simulada. ¿qué significa esto?
Cuando desarrollamos usando hilos en Python, lo que realmente ocurre es que el motor de Python ejecuta nuestro
programa en un único proceso y en dicho proceso registra los hilos “virtuales” que, como programadores, creemos.
La limitación de Python consiste en que solo se podrá ejecutar un hilo a la vez. La máquina virtual de Python
designa un tiempo de ejecución para ejecutar cada hilo. Este tiempo es el mismo para todos los hilos. Cuando este
tiempo finaliza, suspende ese hilo y lo intercambia por otro. De tal forma que, de nuevo, solamente hay un hilo
ejecución. Por esta razón decimos que los hilos son simulados. Esta animación ayudará a aclarar este concepto:
Í
VÍDEO 3.6 - Funcionamiento hilos en Python.
Debemos de tener claro este modo de funcionamiento de Python, ya que muchos problemas que en otros lenguajes
Como apunte final, comentar que existen varias implementaciones del motor de Python. Python es un lenguaje de
programación que tiene definido su modo de funcionamiento mediante los llamados PEP y cualquiera que
implemente este funcionamiento podrá escribir un motor compatible con el código de Python que escribamos.
El motor oficial de Python está escrito en C. Pero existen otro escritos en diferentes lenguajes. Lo más curioso, e
interesante, es que algunos de ellos no tienen la limitación de los hilos comentada y pueden ejecutar hilos reales. El
problema es que estas implementaciones no son compatibles 100% con las versiones oficiales de Python y su uso
es bastante limitado.
Pypy: Escrita en RPython. Es una gran alternativa al motor oficial debido a su alta compatibilidad, gran
IronPython: Escrita en .NET. Una gran opción para usar Python conjuntamente a otros lenguajes de Microsoft,
Qué paralelizar
Debido a las restricciones de motor de Python, podemos encontrarnos con ciertos problemas, resueltos en otros
lenguajes, que cuando los portamos a Python pueden darnos resultados paradójicos.
Uno de estos problemas suele ser el procesamiento concurrente de una lista de elementos. En otros lenguajes
lanzaríamos un hilo para que cada valor se procesara en paralelo y conseguiríamos una gran mejora de velocidad.
Según lo estudiado hasta ahora, cada elemento que se procesa lanzaría un hilo “virtual”.
Cada uno de estos hilos, como ya se ha comentado, estaría ejecutándose un determinado tiempo, prefijado por el
motor de Python.
Si el tiempo en procesar cada elemento de las lista, es mayor que el tiempo prefijado para cambiar de hilo, entonces
ese hilo tendrá que ejecutarse varias veces hasta finalizar el procesamiento del elemento. Es muy importante
La cantidad de hilos en ejecución es limitada, ya que sino saturaríamos la máquina virtual de Python y el sistema.
Creamos 5 hilos.
Esto significa que, para procesar 1 elemento necesitamos 2 ejecuciones de un hilo. Hasta que un hilo no finaliza no
En la segunda ejecución de cada hilo, solo quedaría 1 unidad de tiempo por procesar, pero este hilo quedaría
suspendido hasta que finalicen de ejecutarse los otros 4 y vuelva a tocarle su turno de ejecución.
El resultado para este problema sería que el procesamiento de los 100 elementos tardaría casi el doble que si
hubiéramos escrito ese mismo programa sin hilos y se ejecutara de forma secuencial. Y he aquí la paradoja
comentada: cuando el sentido común nos dice que el tiempo de ejecución mediante hilos debería de reducirse casi
tanto como el número éstos, los resultados empíricos nos demuestran que no solo no es así, sino que su ejecución
La conclusión de este estudio es que, en Python, los hilos solamente han de usarse para ciertos casos de uso muy
Funciones de ejecución continuada: Como las funciones que procesan las conexiones de clientes de un servidor
web.
Si el sistema analizado nos devuelve un SYN-ACK, significará que dicho puesto está abierto.
import threading
from scapy.all import sr1, IP, TCP
CONCURRENCY = 5
OPEN_PORTS = []
VERBOSE = 1
if VERBOSE > 0:
if res[TCP].flags == 18:
OPEN_PORTS.append(port)
if VERBOSE > 1:
sem.release()
def main():
sem = threading.BoundedSemaphore(value=CONCURRENCY)
threads = []
threads.append(t)
t.start()
sem.acquire()
for x in threads:
x.join()
# Mostrando resultados
for x in OPEN_PORTS:
print " - %s/TCP" % x
if __name__ == '__main__':
main()
SECCIÓN 5
Interceptación De Paquetes Y El
Sistema Operativo
de la red.
información en crudo.
más. Imagínese una tubería transparente con agua por la que circulan peces.
Problemas de modificar la
vuelo:
Como ya hemos comentado, modificar información al vuelo no es tarea
estándar.
(la red) hasta el sistema operativo. Para poder realizar esto tenemos la
operativo.
Una vez tengamos bloqueado el tráfico a la capa del kernel que procesa los
El S.O. y la interceptación al
vuelo
Para que un paquete sea procesado por el sistema operativo, tiene que pasar
lanzar muchos paquetes con el flag SYN activo. Cuando el sistema remoto
Para realizar este tipo de ataques tendremos entonces que interponer ciertas
con un paquete TCP RST, podríamos poner la regla firewall que no permita
SECCIÓN 6
Introducción Syslog
Un log es una bitácora que nos permitirá registrar aquella actividad e información que deseemos, de la forma y
manera necesitemos. Todos los sistemas operativos (incluso los de los dispositivos móviles) integran algún sistema
Cuando hablamos de logging remoto, nos estamos refiriendo a poder registrar toda la actividad en un sistema
remoto. Un sistema dedicado exclusivamente al almacenamiento y gestión de logs. De esta forma, todos los
dispositivos pueden enviar su bitácora a dicho sistema y éste les proporciona lugar centralizado donde explotar y
Las bitácoras nos serán de gran ayuda cuando necesitamos saber qué hemos hecho y en qué momento. Esto es muy
importante de cara a poder demostrar y probar cuándo sucedió cada acción. En una auditoría de seguridad, de cara
Syslog es un estándar de facto en los sistemas de logging, compatible con prácticamente cualquier plataforma,
para que almacene dicha información en un servidor remoto o, incluso, en ambas ubicaciones.
En Python, configurar un sistema de log remoto, es tan sencillo como indicar el IP/domino del servidor (y resto de
En el siguiente código se puede ver la configuración de un sistema de log remoto en código Python:
import logging
import logging.handlers
logging.basicConfig()
logger = logging.getLogger()
logger.setLevel(logging.INFO)
# CONFIGURACION DEL LOG REMOTO
logger.addHandler(syslog)
def main():
# Level: Info
logger.info("This is a message")
# Level: Debug
logger.debug("This is a message")
# Level: Error
logger.error("This is a message")
if __name__ == '__main__':
main()
Niveles de log
El sistema de log permite guardar información en la bitácora, en función del nivel de detalle que queramos, sin
Escribiremos nuestro código, usando el sistema de log, y mostrando la información que creamos necesaria. En
función del nivel de detalle que configuraremos globalmente en nuestra aplicación, se mostrarán unos mensajes u
def main():
# Level: Info
logger.info("This is a message")
# Level: Debug
logger.debug("This is a message")
# Level: Error
logger.error("This is a message")
Como vemos en el código, cada función corresponde con el nombre de un nivel de log (debug, info o error).
Dependiendo del nivel de log que se indique globalmente, se mostrarán unos mensajes u otros.
Cada nivel de log tiene un valor numérico asignado internamente. Cuando indicamos un nivel, todo los niveles
iguales o superiores estarán también incluidos. Sería como decirle al sistema de log: Muéstrame todos los mensajes
Debug.
Info.
Warning.
Error.
Critical.
Uso en Scapy
En Scapy podemos usar el sistema de log estándar. Como hemos comentado anteriormente es recomendable hacer,
De este modo quedará registrado cuando se ha efectuado cada prueba y cual fue el resultado de la misma:
# -*- coding: utf-8 -*-
import logging
import logging.handlers
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
log_file = logging.FileHandler(filename="scapy_log_1.2.3.7.2_3.txt")
log_file.setFormatter(formatter)
log_console = logging.StreamHandler()
log_console.setFormatter(formatter)
log_syslog.setFormatter(formatter)
logger.addHandler(log_syslog)
logger.addHandler(log_console)
logger.addHandler(log_file)
OPEN_PORTS = []
timeout=0.2)
if res:
if res[TCP].flags == 18:
OPEN_PORTS.append(port)
else:
def main():
analyze_port("192.168.1.1", x)
# Mostramos resultados
for x in OPEN_PORTS:
logger.critical(" - %s/tcp" % x)
else:
def xmain():
# Level: Info
logger.info("This is a message")
# Level: Debug
logger.debug("This is a message")
# Level: Error
logger.error("This is a message")
if __name__ == '__main__':
main()
SECCIÓN 7
muy sencilla.
Gracias a esta funcionalidad podremos simular pilas de protocolos completas y cada uno de los estados en el que
puede encontrarse.
Una vez hayamos definido el funcionamiento de la pila de protocolos y la respuesta ante cada tipo de situación, su
Qué es un autómata
Un autómata es modelo computacional que realiza aciones de forma automática sobre una entrada para producir
una salida.
Por flechas: Que interconectan los estados con la acción que los hace ir de un estado a otro, para las transiciones.
Gracias a esta representación, es muy sencillo entender conceptualmente, incluso aunque no se sepa teoría de
En movimiento.
Parado.
El estímulo para llegar a cada uno de los estados pueden ser los siguientes:
Tipos de autómatas
Los autómatas están basados en teoría matemática y sus modelos de representación. Estos enfoques están fuera del
alcance de esta formación, por lo que solamente se tratarán a muy alto nivel los tipos de autómatas que existen.
Moore
Una autómata de Moore es un autómata de estados finitos donde las salidas están determinadas por el estado actual
Su representación es la siguiente:
Mealy
Un autómata de Mealy es un tipo de máquina de estados finitos que genera una salida basándose en su estado actual
y una entrada.
Esta es su presentación:
A modo de resumen, podemos concluir con que la principal diferencia entre un modelo y otro es si tienen o no en
cuenta la entrada.
Scapy no sigue ninguno de estos modelos al completo, sino que coge lo mejor de cada uno de ellos para facilitarnos
Estados.
Transiciones.
Los primero que deberemos de hacer será importar la librería que implementa el automaton de Scapy.
Crearemos una nueva clase, que será nuestro autómata, que heredará de la clase Automaton de Scapy.
class HelloWorld(Automaton):
pass
Creación de estados:
Podremos crear un nuevo estado de nuestro autómata, definiendo un nuevo método en la clase y estableciendo el
decorador @ATMT.state.
Todo autómata ha de tener un estado inicial. Para indicar que un estado es el inicial, estableceremos la propiedad
initial al decorador. También podemos establecer que un estado es final (o sumidero) indicando la propiedad final.
Por convención, los estados iniciales y finales se les suele nombrar: BEGIN y END respectivamente, y el resto
class HelloWorld(Automaton):
def BEGIN(self):
@ATMT.state
def STATE_N(self):
def END(self):
Transiciones
Un cambio de un estado viene determinado por una transición. Dicha transición se genera cuando se recibe un
estímulo de entrada.
Generado manualmente.
Transiciones manuales
Las transiciones manuales son iniciadas lanzando una excepción cuyo parámetro será el estado siguiente:
class HelloWorld(Automaton):
@ATMT.state(initial=1)
def BEGIN(self):
@ATMT.state(final=1)
def END(self):
Las condiciones de un estado son formas de indicarle a Automaton cuándo debe de pasar de un estado a otro, sin
Scapy define 3 tipos de condiciones que podremos configurar definir para que se produzcan las transiciones:
Automática: se inicia justo después de que se haya alcanzado el estado al que está asociada.
paquete de red.
Condicionada por un timeout: es iniciada cuando, estando en el estado configurado, se agota el tiempo de espera.
Una condición es tan solo un método con un decorador que indica que ha de ser tratado como una transición. Y un
class HelloWorld(Automaton):
@ATMT.state(initial=1)
def BEGIN(self):
@ATMT.receive_condition(BEGIN)
raise self.STATE_2()
@ATMT.timeout(BEGIN, 15)
def begin_timeout(self):
@ATMT.state()
def STATE_2(self):
@ATMT.condition(STATE_2)
def state_2_wait_for_nothing(self):
raise self.END()
def on_state2_nothing(self):
@ATMT.state(final=1)
def END(self):
Acciones
Por último, tan solo nos queda tratar las llamadas acciones en Automaton. Éstas son ejecutadas justo después de
que una condición finalice y antes de que se alcance el siguiente estado. Dicha acción, se configura mediante un
decorador:
# -*- coding: utf-8 -*-
class HelloWorld(Automaton):
@ATMT.state(initial=True)
def BEGIN(self):
@ATMT.receive_condition(BEGIN, prio=1)
raise self.STATE_2()
@ATMT.timeout(BEGIN, 15)
def begin_timeout(self):
raise self.END()
@ATMT.state()
def STATE_2(self):
@ATMT.condition(STATE_2)
def state_2_wait_for_nothing(self):
raise self.END()
@ATMT.action(state_2_wait_for_nothing)
def on_state2_nothing(self):
nothing"
@ATMT.state(final=1)
def END(self):
Con lo que nos quedaría una representación final del autómata como sigue:
Ejecución de un automaton
Una vez tenemos creado y bien definido nuestro autómata en Scapy, la ejecución es realmente sencilla. Tan solo
def main():
HelloWorld().run()
if __name__ == '__main__':
main()
Í
VÍDEO 3.9 - Ejecución del Automaton completo.
complicadas. Ejemplo de ello son las implementaciones que existen por internet de diversos protocolos y servicios
Una vez explicado y entendido el funcionamiento de autómatas, Scapy y su Automaton, nos resultará realmente
El siguiente código es parte del proyecto. En concreto la parte del servidor DNS:
#!/usr/bin/env python2
the
# SSH connection, SCP and proxy socks (SSH -D) are supported
from scapy.all import IP, UDP, DNS, DNSQR, DNSRR, Raw, send, Automaton,
CNAME = 5
TXT = 16
_CON = "a"
_ACK = "b"
_IWT = "c"
_DATA = "d"
_DONE = "e"
_FAST = "f"
class Core(Automaton):
dn = ""
def parse_qname(self, pkt):
pkt[DNSQR].qname.endswith(self.dn + "."))
d = pkt[IP].src
dp = pkt[UDP].sport
id = pkt[DNS].id
q = pkt[DNS].qd
t = pkt[DNSQR].qtype
if t == TXT:
# if scapy is patched:
# rdata = txtfy(rdata)
0]
class Parent(Core):
self.dn = dn
self.ext_ip = ext_ip
self.dbg = debug
self.nb_clients = nb_clients
self.ssh_p = ssh_p
else:
return False
def get_identifier(self):
if len(self.empty_slots) >= 1:
return self.empty_slots.pop()
return self.empty_slots.pop()
else:
return None
def kill_children(self):
for k in self.childs.keys():
if self.childs[k].state.state == "END":
self.childs[k].stop()
del(self.childs[k])
self.empty_slots.add(k)
return len(self.empty_slots)
@ATMT.state(initial=True)
def START(self):
self.childs = {}
raise self.WAITING()
@ATMT.state()
def WAITING(self):
pass
@ATMT.receive_condition(WAITING)
if not self.qname[-2].isdigit():
qtype = pkt[DNSQR].sprintf("%qtype%")
@ATMT.action(true_dns_request)
if qtype == "A":
else:
send(reply, verbose=0)
@ATMT.receive_condition(WAITING)
raise self.WAITING().action_parameters(pkt)
@ATMT.action(connection_request)
i = self.get_identifier()
if i is not None:
self.childs[i] = thread
thread.runbg()
class Child(Core):
self.dn = dn
self.con_id = str(con_id)
self.first_pkt = first_pkt
self.ssh_p = ssh_p
Automaton.parse_args(self, debug=dbg)
if len(qname) >= 4:
if qname[-2].isdigit() and qname[-3] == self.con_id:
self.msg_type = qname[-4]
return True
_DONE]:
self.arg = qname[-5]
self.payload = qname[:-5]
return True
return False
len("ns.") - 10
if pkt[DNSQR].qtype == TXT:
max_size = 512
s -= len(str(s))
else:
max_size = self.qname_max_size
if qtype == CNAME:
qname = []
rest = data
d = rest[:limit_size]
self.label_size)]))
rest = rest[limit_size:]
return qname
l.sort()
temp = [[l[0]]]
result = []
j = 0
for i in range(1,len(l)):
if l[i] == l[i-1]+1:
temp[j] += [l[i]]
else:
temp.append([l[i]])
j += 1
for r in temp:
if len(r) > 1:
result.append("{0}-{1}".format(r[0],r[-1]))
else:
result.append(str(r[0]))
return ".".join(result)
@ATMT.state(initial=True)
def START(self):
self.label_size = 63
self.qname_max_size = 253
self.pkt_max_size = 512
self.recv_data = {}
self.ip_client = self.first_pkt[IP].src
self.is_first_wyw_pkt = True
self.iwt_pkt = None
raise self.TICKLING()
@ATMT.state()
def TICKLING(self):
s = socket.socket()
s.connect(("127.0.0.1", self.ssh_p))
ssh_msg = self.stream.recv()
raise self.CON(ssh_msg.load)
@ATMT.state()
if ssh_msg == "":
raise self.TICKLING()
s = self.calculate_limit_size(self.first_pkt)
qtype = self.first_pkt[DNSQR].qtype
if len(self.frag_reply) == 1:
self.con_id, self.frag_reply[0]))
else:
self.con_id, str(len(self.frag_reply)-1)))
send(pkt, verbose=0)
raise self.WAITING()
@ATMT.state()
def WAITING(self):
pass
@ATMT.timeout(WAITING, 600)
def timeout_reached(self):
raise self.END()
@ATMT.receive_condition(WAITING)
pkt_nb = self.arg
if pkt_nb.isdigit():
@ATMT.receive_condition(WAITING)
if self.msg_type == _IWT:
raise self.IWT(pkt)
@ATMT.receive_condition(WAITING)
if self.msg_type == _DATA:
asked_pkt = self.arg
if asked_pkt.isdigit():
@ATMT.receive_condition(WAITING)
if self.msg_type == _DONE:
code = self.arg
@ATMT.state()
def DATA_RECEPTION(self, pkt, pkt_nb):
if not self.recv_data.has_key(pkt_nb):
self.recv_data[pkt_nb] = "".join(self.payload)
if self.msg_type == _ACK:
send(ack_pkt, verbose=0)
raise self.WAITING()
self.fast_pkt = pkt
self.to_ack = [pkt_nb]
@ATMT.receive_condition(DATA_RECEPTION)
if self.msg_type == _FAST:
if self.arg.isdigit():
self.fast_pkt = pkt
pkt_nb = int(self.arg)
if not self.recv_data.has_key(pkt_nb):
self.recv_data[pkt_nb] = "".join(self.payload)
self.to_ack.append(pkt_nb)
@ATMT.timeout(DATA_RECEPTION, 0.5)
def ack(self):
l = self.compress(self.to_ack)
send(ack_pkt, verbose=0)
raise self.WAITING()
@ATMT.state()
After receiving a WYW (What You Want) pkt from the client, the server
"""
send(self.iwt_pkt, verbose=0)
else:
qtype = pkt[DNSQR].qtype
s = self.calculate_limit_size(pkt)
self.frag_reply = self.fragment_data(b64encode(ssh_reply[0].load), s,
qtype)
str(len(self.frag_reply))))
iwt_pkt = self.iwt_pkt
send(iwt_pkt, verbose=0)
raise self.WAITING()
@ATMT.state()
str(asked_pkt), self.frag_reply[-(asked_pkt+1)]))
send(data_pkt, verbose=0)
raise self.WAITING()
@ATMT.state()
if code == _ACK:
if self.recv_data.keys() == range(0,len(self.recv_data)):
d = "".join(self.recv_data.values())
ssh_request = Raw(b64decode(d))
self.stream.send(ssh_request)
self.recv_data.clear()
self.iwt_pkt = None
raise self.WAITING()
@ATMT.state(final=True)
def END(self):
pass
if __name__ == "__main__":
help="Generate the graph of the automaton, save it to /tmp and exit. You will need
default=False)
debug level, where D is an integer between 0 (quiet) and 5 (very verbose). Default
max number of simultaneous clients your server will handle with. Max is 1000.
if opt.graph:
Parent.graph(target="> /tmp/dnscapy_server_parent.pdf")
Child.graph(target="> /tmp/dnscapy_server_child.pdf")
sys.exit(0)
if len(args) != 2:
dn = args[0]
ext_ip = args[1]
log_interactive.setLevel(1)
ssh_p=opt.port)
dnscapy.run()
TShark
TShark es la versión del linea de comandos del sniffer y analizador de protocolos Wireshark.
Ettercap
activas y pasivas de varios protocolos (incluso aquellos cifrados, como SSH y HTTPS).
También hace posible la inyección de datos en una conexión establecida y filtrado al vuelo aun
the-middle(Spoofing).
Fuente: Wikipedia
Snort
Snort es un sniffer de paquetes y un detector de intrusos basado en red (se monitoriza todo un
de sus bitácoras (logs) tanto en archivos de texto como en bases de datos abiertas, como lo es
MySQL.
Fuente: Wikipedia
Dsniff
conmutación).
PKI.
En el ambiente de los desarrolladores del lenguaje Python también se le conoce por el título
BDFL ("Benevolent Dictator for Life'"), teniendo asignada la tarea de fijar las directrices sobre
la evolución de Python, así como la de tomar decisiones finales sobre el lenguaje que todos los
desarrolladores acatan. Van Rossum tiene fama de ser bastante conservador, realizando pocos
Fuente: Wikipedia
PEP
El desarrollo de Python se lleva a cabo en gran medida usando los Python Enhancement
Proposal (PEP). Los PEP son el principal mecanismo para proponer nuevas e importantes
las decisiones de diseño que han entrado en Python. Los PEP pendientes son revisados y
Fuente: Wikipedia
127.0.0.1
En el contexto de redes TCP/IP, localhost es una dirección reservada que hace referencia al
Capa 1
La capa 1 es la primera capa del Modelo OSI. Es la que se encarga de la topología de red y de
las conexiones globales de la computadora hacia la red, se refiere tanto al medio físico como a
Fuente: Wikipedia
Capa 2
En el modelo OSI, esta capa se ocupa del direccionamiento físico, del acceso al medio, de la
detección de errores, de la distribución ordenada de tramas y del control del flujo. Es uno de
los aspectos más importantes que revisar en el momento de conectar dos ordenadores, ya que
está entre la capa 1 y 3 como parte esencial para la creación de sus protocolos básicos (MAC,
IP).
En el modelo TCP/IP, esta es la capa de internet: Internet, semejante a la capa 3 (red) del
modelo OSI.
Fuente: Wikipedia
Capa 7
En modelo OSI, la capa 7 ofrece a las aplicaciones la posibilidad de acceder a los servicios de
las demás capas y define los protocolos que utilizan las aplicaciones para intercambiar datos,
como correo electrónico (Post Office Protocol y SMTP), gestores de bases de datos y servidor
de ficheros (FTP), por UDP pueden viajar (DNS y Routing Information Protocol). Hay tantos
Fuente: Wikipedia
DARPA
Projects Agency, es una agencia del Departamento de Defensa de Estados Unidos responsable
del desarrollo de nuevas tecnologías para uso militar. Fue creada en 1958 como consecuencia
tecnológica de la llamada Guerra Fría, y del que surgieron, década después, los fundamentos
Fuente: Wikipedia
Debugger
Un depurador (en inglés, debugger), es un programa usado para probar y depurar (eliminar) los
errores de otros programas (el programa "objetivo"). El código a ser examinado puede
técnica que permite gran potencia en su capacidad de detenerse cuando son encontradas
condiciones específicas pero será típicamente algo más lento que ejecutando el código
Fuente: Wikipedia
DoD
Defense - DoD) es un departamento del brazo ejecutivo del gobierno federal de Estados Unidos
encargado de coordinar y supervisar todas las agencias y funciones del gobierno relacionadas
directamente con la seguridad nacional y las Fuerzas Armadas de los Estados Unidos.
Fuente: Wikipedia
GNUPlot
Gnuplot puede producir sus resultados directamente en pantalla, así como en multitud de
formatos de imagen, como PNG, EPS, SVG, JPEG, etc. Se puede usar interactivamente o en
modo por lotes (batch), usando scripts. Este programa tiene gran base de usuarios y está
convenientemente mantenido por sus desarrolladores. Existe una ingente cantidad de ayuda en
Fuente: Wikipedia
Localhost
En el contexto de redes TCP/IP, localhost es una dirección reservada que hace referencia al
Locate
locate es un comando del paquete findutils de GNU que provee una fácil y rápida manera de
El comando es mucho más rápido (aunque menos flexible) que find, pues utiliza los datos en
una base de datos temporal que almacena los nombres de todos los archivos en el sistema, por
Fuente: Wikipedia
Syslog
Syslog es un estándar de facto para el envío de mensajes de registro en una red informática IP.
Por syslog se conoce tanto al protocolo de red como a la aplicación o biblioteca que envía los
mensajes de registro.
Fuente: Wikipedia
TCPDump
Permite al usuario capturar y mostrar a tiempo real los paquetes transmitidos y recibidos en la
Fuente: Wikipedia
Verbose
mostrará por los canales destinados a ello, normalmente la linea de comandos o el log del
sistema.
VLAN
Una VLAN, acrónimo de virtual LAN (red de área local virtual), es un método para crear
Fuente: Wikipedia
Wrapper
CLI
método que permite a los usuarios dar instrucciones a algún programa informático por medio
Fuente: Wikipedia
TShark
TShark es la versión del linea de comandos del sniffer
Índice
Capítulo 2 - Lectura de ficheros PCAP
Ettercap
Ettercap es un interceptor/sniffer/registrador para LANs con switch.
middle(Spoofing).
Fuente: Wikipedia
Índice
Capítulo 2 - Lectura de ficheros PCAP
Snort
Snort es un sniffer de paquetes y un detector de intrusos basado en red
lo es MySQL.
previamente definida.
Fuente: Wikipedia
Índice
Capítulo 2 - Lectura de ficheros PCAP
Dsniff
Dsniff es una colección de herramientas de auditoría de red y pruebas
WebSpy.
Índice
Capítulo 2 - Lectura de ficheros PCAP
Guido Van Rossum
Guido van Rossum es un científico de la computación, conocido por
Países Bajos.
Fuente: Wikipedia
Índice
Capítulo 3 - Scapy y Multithreading
PEP
El desarrollo de Python se lleva a cabo en gran medida usando los
Fuente: Wikipedia
Índice
Capítulo 3 - Scapy y Multithreading
127.0.0.1
En el contexto de redes TCP/IP, localhost es una
en IPv4.
Índice
Capítulo 1 - Construcción de paquete básico
Capa 1
La capa 1 es la primera capa del Modelo OSI. Es la que se encarga de
se transmite la información.
Fuente: Wikipedia
Índice
Capítulo 1 - Construcción de paquete básico
Capa 2
En el modelo OSI, esta capa se ocupa del direccionamiento físico, del
que está entre la capa 1 y 3 como parte esencial para la creación de sus
Fuente: Wikipedia
Índice
Capítulo 1 - Construcción de paquete básico
Capa 7
En modelo OSI, la capa 7 ofrece a las aplicaciones la posibilidad de
acceder a los servicios de las demás capas y define los protocolos que
Fuente: Wikipedia
Índice
Capítulo 2 - Pila TCP/IP Y Layers en Scapy
DARPA
La Agencia de Proyectos de Investigación Avanzados de Defensa,
Fuente: Wikipedia
Índice
Capítulo 2 - Pila TCP/IP Y Layers en Scapy
Debugger
Un depurador (en inglés, debugger), es un programa usado para probar
mismo) procesador.
Fuente: Wikipedia
Índice
Capítulo 1 - Construcción de paquete básico
DoD
El Departamento de Defensa de Estados Unidos (del inglés: United
Fuente: Wikipedia
Índice
Capítulo 2 - Pila TCP/IP Y Layers en Scapy
GNUPlot
Gnuplot es un programa muy flexible para generar gráficas de
funciones y datos.
Fuente: Wikipedia
Índice
Capítulo 1 - ¿Qué es Scapy?
Localhost
En el contexto de redes TCP/IP, localhost es una
dispositivo o computadora.
Índice
Capítulo 2 - Parámetros de los layers
Locate
locate es un comando del paquete findutils de GNU que provee una
en patrones de nombres.
pues utiliza los datos en una base de datos temporal que almacena los
Fuente: Wikipedia
Índice
Capítulo 2 - Creación de un nuevo layer
Syslog
Syslog es un estándar de facto para el envío de mensajes de registro en
una red informática IP. Por syslog se conoce tanto al protocolo de red
Fuente: Wikipedia
Índice
Capítulo 3 - Logging remoto con syslog y scapy
TCPDump
Tcpdump es un herramienta en línea de comandos cuya utilidad
Fuente: Wikipedia
Índice
Capítulo 1 - ¿Qué es Scapy?
Verbose
El término verbose hace referencia al nivel de
Índice
Capítulo 2 - Modos de Envío
VLAN
Una VLAN, acrónimo de virtual LAN (red de área local virtual), es un
red física
Fuente: Wikipedia
Índice
Capítulo 2 - Layers más usados
Wrapper
En computación, un wrapper hace referencia a la
Índice
Capítulo 1 - El modo interactivo
CLI
La interfaz de línea de comandos, traducción del inglés command-line
texto simple.
Fuente: Wikipedia
Índice
Capítulo 1 - ¿Qué es Scapy?