Reputation: 974
I'm writing some protocols in ScaPy, but am having difficulty understanding how the len fields work. After reading http://trac.secdev.org/scapy/wiki/LengthFields I'm no less enlightened.
Obviously, we have what they call 'lenfield' (Holds the length of the field) and 'varfield' (Contains the actual variable length field). However, it seems that the only fields that can be varfields are PacketLenField, StrFixedLenField, and StrLenField. Where's the rest of the fields? Why can't you have a variable length BitField, or XBitField?
For example I've got:
BitFieldLenField('lenfield', None, 8, length_of='varfield')
This correctly returns a length of 8 (the field I want in this case is 8 octets/ 4 hex pairs long). All good so far. However, when I try and get that field, it seems like my only option is a StrLenField which returns something like 'A\x81\x11\x11P 3'
So, my question is: How do I get that field back as the actual hex in the packet? Am I missing something in the built in fields, or do I have to create something like an XBitLenField?
Thanks for your help.
Upvotes: 1
Views: 5754
Reputation: 9139
This answer is with respect to Scapy 2.2.0.
LenField
s typically work in pairs like the following:
FieldLenField("len", None, length_of="data")
StrLenField("data", "", length_from=lambda pkt:pkt.len)
Notice how the length_of
and length_from
link the two fields together. The length_of
value tells Scapy how to calculate the "len"
field when sending the packet (Notice the default value is None
, to indicate it should be calculate automatically). The length_from
value tells Scapy how many bytes to input into the "data"
field when it is dissecting the packet.
There is a special field called LenField
which can be used by itself. Notice again that the default value is None
meaning it should be calculated automatically. When sending Scapy will simply calculate "len"
as the number of bytes following the current layer.
LenField("len", None)
Now that Length Fields have been introduced, you can use Python to encode the output of the StrLenField
into hex.
# In layer definition
BitFieldLenField("lenfield", None, 8, length_of="varfield")
StrLenField("varfield", "", length_from=lambda pkt:pkt.lenfield)
# In main script
print(pck[mylayer].varfield.encode("hex")) # Replace "mylayer" with the name of your new layer
Upvotes: 3
Reputation: 36
You can rewrite Fields object, for instance StrLenField:
# String to hex split by space
def str2hex(string):
return ' '.join('%02x' % ord(b) for b in string)
class XStrLenField(scapy.fields.StrLenField):
def i2repr(self, pkt, x):
return str2hex(scapy.fields.StrLenField.i2m(self, pkt, x))
After you can use the XStrLenField in field_desc[]:
XStrLenField("rand", "", length_from=lambda x: x.len)
Upvotes: 2