在 Python 中的 tcp 套接字中提取接收到的数据 [英] Extract received data in a tcp socket in Python
问题描述
我有一个客户端发送一个带有使用 Scapy 创建的自定义层Reservation"的数据包
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.
如何访问数据包的特定字段?如何解释接收到的数据?我想使用类似于 spkt.id 的东西来检索该字段的值.有没有可能?
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?
编辑我已经到了这一点:我正在通过 tcp 套接字发送 pcaket.它具有以下结构:
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'
其中 ReservationPacket 是自定义层.数据包被接收并带有
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()
输出
container.show()
是
###[ 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'
显然,Reservation 图层未被识别并解释为 RAW.如何构建与传输的数据包相同的数据包?
Apparently the Reservation layer is not recognized and interpreted as RAW. How can I build the same packet as the one transmitted?
推荐答案
您可以使用 s=str(packet)
在 scapy 2 和 packet=Layer(s) 中序列化一个数据包
强制将字节流反序列化为 Layer
.
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
.
在你的情况下:
rdata = sock.recv(8192)
layer = Reservation(rdata)
layer.show()
print layer.id
请注意,您还可以使用 bind_layers()
为 scapys autodissect/payload 猜测绑定层,使其与 sniff()
或 tcp/Reservation 字节流的剖析一起使用(带有保留负载的 tcp 数据包).以下行将 TCP.dport=5005 绑定到 Reservation.
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)
更新:您问题的具体答案.
您不必关心 IP/TCP 层,因为这一切都在套接字内处理.socket.recv
接收到的数据是 TCP
的有效载荷,因此你所要做的就是强制 scapy 反序列化接收到的 data
作为预订
.
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 套接字:
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
此外,您可以指示 scapy 尝试根据简单规则自动剖析您的图层,例如TCP.dport==5005
调用 bind_layers()
.这样,它也适用于 sniff
或当您收到完整的 IP/TCP/Reservation/Raw
字节流时.
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.
原始套接字:
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
这篇关于在 Python 中的 tcp 套接字中提取接收到的数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!