web-dev-qa-db-fra.com

Envoi de paquets depuis pcap avec src/dst modifié en scapy

J'essaie d'envoyer un trafic enregistré précédemment (capturé au format pcap) avec scapy. Actuellement, je suis coincé dans la couche d'éther d'origine. Le trafic a été capturé sur un autre hôte et je dois fondamentalement changer à la fois les couches src et dst des couches Ether et Ether. J'ai réussi à remplacer la couche IP et à recalculer les sommes de contrôle, mais la couche Ether me pose problème.

Quelqu'un a-t-il de l'expérience dans l'envoi de paquets à partir d'un fichier de capture avec les modifications appliquées aux couches IP et Ether (src et dst)? En outre, la capture est plutôt un gros couple de Gb, que diriez-vous des performances de scapy avec une telle quantité de trafic?

17
Jason Bart

vérifier cet exemple

from scapy.all import *
from scapy.utils import rdpcap

pkts=rdpcap("FileName.pcap")  # could be used like this rdpcap("filename",500) fetches first 500 pkts
for pkt in pkts:
     pkt[Ether].src= new_src_mac  # i.e new_src_mac="00:11:22:33:44:55"
     pkt[Ether].dst= new_dst_mac
     pkt[IP].src= new_src_ip # i.e new_src_ip="255.255.255.255"
     pkt[IP].dst= new_dst_ip
     sendp(pkt) #sending packet at layer 2

commentaires:

  • utilisez les méthodes rdpcap, wrpcap scapy pour lire et écrire à partir d'un fichier au format pcap
  • vous pouvez utiliser sniff(offline="filename") pour lire les paquets et vous pouvez utiliser le paramètre prn comme ceci sniff(offline="filename",prn=My_Function) dans ce cas, My_Functions sera appliqué à chaque commande sniffée
  • la bonne façon d'écrire votre nouvel ip ou mac est de le considérer comme une chaîne ex: ip="1.1.1.1" et ainsi de suite, comme illustré ci-dessus.
  • dans l'exemple: méthode sendp incluse dans la boucle for, ce qui est plus lent que la création d'une autre boucle pour envoyer des paquets
  • conseil de performance: en python, l’utilisation des boucles for est trop lente, utilisez map à la place si vous souhaitez une vitesse semblable à celle d’une boucle for en C, Ref
  • le rdpcap, tel qu'utilisé ci-dessus, lit le fichier en une fois. Si la mémoire disponible pendant la lecture indique 1,5 Go et que vous lisez un fichier de 2,3, .. Go, il échouera.
  • si le problème de performance est critique pour vous, vous pouvez utiliser winpcap mais vous devez écrire du code plus complexe en C; effectuer la même tâche avec python/scapy est assez simple, mais il n’est pas plus rapide que c
  • cela dépend de laquelle utiliser sur le niveau de performance nécessaire 
  • si mon hypothèse est correcte, vous envoyez un paquet de flux vidéo dans ce cas, je voudrais utiliser un winpcap si j'envoie une vidéo de 1 méga pixel ou un scapy dans d'autres cas (taille inférieure par image)
  • en cas d'utilisation de C/winpcap, vous obtiendrez de grandes performances en lecture de pcaps, en modifiant les données et en le renvoyant, mais vous devez être conscient du même problème (fichiers volumineux), vous devez créer un tampon de taille appropriée pour pouvoir l'utiliser. lire l'envoi des paquets dans une assez bonne performance
  • si la taille du paquet est constante (ce qui est rare dans la plupart des cas, je suppose), vous pouvez avoir un avantage à tirer le meilleur parti de votre mémoire disponible 
  • si vous voulez utiliser python/scapy pour l'ensemble du "projet/programme", vous pouvez créer les fonctions hautes performances dans C/Wincap et les compiler en dll, puis importer cette dll dans votre programme python et l'utiliser dans un programme python. . De cette façon, vous bénéficiez des avantages de python/Scapy, très simple et convivial, et vous n’écrivez que des fonctions spécifiques en c, ce qui vous permet d’accomplir votre travail plus rapidement et de faire en sorte que votre code soit facile à gérer et à maintenir. 
24
Abdurahman

Si j'étais vous, je laisserais Scapy s'occuper de la couche Ether et utiliser la fonction send(). Par exemple:

ip_map = {"1.2.3.4": "10.0.0.1", "1.2.3.5": "10.0.0.2"}
for p in PcapReader("filename.cap"):
    if IP not in p:
        continue
    p = p[IP]
    # if you want to use a constant map, only let the following line
    p.src = "10.0.0.1"
    p.dst = "10.0.0.2"
    # if you want to use the original src/dst if you don't find it in ip_map
    p.src = ip_map.get(p.src, p.src)
    p.dst = ip_map.get(p.dst, p.dst)
    # if you want to drop the packet if you don't find both src and dst in ip_map
    if p.src not in ip_map or p.dst not in ip_map:
        continue
    p.src = ip_map[p.src]
    p.dst = ip_map[p.dst]
    # as suggested by @AliA, we need to let Scapy compute the correct checksum
    del(p.chksum)
    # then send the packet
    send(p)
6
Pierre

Eh bien, avec scapy je suis venu avec ce qui suit (désolé pour mon python). Espérons que cela aidera quelqu'un. Il y avait un scénario plus simple possible dans lequel tous les paquets du fichier pcap sont lus en mémoire, mais cela pourrait entraîner des problèmes avec les gros fichiers de capture.

from scapy.all import *
global src_ip, dst_ip
src_ip = 1.1.1.1
dst_ip = 2.2.2.2
infile = "dump.pcap"

try:
    my_reader = PcapReader(infile)
    my_send(my_reader)
except IOError:
    print "Failed reading file %s contents" % infile
    sys.exit(1)

def my_send(rd, count=100):
    pkt_cnt = 0
    p_out = []

    for p in rd:
        pkt_cnt += 1
        np = p.payload
        np[IP].dst = dst_ip
        np[IP].src = src_ip
        del np[IP].chksum
        p_out.append(np)
        if pkt_cnt % count == 0:
            send(PacketList(p_out))
            p_out = []

    # Send remaining in final batch
    send(PacketList(p_out))
    print "Total packets sent %d" % pkt_cn
5
Jason Bart

Pour que la somme de contrôle soit correcte, j’avais également besoin d’ajouter del p[UDP].chksum

0
Catalina