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 thissniff(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