Cargando



Crear un SYN scan con Python y Scapy

Te enseño cómo realizar tu propio escáner SYN de una manera sencilla utilizando Python y Scapy


jun 13 2016 12:44
Avanzado
jun 30 2016 16:45

En este tutorial te voy a enseñar a realizar un escáner de puertos TCP SYN scan, para ello voy a utilizar Python con la librería Scapy.

 

Para instalar Python puedes ver el siguiente tutorial. Y para instalar la librería Scapy para Python pincha en el siguiente botón:

 

 

Conociendo qué es un SYN scan
SYN scan es una técnica de exploración que también se conoce como exploración entre abierta y que es usada por los hackers para determinar el estado de los puertos sin establecer una conexión completa. También es posible utilizar esta técnica para llevar a cabo ataques DDOS (ataques de denegación de servicio).

 

Nota
Está dirigido a enseñar cómo funcionan este tipo de programas y que puedas testear tus puertos, pero no para utilizarlo maliciosamente.

 

Vamos a empezar con el escáner de puertos.

 

Paso 1

Lo primero que hacemos es importar las librerías que necesitamos.
import logging
logging.getLogger("scapy.runtime").setLevel(logging.ERROR) 
from scapy.all import *
Importamos scapy a nuestro programa, además he importado logging para hacer que no nos muestre un warning molesto si no tenemos dirección IPv6.

 

Paso 2

Un paso que sirve para iniciar nuestras variables.
conf.verb = 0
listaPuertos = list(range(20,130)) 
host = "192.168.0.1"
La primera instrucción de este paso hace una pequeña configuración para que no nos muestre por pantalla la información de Scapy. Las siguientes solo añadimos los puertos y el host, dónde ejecutaremos la acción, sería una mejor opción agregarla como parámetros a la hora de ejecutar el programa, (si te interesa agregarlo para tu programa consulta este link), para facilitar el programa y que sea más corto aquí se mete a mano.

 

Paso 3

Este paso es el núcleo del programa.
print("Escaneando los puertos de la IP:",host)
for puerto in listaPuertos:
    puertoOrigen = RandShort()
    paquete = IP(dst = host)/TCP(sport = puertoOrigen, dport = puerto, flags = "S")
    respuesta = sr1(paquete, timeout = 2)
    if("NoneType" in str(type(respuesta))):
        pass
    elif(respuesta.haslayer(TCP) and respuesta.getlayer(TCP).flags == 0x12):
        p = IP(dst = host)/TCP(sport = puertoOrigen, dport = puerto, flags = "R")
        rst = sr(p, timeout = 1)
        try:
            servicio = socket.getservbyport(puerto)
        except:
            servicio = "¿?"
        print("[ABIERTO]",puerto," ->",servicio)
En esta parte es dónde se inicia el escaneo de puertos, mostramos un mensaje para que sepamos que se está trabajando, y a través del for recorremos cada puerto. Utilizamos la función RandShort() para que el paquete que se envíe tenga como origen un puerto distinto cada vez.

 

La construcción del paquete se hace con la segunda instrucción que se encuentra en el for. Configuramos los datos que nos interesa, la IP destino para la capa IP, el puerto origen y destino y las flags para TCP, en este caso se trata de un escáner SYN, por eso está la S, cambiando este parámetro podrás hacer otro tipo de escáner, cómo un FIN scan o un window scan (pero ten en cuenta que tendrás que cambiar las condiciones que aparecen abajo).

 

La función sr1 es la encargada de enviar el paquete. La tenemos que pasar como argumento el paquete creado (en esta ocasión se crea directamente aquí), y en este caso he puesto un máximo de espera de 2 segundos, puedes cambiarlo, solo que si no lo indicas se puede volver infinito tu programa. El resultado de enviar el paquete se guarda en la variable respuesta.

 

En las condiciones nos interesa saber si tenemos una respuesta y si tiene activadas las flags SYN y ACK (por eso usamos 0x12), si no usáramos antes del and respuesta.haslayer(TCP), si no tiene la capa nos saltará una excepción. Si cumple está condición enviaremos un mensaje con la flag RST activa para cortar la conexión. La parte del try... catch la puedes ignorar, lo único que hace es sacar el servicio que se usa en ese puerto para mostrar más información por pantalla (la función socket.getservbyport(puerto) si es un puerto conocido nos devolverá información, si no lanzará una excepción y si ocurre esto he optado por poner ¿? como "información", cómo indicación de no conocido.)

 

Bueno pues ya hemos terminado, en la siguiente imagen puedes ver la salida de la ejecución del escáner:

 

SynScan.jpg

 

A continuación pongo el código completo:

import logging
logging.getLogger("scapy.runtime").setLevel(logging.ERROR) # Que no muestre warning
from scapy.all import *

conf.verb = 0 #Que no muestre datos en pantalla
listaPuertos = list(range(20,130)) #La lista de puertos a escanear
host = "192.168.0.1" #Aquí la IP que quieres escánear

print("Escaneando los puertos de la IP:",host)
for puerto in listaPuertos:
    puertoOrigen = RandShort()
    paquete = IP(dst = host)/TCP(sport = puertoOrigen, dport = puerto, flags = "S")
    respuesta = sr1(paquete, timeout = 2)
    if("NoneType" in str(type(respuesta))):
        pass
    elif(respuesta.haslayer(TCP) and respuesta.getlayer(TCP).flags == 0x12):
        p = IP(dst = host)/TCP(sport = puertoOrigen, dport = puerto, flags = "R")
        rst = sr(p, timeout = 1)
        try:
            servicio = socket.getservbyport(puerto)
        except:
            servicio = "¿?"
        print("[ABIERTO]",puerto," ->",servicio)
[color=rgb(169,169,169)]Código completo[/color]

 

Nota
Este escáner puede ser lento para comprobar muchos puertos, para esos casos es buena idea usar “mulltithreading” o “multiprocessing ”. También puedes realizar el escáner de otras formas, usando nmap dentro de Python o usando raw sockets.

 

Y por si quieres descargar el código, adjunto un zip:

 

Código
Fichero Adjunto  SynScan.zip   644 bytes   357 Descargas


¿Te ayudó este Tutorial?


1 Comentarios

Que bueno que exista scapy, nos ayuda mucho

No esperes más y entra en Solvetic
Deja tus comentarios y aprovecha las ventajas de la cuenta de usuario ¡Únete!

X