Curso-lenguaje-python/python-ofensivo/14_escaner_red_ICMP/network_scaner.py
2024-01-28 16:06:28 +01:00

203 lines
4.5 KiB
Python

# /usr/bin/env python3
"""
Escaner de red ICMP
"""
import argparse
import ipaddress
import re
import signal
import subprocess
from concurrent.futures import ThreadPoolExecutor
from termcolor import colored
def def_handler(sig, frame):
print(colored(
"\n\n[!] Saliendo del programa...\n", "blue")
)
exit(1)
signal.signal(signal.SIGINT, def_handler)
def get_arguments():
"""
Obtiene los argumentos de la linea de comandos
"""
parser = argparse.ArgumentParser(description="Escaner de red ICMP")
parser.add_argument(
"-t", "--target",
required=True, dest="target",
help="Host o rango de red a escanear"
)
args = parser.parse_args()
return args.target
def validar_ip(target_str):
"""
Valida si el target es una IP o un rango de IPs
"""
# Verificar si es un rango de IPs
rango_match = re.match(
r'^(\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3})-(\d{1,3})$', target_str)
if rango_match:
ip_inicio = rango_match.group(1)
ip_fin = int(rango_match.group(2))
try:
# Convertir la IP de inicio a un objeto ipaddress
ipaddress.IPv4Address(ip_inicio)
# Verificar que el rango sea válido
if 0 <= ip_fin <= 255:
# Crear un objeto ipaddress para la IP de inicio
inicio = ipaddress.IPv4Address(ip_inicio)
# Crear un objeto ipaddress para la IP de fin
fin = ipaddress.IPv4Address(
ip_inicio.rsplit('.', 1)[0] + '.' + str(ip_fin)
)
# Verificar que la IP de inicio sea menor que la IP de fin
if inicio < fin:
print(colored(
f"\n[+] Escaneando el rango de IPs: {inicio} - {fin}",
"blue")
)
rango_ips = ipaddress.summarize_address_range(inicio, fin)
return rango_ips
else:
print(colored(
"\n[!] Error: El rango debe ser de menor a mayor",
"red")
)
return False
else:
print(colored(
"\n[!] Error: El rango especificado no es válido",
"red")
)
return False
except ipaddress.AddressValueError:
print(colored(
"\n[!] Error: El rango especificado no son IPs válidas",
"red")
)
return False
else:
# Si no es un rango, verificar si es una IP individual
try:
ipaddress.IPv4Address(target_str)
print(colored(
f"\n[+] Escaneando IP: {target_str}", "blue")
)
return target_str
except ipaddress.AddressValueError:
print(colored(
"\n[!] Error: El target especificado no es una IP válida",
"red")
)
return False
def parse_target(target_str):
"""
Parsea el target y devuelve una lista de IPs
"""
if "-" in target_str:
ip_list = target_str.split('-')
ip_inicio = ip_list[0]
ip_fin = int(ip_list[1])
inicio = ipaddress.IPv4Address(ip_inicio)
fin = ipaddress.IPv4Address(
ip_inicio.rsplit('.', 1)[0] + '.' + str(ip_fin)
)
ips_return = []
for ip in range(int(ip_inicio.split('.')[3]), ip_fin + 1):
ip_address = ip_inicio.rsplit('.', 1)[0] + '.' + str(ip)
ips_return.append(ip_address)
return ips_return
else:
# Si target_str es una IP individual, crear una lista con esa IP
target_list = [target_str]
return target_list
def host_discovwery(target):
try:
ping = subprocess.run(
["ping", "-c", "1", target],
timeout=1, stdout=subprocess.DEVNULL
)
if ping.returncode == 0:
print(colored(
f"[+] {target} está activo", "green")
)
except subprocess.TimeoutExpired:
pass
def main():
"""
Funcion principal
"""
target_str = get_arguments()
if not validar_ip(target_str):
print(colored(
"\n[!] Introduce un target válido", "red")
)
return
targets = parse_target(target_str)
with ThreadPoolExecutor(max_workers=50) as executor:
executor.map(host_discovwery, targets)
if __name__ == "__main__":
main()