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)
Related
I am reading USBPcap files created in Wireshark with large, isochronous packets up to 494439 bytes. I am then trying to parse the packets in python with scapy. Unfortunately, scapy 2.4.3 defaults to ignoring bytes past the 65535th byte for packets greater than 65535 bytes.
Is there a way to read packets larger than 65535 bytes?
In order to instruct scapy to read packets larger than 65535 bytes, you must read packets one at a time off the many pcap reading generators found in scapy.utils API. Specifically, the following classes within scapy.utils support reading large packets from a pcap or pcapng file:
class scapy.utils.PcapReader(filename)
class scapy.utils.PcapNgReader(filename)
class scapy.utils.RawPcapReader(filename)
class scapy.utils.RawPcapNgReader(filename)
Note that scapy.utils.rdpcap(filename, count=- 1) does not support this functionality.
My solution:
from scapy.all import *
packet_reader = RawPcapNgReader('my_pcapng_file.pcapng')
while True:
try:
# created my own usb_packet class to parse packet header on __init__
p = usb_packet(packet_reader.read_packet(size=500000)) # read packet up to 500 kB large
if p.filter(): # filter packets based on usb_packet custom filter method
print(len(p.hex_str), len(p.data_packets)) # do stuff to the filtered packets
except EOFError:
break
For capturing packets via sniff or similar, one might set the buffer size via class scapy.config.Conf.bufsize which defaults to 65536 to allow a 65535 byte packet to be captured (see docs). For pragmatic programming, one may set this configuration when reading pcaps as well rather than maintaining the size argument wherever read_packet() is called on a generator.
An interesting note: This default appears to be due to IPv4 packet structure in which the packet length is represented by a 16 bit number. In other words, the largest packet this header value can depict is 1111111111111111 bytes, or 2^16=65536. Counting from zero, we have the largest IPv4 packet being 65535 bytes. For USB, as in my case, larger packets are possible.
I'm working on project at university. What I'm trying to do is that I want my program to be able to change bits in RTP packets' payload. I'm trying to create a simple tool that would apply steganography on RTP packets' payload - first it would "catch" rtp packets sent from my computer, then change payload section and send packets further to destination. First thing (while learning) what I'm trying to do is to create RTP packet stream. And i thought I managed, until I checked with Wireshark:
All that we see is only UDP packets (python socket.SOCK_DGRAM)
And just simple data stream of bits..
I'm trying to create packet by the RCF 3550:
Version - 2 bits;
padding - 1 bit;
extension - 1 bit;
csrc_count - 4bits;
marker - 1 bit;
payload_type - 7 bits;
sequence_number - 16 bits;
timestamp - 32 bits;
ssrc - 32 bits;
payload - varies;
I'm creating a list of bits:
rtp_packet[0:2] = format(packet_data["version"], "b").zfill(2)
rtp_packet[2:3] = format(packet_data["padding"], "b")
rtp_packet[3:4] = format(packet_data["extension"], "b")
rtp_packet[4:8] = format(packet_datas["csrc_count"], "b").zfill(4)
rtp_packet[8:9] = format(packet_data["marker"], "b")
rtp_packet[9:16] = format(packet_data["payload_type"], "b").zfill(7)
rtp_packet[16:32] = format(packet_data["sequence_number"], "b").zfill(16)
rtp_packet[32:64] = format(packet_datas["timestamp"], "b").zfill(32) # turi dideti po 160
rtp_packet[64:96] = format(packet_data["ssrc"], "b").zfill(32)
rtp_packet[96:128] = format(packet_data["csrc_list"], "b").zfill(32)
rtp_packet[128:] = bin(int.from_bytes(packet_data["payload"].encode(), "big"))[2:]
And then send those bytes through created socket. Didin't work (the result is above). Then I found this PyRTP library and the result is the same as above.
I'm new in Python and all this packet thing, so maybe someone could help me with what I'm doing wrong or what I didn't do that Wireshark still sees those packets as only UDP, but not RTP? Image below is what I hope to do (this was done with a SIP server at home). Thank you in advance!
RTP is an application protocol and it's encapsulated into UDP (network protocol), you can verify that your packets are RTP packets using WireShark with the following: https://en.wikiversity.org/wiki/Wireshark/IPv4_multicast
Wireshark actually understands audio/video packets as UDP packets.
You can convert those UDP packets to RTP using the menu option - https://support.hpe.com/hpesc/public/docDisplay?docId=c03617954&docLocale=en_US
You could create that packet using the scapy library's rtp functionality and save it as pcap file (as done in question):
from scapy.all import *
from scapy.all import wrpcap
rtp = { "marker": 1,
"payload_type": 0,
"sequence": 27675,
"timestamp": 3157624494,
"sourcesync": 0x3f622544
}
pkt= Ether()/IP(src="10.0.0.10", dst="10.0.0.100")/UDP(sport=18529, dport=23570)/RTP(**rtp)
wrpcap("rtp_pkt.pcap",pkt)
You can then open the resulting pcap file in Wireshark on the command line and tell it to decode port 23570 as RTP:
wireshark -d udp.port==23570,rtp rtp_pkt.pcap
There also other dedicated Python based RTP libraries such as rtp.
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 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.
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