im trying to create a little sniffer on `python, to remove the tzsp encapulation that my router uses to send me
a copy all all the packet that flows through it. The problem is that i want to use ossim, and snort to analyze
the traffic, and woul like to de-encapsulate the packet and send it to a virtual interface where snort is
listening.
I allready have the sniffer, but didnt find the way to strip the tzsp headers to get the original packet and
send it after. I see that other people have done this on perl, but dont know how to do the same on scapy.
Its basically remove the firts 5 bytes.
# --- Cut TZSP bytes
my $tzspheader = substr $udp->{data}, 0, 5;
my $tzspdata = substr $udp->{data}, 5;
Full perl script -> http://wiki.mikrotik.com/wiki/Calea_perl_trafr
Can i use the pkt scapy format as an array ? If i remove the headers the packet will be as received by
the router, can i use scapy to sned it directly or do i have to create a emtpy packet according to the original
packet protocol and copy each field to the new one ?
Thank you All
Related
I've searched in several places, but I didn't find a simple answer to this question -
I have a .pcap file, generated using Wireshark, with several packets in it, and I wish to extract from each packet it's TCP-Timestamp (TSval).
I've managed to open each packet using scapy
packets = rdpcap('pcap_file.pcap')
for packet in packets:
print(packet.payload.id)
but I can't find the TSval of the packet (even though I can see the TSval field in the packet when I open it with Wireshark as shown in the picture below).
Packets can be accessed like dictionaries whose keys are protocols and values are payloads. For instance you can print the TCP payload in a packet like this:
if TCP in packet:
packet[TCP].show()
Now to get the TSval of the payload you have to look in TCP options. Each TCP option is encoded by scapy as a couple (option name, option value). For the timestamp option, the option value is itself a couple (TSval, TSecr). So you can basically get what you want doing the following:
from scapy.all import TCP, rdpcap
packets = rdpcap('packets.pcapng')
for packet in packets:
if TCP in packet: # ignore packets without TCP payload
for opt, val in packet[TCP].options: # consider all TCP options
if opt == 'Timestamp':
TSval, TSecr = val # decode the value of the option
print('TSval =', TSval)
I like to read a pcap file through scapy and use a filter of source address,destination address and length of the packet above or equal to 400,
After matching those packets, i would like to remove the first 16 bytes and then extract the remaining bytes sequentially.
file=rdpcap(pcap)
for pkt in file:
if pkt[0].src=='198.18.32.1' and pkt[0].dst=='198.18.50.97':
This is more than normal. pkt[0] does not really mean anything...
When doing pkt.src, you’ll get the Ethernet address (of the first layer), which is no IP address. You would need pkt[IP].src to get the IP address
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 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 am trying to sniff UDP packets using scapy sniff function, I send the packets in the Looback interface, the sending code is simple as follows:
from socket import *
IPv4 = "127.0.0.1"
Port = 45943
ClientSock = socket(AF_INET, SOCK_DGRAM)
while True:
MESSAGE = raw_input()
ClientSock.sendto(MESSAGE, (IPv4, Port))
However when i run (in another terminal tab after importing scapy):
a = sniff(iface="lo0", count = 5)
I get the following result:
>>> a.nsummary()
0000 Raw
0001 Raw
0002 Raw
0003 Raw
0004 Raw
whereas i am supposed to get UDP packets!, can any one point out to anything that i am missing here.
thanks
Unable to guess datalink type (interface=lo0 linktype=0)
That message translates as "Scapy doesn't understand the DLT_NULL link-layer header type, as used on the loopback device in *BSD and OS X, so it doesn't support the loopback device on *BSD and OS X".
So you're out of luck if you want to use Scapy on OS X to capture on the loopback device, unless and until Scapy is enhanced to handle DLT_NULL. (DLT_NULL is not that hard to handle, so presumably the only reason it's not handled is that most of the people using it on a loopback device are doing so on Linux, where the link-layer header type value on the loopback device is DLT_EN10MB, i.e. Ethernet, so nobody's bothered to fix it. I'll see if I can get it working and, if so, send them a patch.)
Some suggestions.
Instead of a.nsummary(), you can print out more information on individual packets using something like
a[1].show()
a[1].show2()
hexdump(a[1])
to examine the first packet.
2) You can force the protocol decoding to a particular type of packet format. For instance, a RAW_IP packet capture (link layer header type = 101) can be forced to be IPv6 using
conf.l2types.register(101, IPv6)
If you want to add a new layer on top of UDP, you can add a new dissector based on the port used.