Search code examples
pythonscapypcap

Altering packets using Scapy - automatically update properties (length, checksum etc.) after editing packet's payload


I am currently modifying a pcap file (on a Linux system) using scapy in Python. I do this for two reasons:

  • I need to alter specific parts of the load of some of the packets and then replay those so that a software I'm testing receives the changed data allowing me to observe its behaviour
  • With some packets (with the original load) I'm getting the "message too long" when I try to use tcpreplay or scapy's own sendp(...). Trimming down the load should (if I'm not mistaken) allow me to go around this problem.

Here is a small example of what I do (I use ipython):

from scapy.all import rdpcap, wrpcap
from scapy.utils import sendp
import re

# Load PCAP file. In my case I have 24 packets
pkts = rdpcap('dump.pcap')

# Change the load of packet 16 by removing some of the data inside
pkts[16].load = re.sub(r'<Stop[0-9]+>[0-9]+</Stop[0-9]+>', '', pkts[16].load)

# Write the changes to a new file
wrpcap('dump_edited.pcap', pkts)

# and send those (the operation requires admin privileges!)
sendp(pkts) # or use tcpreplay in the terminal

Now the problem is that editing the load in this way means that other properties related to it will not get updated. For example if the length was previously 2982 (using pkts[16].show() you can get a detailed overview of the packet's properties) after editing its load the length is still the same. Checksum doesn't change also. This is of course expected since all I'm doing is directly edit the string, which clearly doesn't trigger any updates of the packets properties.

I've just discovered scapy so the question is probably too obvious but is there a way to alter the load in such a way that its properties also get updated automatically?


Solution

  • Scapy avoid doing things without the coder wanting it. For instance, you must be able to specify manually a wrong checksum for your tests, without having scapy modifying it.

    In general, when a property is None, then scapy calculates the value automatically. For instance, set all the checksums and the lengths to None, and scapy will calculate them for you based on the packet when building.

    If you don’t want to write it, you can also build it using

    pkt = Ether(bytes(pkt))
    

    (Supposing Ether is the lowest layer), after having set the values to None, this also recalculate the checksums

    A packet will also be built while doing wrpcap(..), bytes(packet) or packet.show2()

    This should fix your problem