I am trying to send a previously recorded traffic (captured in pcap format) with scapy. Currently I am stuck at striping original Ether layer. The traffic was captured on another host and I basically need to change both IP and Ether layer src and dst. I managed to replace IP layer and recalculate checksums, but Ether layer gives me trouble.
Anyone has experience resending packets from capture file with applied changes to IP and Ether layer(src and dst)? Also, the capture is rather big couple of Gb, how about scapy performance with such amounts of traffic?
check this example
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
comments:
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 sniffedip="1.1.1.1"
and so on as illustrated above.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_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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With