Guest gnoo Posted April 3, 2019 Share Posted April 3, 2019 (edited) 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. Edited April 8, 2019 by gnoo Quote Link to post Share on other sites
jorgegustavo 0 Posted June 23, 2020 Share Posted June 23, 2020 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. Quote Link to post Share on other sites
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.