Guest gnoo Posted April 3, 2019 at 08:13 PM Share Posted April 3, 2019 at 08:13 PM Saudações, eu algum tempo atrás fiz um script em python com o objetivo de fazer scan ARP na minha LAN para efeitos educacionais... e não só ?️ ... E decidi partilhar aqui esse script para quem quer tirar umas ideias .... E aqueles que quiserem dar umas sugestões de melhoria do código podem comentar para trocar umas ideias, para que eu possa também aprender coisas novas. O scan ARP pode ser interessante em várias situções, uma delas é quando queremos fazer um scan na nossa rede, e por alguma razão outros hosts ativos na rede podem estar a bloquear pacotes ICMP, não ter portas abertas no sistema para fazer scan através de handshake. Acho que o mais interessante disto tudo é perceber como um scan ARP funciona... Então nós sabemos que o nosso sistema para iniciar conversação com outro host na rede, precisa do endereço físico desse host ( MAC ADDRESS ), é ai que entra o protocolo ARP, para fazer a resolução de endereço do host que nós queremos comunicar com base no endereço de IP que temos, fazendo um broadcast ( pergunta de um para todos ), para todos os elementos estão ligados à rede, depois é nos devolvido uma resposta em Unicast ( resposta de um para um ) do host com o IP com o qual nos queremos comunicar. Então um scan ARP consiste em criar uma sequência de ip's, percorrer essa sequência de ip's num ciclo de repetição, a cada iteração desse ciclo de repetição criar um frame ethernet, criar um pacote ARP, adicionar o pacote ARP à carga do frame ethernet e enviar esse frame. No meu caso eu criei dois sockets um para enviar o pacote e outro para ficar em "escuta" de frames ethernet, analisando o seu tipo de ethernet... se o tipo for ARP analisamos a carga desse frame, e tentamos perceber se o tipo de operação do pacote que chega é 2, se essa condição for verdadeira então analisamos o ip de quem envia e o respetivo endereço fisico ( MAC ADDRESS ), e realizamos a saida de dados. ATENÇÂO: o script que segue deve ser melhorado especialmente na função em que é feita a iteração e o empacotamento uma vez que o seu tempo de execução está a demorar em média 8 a 10 segundos, deve ser aplicado um sistema de threads nessa função. O código que segue percisa de configurações... é necessário configurar o nome da placa de rede no socket que envia pacotes, tal como dados necessário para o pacote ARP SEGUE SCRIPT: #!/usr/bin/env python3 from socket import * import struct import binascii from ipaddress import IPv4Network import signal import sys import threading # Esta class serve para fazer o pacote ARP class Pacote_Arp(object): def __init__(self): self.tipo_hardware = None self.tipo_protocolo = None self.len_hardware = None self.len_protocolo = None self.operacao = None self.mac_src = None self.src_ip = None self.mac_dest = None self.dest_ip = None self.protocolo = None class Gestor_Pacotes(object): def __init__(self, socket_family, socket_type, protocolo, cabecalho_arp): self.socket_family = socket_family self.socket_type = socket_type self.protocolo = ntohs(protocolo) self.lista_ip = IPv4Network('192.168.1.0/24') self.cabecalho_arp = cabecalho_arp def Mac_unhexlify(self): mac_dest_byte_order = binascii.unhexlify(self.cabecalho_arp.mac_dest.replace(":", "")) mac_src_byte_order = binascii.unhexlify(self.cabecalho_arp.mac_src.replace(":", "")) return mac_dest_byte_order, mac_src_byte_order def Empacotamento_Frame_ArpHeader(self, ip): src_ip = inet_aton(self.cabecalho_arp.src_ip) self.cabecalho_arp.dest_ip = ip dest_ip = inet_aton(str(ip)) mac_dest_byte_order, mac_src_byte_order = self.Mac_unhexlify() frame = struct.pack("!6s6sH", mac_dest_byte_order, mac_src_byte_order, self.cabecalho_arp.protocolo) arp_header = struct.pack("!HHBBH6s4s6s4s", self.cabecalho_arp.tipo_hardware, self.cabecalho_arp.tipo_protocolo, self.cabecalho_arp.len_hardware, self.cabecalho_arp.len_protocolo, self.cabecalho_arp.operacao, mac_src_byte_order, src_ip, mac_dest_byte_order, dest_ip) return frame + arp_header def desempacotamento_header_arp(self,payload): (tipo_hardware, tipo_protocolo, tamanho_endereco_hardware, tamanho_endereco_protocolo, operacao, mac_sender, ip_sender, mac_dest, ip_dest) = struct.unpack("!HHBBH6s4s6s4s", payload) return tipo_hardware, tipo_protocolo, tamanho_endereco_hardware, + \ tamanho_endereco_protocolo, operacao, mac_sender, ip_sender, mac_dest, ip_dest def byte_to_hex_mac(self, mac_em_bytes): endereco = binascii.hexlify(mac_em_bytes).decode("ascii") return ":".join([endereco[i:i+2] for i in range(0,12,2)]) def desempacotamento_ethernet_frame(self,raw_dados): mac_destino, mac_fonte, tipo_ethernet = struct.unpack('! 6s 6s H', raw_dados[:14]) return tipo_ethernet, raw_dados[14:] def send_broadcast(self, pacote_broadcast): self.sock = socket(self.socket_family, self.socket_type, self.protocolo) self.sock.settimeout(0.3) self.sock.bind(("< PLACA DE REDE >",htons(0x0806))) self.sock.send(pacote_broadcast) self.sock.close() def recv_unicast(self): self.sock2 = socket(AF_PACKET, SOCK_RAW, ntohs(0x0003)) try: while True: raw_dados, addr = self.sock2.recvfrom(65536) if raw_dados: tipo_ethernet, payload = self.desempacotamento_ethernet_frame(raw_dados) if tipo_ethernet == 2054: (tipo_hardware, tipo_protocolo, tamanho_endereco_hardware,tamanho_endereco_protocolo, operacao, mac_sender, ip_sender, mac_dest, ip_dest) = self.desempacotamento_header_arp(payload[:28]) if operacao == 2: print("Host: {} MAC: {} Hostname: {}".format(inet_ntoa(ip_sender), self.byte_to_hex_mac(mac_sender),getfqdn(inet_ntoa(ip_sender)))) except: pass # Gera pacotes com um ip diferente a cada iteração enviando esse pacote def for_loop_gera_pacote(): for ip_em_lista in GestorPacotes.lista_ip: pacote = GestorPacotes.Empacotamento_Frame_ArpHeader(ip = ip_em_lista) GestorPacotes.send_broadcast(pacote) def InterrompePrograma_CTRL_C(signal, frame): print("Programa interrompido pelo utilizador") sys.exit(0) if __name__ == '__main__': ##### AQUI SÂO INSERIDOS OS DADOS DO PACOTE ############### Arp = Pacote_Arp() Arp.tipo_hardware = 1 Arp.tipo_protocolo = 0x0800 Arp.len_hardware = 6 Arp.len_protocolo = 4 Arp.operacao = 1 Arp.mac_src = '' Arp.src_ip = '' Arp.mac_dest = 'ff:ff:ff:ff:ff:ff' Arp.protocolo = 0x0806 ##################################################### GestorPacotes = Gestor_Pacotes(socket_family = PF_PACKET, socket_type = SOCK_RAW , protocolo = 0x0806, cabecalho_arp = Arp) # Termina programa quando CTRL + C signal.signal(signal.SIGINT, InterrompePrograma_CTRL_C) # Esta thread """ Permite a execução do metodo recv_unicast da class Gestor_Pacotes, em simultaneo com a função for_loop_gera_pacote, o que nos permite que esse método fique em escuta enquanto empacotamos e fazemos o envio do pacotes em broadcast, podendo assim receber as respostas """ processo = threading.Thread( target = GestorPacotes.recv_unicast) # É necessário para que seja possivel sair do programa após a função for_loop_gera_pacote terminar processo.daemon = True processo.start() for_loop_gera_pacote() sys.exit(0) Abraço. Link to comment Share on other sites More sharing options...
jorgegustavo Posted June 23, 2020 at 10:47 PM Share Posted June 23, 2020 at 10:47 PM Boa Noite a todos, Estava procurando um script em Python que, a partir do MAC Address ou IP (ou os 2) pudesse me dar o Switch e a porta desse Switch onde estaria conectado fisicamente um determinado dispositivo ou vários deles, para uma rede LAN bem maior, em VLAN específica e guardar esses resultados em um .csv ou .xlx/.xlsx. Até tenho um script que me dá em planilha um teste de ping, dizendo qual IP respondeu Ok e qual apresenta erro. Link to comment Share on other sites More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.