Modify bytes in Scapy script - python

I have a pcap file where I have packets like this :
Ether()/IP()/TCP()/Raw (this one for example)
I'd like to choose random 10 packets in the pcap file and modify 3 bytes in the Raw layer located at the same position in the whole 10 packets, and then save the pcap.
I did some tests but didn't achieve anything, I don't think it's the right way to do:
pkt = rdpcap('file.pcap')
for i in pkt:
if i.haslayer(TCP) and i.haslayer(Raw):
list_pkt.append(i)
rdm_list = random.sample(list_pkt,10)
for i in rdm_list:
org = i[Raw].load
new = org[:15] + '\xdd\xdd\xdd' + org[18:]
i[Raw].load = new
Any help please?

Related

How to get the number of packets in a pcap file using scapy and python , without iterating

I need to obtain the number of packets in a pcap file using python and scapy, in an efficent way.
I now use the following python code:
from scapy import *
pcap_file = "path/to/pcap/file.pcap"
count = 0
for packet in scapy.PcapReader(pcap_file):
count += 1
But with big pcap files (hundreds of MB) it is not an efficient solution. Is there another way to obtain packets number without iterating all over them?
You can't. The pcap file format consists only of a file header followed by all the packet payloads preceded by a packet record header. Neither the file header contains a count of all packets, nor a packet record header contains the index of the current packet.
And while the pcapng format is more flexible it does not seem to be possible to get the number of packets without iterating either.

How to convert pyshark packet to binary value

I am able to read .pcap file with pyshark. Here is my code:
packets = pyshark.FileCapture(pcap_dir) # pcap_dir is the directory of my pcap file
To print a packet, I use print(packets[0]). My question is: how can I convert packets[0] to its binary value? For example, this can be useful if I want to send the packet again to the network
I was able to solve the problem. I simply used:
packets = pyshark.FileCapture(
input_file=pcap_dir,
use_json=True,
include_raw=True
)._packets_from_tshark_sync() # pcap_dir is the directory of my pcap file
hex_packet = packets.__next__().frame_raw.value
print(hex_packet)
binary_packet = bytearray.fromhex(hex_packet)
print(binary_packet)
Also, it might be useful to check this

Whole packet length Scapy

I am capturing WiFi traffic with tcpdump using the parameter -s 100 (which means I am only capturing the headers of the packets).
When I load the .pcap file and process it with Scapy I do:
pkts = rdpcap(pcapfile)
totalbytes = 0
for pkt in pkts:
totalbytes += len(pkt)
However, as I am truncating the capture, doing len(pkt) will not give me the whole packet length (frame length), it will give me the captured packet length. How can I get the real packet length?
Extra: as I have done in some occasions before, I open the pcap file in wireshark and search for the hex values of interest. But in this case (frame.len) will show the value I am looking for, but I can't find the way wireshark obtains this real packet length without having the whole packet captured.
The rdpcap function uses the PcapReader class for reading packets. Unfortunately this class discards the information you are looking for in the read_packet method, even though it is to be found in the pcap file. So you have to use the RawPcapReader directly.
totalbytes = 0
for pkt, (sec, usec, wirelen) in RawPcapReader(pcapfile):
totalbytes += wirelen
With modern Scapy versions, the proper answer would be to use pkt.wirelen. This only exists in packets read from a pcap
If for some reason you don't want to use RawPcapReader, you can use the len attribute for IPv4 packets.
real_length = pkt[IP].len
truncated_length = len(pkt)
Strangely, the IPv6 layer in Scapy doesn't have the same attribute, but it does have an attribute called plen which is the length of the payload:
payload_length = pkt[IPv6].plen
real_length = payload_length + 40
truncated_length = len(pkt)

Writing raw IP data to an interface (linux)

I have a file which contains raw IP packets in binary form. The data in the file contains a full IP header, TCP\UDP header, and data. I would like to use any language (preferably python) to read this file and dump the data onto the line.
In Linux I know you can write to some devices directly (echo "DATA" > /dev/device_handle). Would using python to do an open on /dev/eth1 achieve the same effect (i.e. could I do echo "DATA" > /dev/eth1)
Something like:
#!/usr/bin/env python
import socket
s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW)
s.bind(("ethX", 0))
blocksize = 100;
with open('filename.txt') as fh:
while True:
block = fh.read(blocksize)
if block == "": break #EOF
s.send(block)
Should work, haven't tested it however.
ethX needs to be changed to your interface (e.g. eth1, eth2, wlan1, etc.)
You may want to play around with blocksize. 100 bytes at a time should be fine, you may consider going up but I'd stay below the 1500 byte Ethernet PDU.
It's possible you'll need root/sudoer permissions for this. I've needed them before when reading from a raw socket, never tried simply writing to one.
This is provided that you literally have the packet (and only the packet) dumped to file. Not in any sort of encoding (e.g. hex) either. If a byte is 0x30 it should be '0' in your text file, not "0x30", "30" or anything like that. If this is not the case you'll need to replace the while loop with some processing, but the send is still the same.
Since I just read that you're trying to send IP packets -- In this case, it's also likely that you need to build the entire packet at once, and then push that to the socket. The simple while loop won't be sufficient.
No; there is no /dev/eth1 device node -- network devices are in a different namespace from character/block devices like terminals and hard drives. You must create an AF_PACKET socket to send raw IP packets.

header filtering using python

i want to filter some headers in a wireshark capture (converted to text format) so i can analyse these set of headers.i need a python script to do this. any help would be appreciated
You might want to look at dpkt. It's a Python library to simplify reading (or generating) network data. Just save your Wireshark data as a Pcap stream and it can easily be opened from within Python.
I don't know exactly which headers you want or how you need them filtered and formatted, but here's an example of what you could write: (taken from a contributor's blog post)
import dpkt
pcap = dpkt.pcap.Reader(open('test.pcap'))
for timestamp, buf in pcap:
eth = dpkt.ethernet.Ethernet(buf)
ip = eth.data
tcp = ip.data
print 'Got data from port ' + str(tcp.port)

Categories

Resources