Is there an efficienct way to get field offset in pyshark - python

Is there an efficient way to get the offset of some field in a packet captured with pyshark?
For example, I need to get the offset of the source IP within the whole packet or within some layer header in the packet. Is it possible?

I was able to solve my issue. Here is a sample code:
import pyshark
packets = pyshark.FileCapture(input_file=pcap_file_dir)
print(int(packets[0].ip.src.pos)) # Prints the offset of source IP

Related

Pulling data from pyshark

I am trying to pull data out of data packets that I am recieving from another device. I have isolated the packet I want to pull the data from but cannot figure out how to extract the data that I want. I am using pyshark to get to the packet but this does not allow to me to actually see that data. I can see the data when I am in wireshark. The data I am looking to pull is circled in red. Wireshark
Here is my code in python.
import pyshark
capture=pyshark.LiveCapture(interface='wlan0', display_filter='frame.len>190 and upd.port==1700')
for i in capture:
print(i)
Which displays all of the same information that wireshark does minus the latitude, longitude coordinates.
I would ask for a sample PCAP file, but most people don't want to share real world data. Without a PCAP file, I cannot give you a complete answer, but I can give you one that is 95% there.
This is the way that I would attack your problem:
import pyshark
capture = pyshark.LiveCapture(interface='your_interface')
for raw_packet in capture.sniff_continuously():
# filter only UDP packet that have a frame length greater
# than 190 and that have a port number of 1700.
if hasattr(raw_packet, 'udp') and int(packet.frame_info.cap_len) > 190 and packet[packet.transport_layer].srcport == '1700':
# Get the details for the packets by accessing
# _all_fields and _all_fields.values()
field_names = raw_packet.udp._all_fields
field_values = raw_packet.udp._all_fields.values()
for field_name in field_names:
for field_value in field_values:
# you can add another filter here to get your
# lat & long coordinates
print(f'{field_name} -- {field_value}')
# if you need to access the packet data you need to do this,
# but it might come back in hex, which will need to be decoded.
# if "DATA" in str(packet.layers):
# print(packet.data.data)
Please reach out if you have any issues filtering out the packets that you're looking for. if you can share a sample PCAP, I will tweak my answer.
I have a document and code examples on GitHub named pyshark packet analysis that you might find useful.

Python: wrong ip is shown in packet header

I'm forwarding a machine's packets through mine. I tested with tcpdump host <machine_ip> to see if everything is alright, and it is. Now I need to capture these packets. I chose to do this with Python. Right now I'm trying to filter the packets, but the ip that is printed is different from the right one. It should've been 192.168.0.8:
import socket
from struct import *
print("Started")
with socket.socket(socket.AF_PACKET,socket.SOCK_RAW, socket.ntohs(0x0003)) as s:
while True:
packet=s.recvfrom(65565)
content=packet[0]
ip_header=unpack('!BBHHHBBH4s4s', content[:20])
source_ip=socket.inet_ntoa(ip_header[8])
print(source_ip)
The printed ones are 8.0.69.0 and 8.0.69.16, which none of these matches the expected form.
This is because in front of the raw data is the MAC header.
If You change the line:
ip_header=unpack('!BBHHHBBH4s4s', content[:20])
to
ip_header=unpack('!BBHHHBBH4s4s', content[14:34])
You will probably get your ip address. I said probably becase it really depends on the link layer, as there might be a vlan tag present, thus shifting the ip header even further.

Scapy - persistent RandIP

I am trying to simulate a TCP communication between two hosts with scapy.
My problem is, that I can't save the random IP addresses scapy generates for me.
This code
src_IP = RandIP()
print(src_IP)
print(src_IP)
print(src_IP)
gives me an output like this
234.200.98.20
147.3.56.17
135.102.142.49
So every time I access src_IP it has a new value.
Is there a way to save a random IP from scapy? So I could generated 2 IPs at the beginning of my function and use them as source and destination for my TCP communication.
I could generate the IPs myself, but I thought there had to be a more elegant solution to it.
BTW. non of the packets are going to be sent, they will be written into a PCAP file. Therefor I have to create both sides of the communication.
The accepted answer is a hack; it is correct (as in "it works and do what was asked"), but it is not the correct way to do that in Scapy.
The method you are looking for is ._fix(). It will work with any volatile value type.
src_IP = RandIP()._fix()
If you also need for example a random source port, you could do:
src_port = RandShort()._fix()
I found an answer.
RandIP() creates an instance of an object, and every time this object gets accessed, to print or do send a packet or something else, it generates a new IP.
So my solution is to cast it to a string
src_IP = str(RandIP())
print(src_IP)
print(src_IP)
print(src_IP)
And the output is just as intended
232.119.133.38
232.119.133.38
232.119.133.38

Specifying packet length with scapy

I'm trying to send a specific packet size (100 bytes) with scapy but cant seem to get it.
I'm using this to start.
sr(IP(dst="192.168.1.1")/TCP(dport=443))
Looking at the docs / help I cant tell if I can use PacketLenField to specify the length of the packet. I can do it with NMAP & NSE but would like to do it outside of NMAP.
Any ideas on this one?
Thanks!
You can just add on the required number of bytes as a String when crafting the packet e.g.:
payload = 'ZZZZZZZZZZZZZZZZZZZZZ'
pkt = Ether() / IP() / TCP() / payload
will work. You just need to adjust the length of the payload as you require.
Scapy's Raw() function populates the payload of the packet. If you know your header size, you only need to fill in the remaining bytes with random data.
You can use RandString() to generate random padding. The following command sends a packet of length 100 (and listens for a response):
sr(IP(dst="192.168.1.1")/TCP(dport=443)/Raw(RandString(size=72))
You may use inet.Padding() from scapy library:
packet = IP(dst="192.168.1.1")/TCP(dport=443)
if len(packet)<100:
#"\x00" is a single zero byte
myString = "\x00"*(100 - len(packet))
packet = packet/inet.Padding(myString)

Scapy: fields to recompute when forging packets

I'm forging with Scapy the TTL value in the IP header in some data packet that I captured. Besides the checksum in both IP and transport layer headers, is there anything else I should recompute?
Right now I'm doing:
for p in myPackets:
p[IP].ttl = targetTTL
del(p[IP].chksum)
del(p[IP].payload.chksum)
for i in range(len(myPackets)):
myPackets[i] = myPackets[i].__class__(str(myPackets[i]))
I'm asking this because Scapy's sr function, which matches packets with their responses (ICMP in my case) has been returning data with a few RTTs > 1 second, which is absurd since I'm using ttl=1.
Have you tried just sending the packet? Scapy should recompute the checksums for you automatically.You could also try setting them to None, but I don't believe that's necessary.
I believe scapy will automatically recalculate the checksums if you call the show2() command on the packet. So if you have a packet at index 0 in the object pckt, you should call pckt.show2() and the checksum should be correct. At least that's my understanding.
pkt.show2() same as show but on the assembled packet (checksum is calculated, for instance) Source

Categories