Sending packets from pcap with changed src/dst in scapy Sending packets from pcap with changed src/dst in scapy python python

Sending packets from pcap with changed src/dst in scapy


check this example

from scapy.all import *from scapy.utils import rdpcappkts=rdpcap("FileName.pcap")  # could be used like this rdpcap("filename",500) fetches first 500 pktsfor 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

comments:

  • use rdpcap,wrpcap scapy methods to read and write from pcap formatted file
  • you can use sniff(offline="filename") to read packets and you may use prn parameter like this sniff(offline="filename",prn=My_Function) in this case My_Functions will be applied to every pkt sniffed
  • the correct way to write your new ip or mac is to consider it as a string ex: ip="1.1.1.1" and so on as illustrated above.
  • in example: sendp method included in for loop which is slower than making other loop to send packets
  • performance tip: in python using for loops is too slow use map instead if you would like a speed like a for loop in C ,Ref
  • the rdpcap as used above reads the file at once, if the memory available while reading say 1.5 Gb and you are reading a 2,3,.. Gb file it will fail.
  • if the performance issue is critical for you may use winpcap but you have to write more complex code in C;doing the same task using python/scapy is pretty easy an simple but it is not faster than c
  • it depends which one to use on the level of performance needed
  • if my guess is right you are sending a video stream packets in this case i would use a winpcap if i am sending an 1 mega pixel video or scapy in other cases(lower size per frame)
  • in case of using C/winpcap you will get a great performance in reading pcaps and change the data and resend but you have to be aware of the same problem (large files) you have to create a buffer with a proper size to use it for reading sending the packets in a quite performance
  • if the packet size is constant(which is rare in most cases, i guess) you may have an advantage get the most of your available memory
  • if you want to use python/scapy for the whole "project/program" you may create the high performance functions in C/Wincap and compile as dll then you can import this dll to your python program and you can use it inside a python program. This way you get benefits of wonderful easy python/Scapy and you only write a specific functions in c so you can get your job done faster and your code to be focused and maintainable


If I were you, I would let Scapy deal with the Ether layer, and use the send() function. For example:

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)


Well, with scapy I came up with the following (sorry for my Python). Hopefully it will help someone. There was a possible simpler scenario where all packets from pcap file are read into memory, but this could lead to problems with large capture files.

from scapy.all import *global src_ip, dst_ipsrc_ip = 1.1.1.1dst_ip = 2.2.2.2infile = "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