I’m trying to dump packets to a file captured by scapy sniff function every 10 second to no avail.
That is possible with tcpdump like: tcpdump -s 0 -i <interface> -G 10 -w <output.pcap>.
G flag is the rotate_seconds.
Is this achievable with scapy?
Of course it is. Have a look at the wrpcap() documentation.
Essentially, you will simply build a callback function that receives packets and takes actions. Here's a very simple example that is not necessarily intended to be functional. (I'm writing it on the fly here) This should save a cap file every 100 packets. You would simply need to change the logic to be time based instead of packet count based.
#!/usr/bin/env python
from scapy import sniff
pendingPackets = []
baseFilename = "capture-"
totalPackets = 0
def handle_packet(packet):
pendingPackets.append(packet)
totalPackets += 1
if len(pendingPackets) >= 100:
filename = baseFilename + str(totalPackets) + ".pcap"
wrpcap(filename, pendingPackets)
pendingPackets = []
sniff(filter="ip", prn=handle_packet)
Related
I have about 10GB pcap data with IPv6 traffic to analyze infos stored in IPv6 header and other extension header. To do this I decided to use Scapy framework. I tried rdpcap function , but for such big files it is not recommended. It tries to load all file into memory and get stuck in my case.
I found in the Net that in such situation sniff is recommended, my code look like:
def main():
sniff(offline='traffic.pcap', prn=my_method,store=0)
def my_method(packet):
packet.show()
In function called my_method I receive each packet separately and I can parse them, but....
When I call show function with is in-build framework method I got sth like this:
When opened in wireshark I got properly looking packet:
Could you tell me how to parse this packets in scapy to get proper results?
EDIT:
According to the discussion in comments I found a way to parse PCAP file with Python. In my opinion the easies way is to use pyshark framework:
import pyshark
pcap = pyshark.FileCapture(pcap_path) ### for reading PCAP file
It is possible to easily iterate read file with for loop
for pkt in pcap:
#do what you want
For parsing IPv6 header following methods may be useful:
pkt['ipv6'].tclass #Traffic class field
pkt['ipv6'].tclass_dscp #Traffic class DSCP field
pkt['ipv6'].tclass_ecn #Traffic class ECN field
pkt['ipv6'].flow #Flow label field
pkt['ipv6'].plen #Payload length field
pkt['ipv6'].nxt #Next header field
pkt['ipv6'].hlim #Hop limit field
Update
The latest scapy versions now support ipv6 parsing.
So to parse an ipv6 ".pcap" file with scapy now it can be done like so:
from scapy.all import *
scapy_cap = rdpcap('file.pcap')
for packet in scapy_cap:
print packet[IPv6].src
Now as I had commented back when this question was originally asked, for older
scapy versions (that don't support ipv6 parsing):
pyshark can be used instead (pyshark is a tshark wrapper) like so:
import pyshark
shark_cap = pyshark.FileCapture('file.pcap')
for packet in shark_cap:
print packet.ipv6.src
or even of course tshark (kind of the terminal version of wireshark):
$ tshark -r file.pcap -q -Tfields -e ipv6.src
If you want to keep using scapy and read the file Iteratively I'd recommend you to give it a shot to PcapReader()
It would do the same you tried to do with pyshark but in Scapy
from scapy.all import *
for packet in PcapReader('file.pcap')
try:
print(packet[IPv6].src)
except:
pass
I'd recommend wrapping this around just as a failsafe if you have any packet that does not have an IPv6 address.
I am trying to analyse packets using Python's Scapy from the beginning. Upon recent searching, I found there is another module in python named as dpkt. With this module I can parse the layers of a packet, create packets, read a .pcap file and write into a .pcap file. The difference I found among them is:
Missing of live packet sniffer in dpkt
Some of the fields need to be unpacked using struct.unpack in dpkt.
Is there any other differences I am missing?
Scapy is a better performer than dpkt.
You can create, sniff, modify and send a packet using scapy. While dpkt can only analyse packets and create them. To send them, you need raw sockets.
As you mentioned, Scapy can sniff live. It can sniff from a network as well as can read a .pcap file using the rdpcap method or offline parameter of sniff method.
Scapy is generally used to create packet analyser and injectors. Its modules can be used to create a specific application for a specific purpose.
There might be many other differences also.
I don't understand why people say that Scapy is better performer. I quickly checked as shown below and the winner is dpkt. It's dpkt > scapy > pyshark.
My input pcap file used for testing is about 12.5 MB. The time is derived with bash time command time python testing.py. In each snippet I ensure that the packet is indeed decoded from raw bites. One can assign variable FILENAME with the needed pcap-file name.
dpkt
from dpkt.pcap import *
from dpkt.ethernet import *
import os
readBytes = 0
fileSize = os.stat(FILENAME).st_size
with open(FILENAME, 'rb') as f:
for t, pkt in Reader(f):
readBytes += len(Ethernet(pkt))
print("%.2f" % (float(readBytes) / fileSize * 100))
The average time is about 0.3 second.
scapy -- using PcapReader
from scapy.all import *
import os
readBytes = 0
fileSize = os.stat(FILENAME).st_size
for pkt in PcapReader(FILENAME):
readBytes += len(pkt)
print("%.2f" % (float(readBytes) / fileSize * 100))
The average time is about 4.5 seconds.
scapy -- using RawPcapReader
from scapy.all import *
import os
readBytes = 0
fileSize = os.stat(FILENAME).st_size
for pkt, (sec, usec, wirelen, c) in RawPcapReader(FILENAME):
readBytes += len(Ether(pkt))
print("%.2f" % (float(readBytes) / fileSize * 100))
The average time is about 4.5 seconds.
pyshark
import pyshark
import os
filtered_cap = pyshark.FileCapture(FILENAME)
readBytes = 0
fileSize = os.stat(FILENAME).st_size
for pkt in filtered_cap:
readBytes += int(pkt.length)
print("%.2f" % (float(readBytes) / fileSize * 100))
The average time is about 12 seconds.
I do not advertise dpkt at all -- I do not care. The point is that I need to parse 8GB files currently. So I checked that with dpkt the above-written code for a 8GB pcap-file is done for 4.5 minutes which is bearable, while I would not even wait for other libraries to ever finish. At least, this is my quick first impression. If I have some new information I will update the post.
I am looking for the specific task:
Grab the payload/data from a packet -> Append to a file... BUT. I want specifically to follow packets according to flags/ICMP types/etc... So lets say I want specifically to take the payload of "echo" packets and not the rest.
My (ineffective) code is the following:
from scapy.all import *
f= open('filecaptured', 'a+')
def pkt_diam(pkt):
raw = pkt.getlayer(Raw).load
print raw
# pkt.show()
# fo = open("payload", "wb")
f.write(raw);
sniff (filter="icmp" , store=0, prn=pkt_diam, timeout = 120 )
The problem here is that I cannot find a way to sniff specifically for "type = echo request" and the only parameters that I can use is 'protocol' and host or 'and not host 127.0.0.1'.
Is there a way around this?
I think for this one I need to use ctypes and libpcap.so but I am not sure... (I didnt find any [other] libraries for python - sniffing )
I don't have scapy installed right now, but what if you simply check for the type echo-reply in your callback-function pkt_diam:
if not "echo-reply" in pkt.show():
return
Try filter="icmp[0]=8" for filtering during capture or
if pkt[ICMP].type==8:
in callback function.
I have created a sniffer in scapy and I want the packets captured by scapy to be written onto a file for further analysis?
def sniffer(ip):
filter_str = "icmp and host " + ip
packets=sniff(filter=filter_str,count=20)
f = open('log.txt',"a")
#f.write(packets)
The last line of code does not work. Is there any way I could do this?
f.write expects a character buffer, but you supply it with a Sniffed object which is the result of calling sniff. You can, very simply, do the following:
f.write(str(packets))
This should work. But it probably won't display the information exactly as you would like it. You are going to have to do more work collecting information from packets as strings before you write to f.
I'm reading a PCAP file using Scapy using a script such as the (semplified) following one:
#! /usr/bin/env python
from scapy.all import *
# ...
myreader = PcapReader(myinputfile)
for p in myreader:
pkt = p.payload
print pkt.time
In this case the packets time is not relative to PCAP capture time, but starts from the instant I've launched my script.
I'd like to start from 0.0 or to be relative to the PCAP capture.
How can I fix it (possibly without "manually" retrieving the first packet time and repeatedly using math to fix the problem)?
I saw that using pkt.time is wrong, in this case.
I should print p.time instead.