2017-06-01 1 views
2

j'ai suivi le tutoriel ci-dessous pour mettre en œuvre un renifleur de paquets en Python:Sniff et envoyer le trafic UDP à l'aide Scapy

http://www.binarytides.com/python-packet-sniffer-code-linux/

Sur réception de chaque paquet UDP, je voudrais envoyer un fichier pcap déjà enregistré (test .pcap). L'extrait suivant montre mon implémentation:

# receive a packet 
while True: 
    packet = s.recvfrom(65565) 

    #packet string from tuple 
    packet = packet[0] 

    #parse ethernet header 
    eth_length = 14 

    eth_header = packet[:eth_length] 
    eth = unpack('!6s6sH' , eth_header) 
    eth_protocol = socket.ntohs(eth[2]) 
    print 'Destination MAC : ' + eth_addr(packet[0:6]) + ' Source MAC : ' + 
    eth_addr(packet[6:12]) + ' Protocol : ' + str(eth_protocol) 

    if eth_addr(packet[6:12]) != my_MAC_address: 

     #Parse IP packets, IP Protocol number = 8 
     if eth_protocol == 8 : 
     #Parse IP header 
     #take first 20 characters for the ip header 
     ip_header = packet[eth_length:20+eth_length] 

     #now unpack them :) 
     iph = unpack('!BBHHHBBH4s4s' , ip_header) 

     version_ihl = iph[0] 
     version = version_ihl >> 4 
     ihl = version_ihl & 0xF 

     iph_length = ihl * 4 

     ttl = iph[5] 
     protocol = iph[6] 
     s_addr = socket.inet_ntoa(iph[8]); 
     d_addr = socket.inet_ntoa(iph[9]); 

     print 'Version : ' + str(version) + ' IP Header Length : ' + str(ihl) + ' TTL : ' + str(ttl) + ' Protocol : ' + str(protocol) + ' Source Address : ' + str(s_addr) + ' Destination Address : ' + str(d_addr) 


     #UDP packets 
     if protocol == 17 : 
     u = iph_length + eth_length 
     udph_length = 8 
     udp_header = packet[u:u+8] 

     #now unpack them :) 
     udph = unpack('!HHHH' , udp_header) 

     source_port = udph[0] 
     dest_port = udph[1] 
     length = udph[2] 
     checksum = udph[3] 

     print 'Source Port : ' + str(source_port) + ' Dest Port : ' + str(dest_port) + ' Length : ' + str(length) + ' Checksum : ' + str(checksum) 

     h_size = eth_length + iph_length + udph_length 
     data_size = len(packet) - h_size 

     #get data from the packet 
     data = packet[h_size:] 

     print 'Data : ' + data 
     my_pkt = rdpcap("test.pcap") 
     sendp(my_pkt) 

Test.pcap contient un paquet UDP avec UDP_src = 7777 et UDP_dest = 9999.

Le trafic est généré à l'aide netcat comme suit:

nc -u -p 7777 ip_dst_addr 9999 

Le renifleur ne peut recevoir que d'abord netcat msg et envoyer test.pcap en réponse. Mais les msg ultérieurs de netcat ne sont pas du tout reçus. Cependant, en utilisant n'importe quelle autre combinaison de ports UDP dans netcat, le sniffer fonctionne bien. Par exemple: netcat en cours d'exécution comme:

nc -u -p 8888 ip_dst_addr 9999 

il n'y a pas de problème et je suis en mesure d'envoyer test.pcap en réponse à chaque paquet UDP/msg.

Toute aide serait grandement appréciée!

Répondre

2

Scapy a plusieurs renifleurs intégrés, qui sont vraiment faciles à utiliser.

>>> help(sniff) 
Help on function sniff in module scapy.arch.windows.compatibility: 

sniff(count=0, store=1, offline=None, prn=None, stop_filter=None, lfilter=None, L2socket=None, timeout=None, *arg, **karg) 
    Sniff packets 
    sniff([count=0,] [prn=None,] [store=1,] [offline=None,] [lfilter=None,] + L2ListenSocket args) -> list of packets 
    Select interface to sniff by setting conf.iface. Use show_interfaces() to see interface names. 
     count: number of packets to capture. 0 means infinity 
     store: whether to store sniffed packets or discard them 
     prn: function to apply to each packet. If something is returned, 
      it is displayed. Ex: 
      ex: prn = lambda x: x.summary() 
    filter: provide a BPF filter 
    lfilter: python function applied to each packet to determine 
      if further action may be done 
      ex: lfilter = lambda x: x.haslayer(Padding) 
    offline: pcap file to read packets from, instead of sniffing them 
    timeout: stop sniffing after a given time (default: None) 
    L2socket: use the provided L2socket 
    stop_filter: python function applied to each packet to determine 
       if we have to stop the capture after this packet 
       ex: stop_filter = lambda x: x.haslayer(TCP) 

Ce qui signifie que vous pouvez simplement faire:

packets = rdpcap("test.pcap") 
sniff(lfilter=lambda x: x.haslayer(UDP) and x[Ether].src==sending_mac and x[UDP].sport==port, prn=lambda x: send(packets)) 

Ceci ajoutera tous les paquets UDP dans le fichier test.pcap

+0

Merci, votre mise en œuvre est beaucoup plus simple. Mais le problème persiste que sniffer ne peut pas renifler les paquets lorsque nous envoyons test.pcap en utilisant les mêmes ports udp que dans le msg client. :/ – user112333

+0

Voulez-vous renifler les paquets que vous avez envoyés? Sinon, cela devrait fonctionner:/Ne comprends pas vraiment votre problème – Cukic0d

+0

Je ne veux pas renifler les pkts sortants dans le renifleur. C'est pourquoi il y a la condition if suivante: si eth_addr (paquet [6:12])! = My_MAC_address Il existe deux types de paquets: 1) demandes que je voudrais renifler. Il peut être généré en utilisant netcat. Disons UDP_src = 7777 et UDP_dst = 9999 2) réponse qui dans notre cas est test.pcap. Je ne veux pas renifler les paquets de réponse. test.pcap contient un paquet UDP avec UDP_src = 7777 et UDP_dst = 9999 A la réception de la première requête, je peux envoyer test.pcap. Mais par la suite il ne peut pas renifler les paquets avec UDP_src = 7777 et UDP_dst = 9999 – user112333