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:
Vamos a empezar con el escáner de puertos.
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.
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.
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:
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]
Y por si quieres descargar el código, adjunto un zip:
Que bueno que exista scapy, nos ayuda mucho