0

I have a client sending a packet with a custom layer "Reservation" created with Scapy

Client.py

#!/usr/bin/env python

import socket
from scapy.all import *


class Reservation(Packet):
    name = "ReservationPacket"
    fields_desc=[ ShortField("id", 0),
            BitField("type",None, 0),
            X3BytesField("update", 0),
            ByteField("rssiap", 0)]


pkt = IP(len=16384, src='192.168.240.5', dst='192.168.240.198',
id=RandShort(), ttl=2)/TCP(sport=5005,
dport=5005, flags="S", window=200,
options=[('MSS', 1460), ('WScale',    2)])/Reservation(id=11)/"HELLO"

spkt = bytes(pkt)
spkt += '\x00'*20

s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
s.setsockopt(socket.SOL_IP, socket.IP_HDRINCL, 1)

s.sendto(spkt, ('192.168.240.198', 5005))

s.close()

The packet is correctly sent and received.

How can I access a specific field of the packet? How can I interpret the received data? I would like to use something similar to spkt.id in order to retrieve the value of that field. Is it possible somehow?

EDIT I've reached this point: I am sending a pcaket over a tcp socket. It has the following structure:

###[ IP ]###
  version   = 4
  ihl       = None
  tos       = 0x0
  len       = 16384
  id        = <RandShort>
  flags     = 
  frag      = 0
  ttl       = 2
  proto     = tcp
  chksum    = None
  src       = 192.168.240.5
  dst       = 192.168.240.1
  \options   \
###[ TCP ]###
     sport     = 5005
     dport     = 5005
     seq       = 0
     ack       = 0
     dataofs   = None
     reserved  = 0
     flags     = S
     window    = 200
     chksum    = None
     urgptr    = 0
     options   = [('MSS', 1460), ('WScale', 2)]
###[ ReservationPacket ]###
     id        = 9
     type      = None
     update    = 0x0
     rssiap    = 0 
###[ Raw ]###
      load      = 'PROVA'

Where ReservationPacket is a custom layer. The packet is received and with

    data = conn.recv(BUFFER_SIZE)
    if not data: break
          print "received data:", data
          by = str.encode(data)             
          pkt_hex = by.encode('hex')
          hexdump(by)
          container = IP(data)
          container.show()

I fill the container packet, which is defined as

container = IP()/TCP()/Reservation()

The output of

container.show()

is

###[ IP ]###
version   = 4L
ihl       = 5L
tos       = 0x0
len       = 16384
id        = 56856
flags     = 
frag      = 0L
ttl       = 2
proto     = tcp
chksum    = 0x3987
src       = 192.168.240.5
dst       = 192.168.240.1
\options   \
###[ TCP ]###
 sport     = 5005
 dport     = 5005
 seq       = 0
 ack       = 0
 dataofs   = 7L
 reserved  = 0L
 flags     = S
 window    = 200
 chksum    = 0xd962
 urgptr    = 0
 options   = [('MSS', 1460), ('WScale', 2), ('EOL', None)]
###[ Raw ]###
    load      = '\x00\t\x00\x00\x00\x00PROVA'

Apparently the Reservation layer is not recognized and interpreted as RAW. How can I build the same packet as the one transmitted?

3
  • Are you using scapy v2.x or v3.x? Commented Nov 16, 2015 at 7:47
  • Scapy 2.3.1 and Python 2.7 Commented Nov 16, 2015 at 8:13
  • You are not supposed to use bytes in scapy v2.x. Normally, you would use smth. like pkt[Reservation].id to access field value, but I did not check your code in full as I am on scapy v3.x. Commented Nov 16, 2015 at 8:15

1 Answer 1

3

You can use s=str(packet) to serialize a packet in scapy 2 and packet=Layer(s) to force deserialization of a bytestream as Layer.

In your case:

rdata = sock.recv(8192)
layer = Reservation(rdata)
layer.show()
print layer.id

Note that you can also bind your layer for scapys autodissect/payload guessing with bind_layers() to make it work with sniff() or dissection of tcp/Reservation bytestreams (tcp packet with reservation payload). The following line binds TCP.dport=5005 to Reservation.

bind_layers(TCP, Reservation, dport=5005)

update: specific answer to your question.

You do not have to care about the IP/TCP layer as this is all handled within the socket. The data that is received by socket.recv is the payload to TCP therefore all you have to do is to force scapy to deserialize the received data as Reservation.

TCP Socket:

data=[]
while True:
    chunk = conn.recv(BUFFER_SIZE)
    if not chunk: 
        break
    print "received data:", chunk
    data.append(chunk)
layer = Reservation(''.join(data))
layer.show()
print layer.id

Additionally, you can instruct scapy to try to auto-dissect your layer based on a simple rule e.g. TCP.dport==5005 with a call to bind_layers(). This way it will also work with sniff or whenever you receive the full IP/TCP/Reservation/Raw bytestream.

Raw Socket:

bind_layers(TCP, Reservation, dport=5005) # bind Reservation as nextlayer to TCP.dport=5005
# ...
data, peer = s.recvfrom(BUFFER_SIZE)
print "received data:", peer, repr(data)
layer = IP(data)                # dissection automagic based on rules registered with bind_layers
layer.show()
print layer[Reservation].id
Sign up to request clarification or add additional context in comments.

6 Comments

Thank you. Can you have a look here of what I tried to do? link
please merge your duplicate question.
using bind_layers() as you suggested it's working fine! Thank you very much.
if you merge your question you'll get a complete answer with an example for a) bind_layers and b) forced dissection.
Please can you share the link / solution. I am facing the same issue.
|

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.