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?
You can use
s=str(packet)
to serialize a packet in scapy 2 andpacket=Layer(s)
to force deserialization of a bytestream asLayer
.In your case:
Note that you can also bind your layer for scapys autodissect/payload guessing with
bind_layers()
to make it work withsniff()
or dissection of tcp/Reservation bytestreams (tcp packet with reservation payload). The following line binds TCP.dport=5005 to Reservation.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 toTCP
therefore all you have to do is to force scapy to deserialize the receiveddata
asReservation
.TCP Socket:
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 tobind_layers()
. This way it will also work withsniff
or whenever you receive the fullIP/TCP/Reservation/Raw
bytestream.Raw Socket: