0

Getting into protocol development with Scapy, going through documentation and watching videos on Scapy but I'm a bit confused with field types. Let's assume something generic for a packet structure:

| version number - 8 bits | message type - 8 bits | payload size - 16 bits | payload of varying length |

Now, I want to implement this in python using Scapy, but I'm confused about what fields I should be using. Scapy documentation doesn't explain most of the different fields. The tutorials in "Adding new protocols" section of the Scapy documentation uses different fields but doesn't explain what they are. Some of them are easy enough to understand based on their names, but what is a ShortField for example? LongField?

Some of the fields have default functionality, like LenField, that gets autopopulated with payload size when you build the packet. However there's no way to set the size of the LenField like you can with a BitField. In my example protocol, payload size is supposed to be 16 bits, how do I enforce that in a LenField or similar. I could always use a BitField but that seems dumb when LenField seems to exist specifically for this kind of purpose.

Looking at another example I found on the Internet while researching this topic:

class Foo(Packet):
    name = "my_packet"
    fields_desc = [
        ShortField("index", 0)
        FieldLenField("len", None, length_of="data")
        StrLenField("data", "", length_from="len")
        FieldLenField("sig_len", None, length_of="data")
        StrLenField("sig", "", length_from="sig_len")

Why did they choose these specific fields? Why ShortField and not BitField?

In conclusion the questions I'm looking answers for are the following:

  1. Is there a place to lookup explanations for each of the field types? Are they a standard? Scapy documentation leaves a beginner like me lacking.
  2. How should I decide what type of field to use? I guess this might be answered by question 1 but in case there's additional details I would love to hear them.
  3. How do I know the bit length of field types that don't explicitly state it, for example in their naming? Some of these also do not have a size attribute like BitField does where I can manually set it.
  4. How should variable length values like frame size be handled in code to build a field of specific size without having to worry about overflowing or bit length that is lower than defined in the protocol spec. Does the LenField, for example do this automatically as part of it's functionality? How would I make sure the value is 16bits long in my example?

1 Answer 1

1

The list of scapy fields is at https://scapy.readthedocs.io/en/latest/api/scapy.fields.html

ShortField (think of a short type in c) is 16 bits
ByteField is 8 bits

I don't think you want to use a bitfield because you don't need to access individual bits like flags for ex.

If I was creating a custom protocol that gets carried in UDP, I would consider doing it like this:

#!/usr/bin/env python3

from scapy.all import Packet, ByteField, ShortField, bind_layers, Raw, hexdump
from scapy.layers.inet import UDP, IP

class DarkoProto(Packet):
  name = "DarkoProto"
  fields_desc = [
    ByteField("version", 1),  # 8 bits for version, default to 1
    ByteField("message_type", 0),  # 8 bits for message type, default to 0
    ShortField("payload_size", None),  # 16 bits for payload size, will be calculated from payload length
  ]

  def post_build(self, p, pay):
    # Determine d_payload_size
    if self.payload_size is None:
      plen = len(pay)
      # p is the current packet in bytes (big-endian)
      p = p[:2] + plen.to_bytes(2, 'big') + p[4:]  # Overwrite bytes 2 and 3 (payload_size field)
    return p + pay

# Add into UDP for ex
bind_layers(UDP, DarkoProto)

# Create the custom portion
custom_packet = DarkoProto(version=2, message_type=10)/Raw(load="Hello Darko!")

# Build an IP packet using the previous packet
packet = IP(dst="127.0.0.1")/UDP(sport=0x4321,dport=0x1234)/custom_packet

# Show the packet details
packet.show2()

# Dump out the packet raw bytes
print(hexdump(packet, dump=True))

There should be plenty of examples out there showing how to put your protocol into IP or even directly into Ethernet if that is what you are looking to do.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.