我有一个
scapy
协议和一个数据包。
就像“第一步”说的那样,很容易打印一个包含字段的数据包,以及数据包的二进制转储:
>>> a=Ether()/IP(dst="www.slashdot.org")/TCP()/"GET /index.html HTTP/1.0 \n\n"
>>> a
<Ether type=IPv4 |<IP frag=0 proto=6 dst=Net("www.slashdot.org/32") |<TCP
|<Raw load='GET /index.html HTTP/1.0 \n\n' |>
>>>
>>> hexdump(a)
0000 FF FF FF FF FF FF 02 42 AC 1F 80 3C 08 00 45 00 .......B...<..E.
0010 00 43 00 01 00 00 40 06 C9 F0 AC 1F 80 3C 68 12 .C....@......<h.
0020 1C 56 00 14 00 50 00 00 00 00 00 00 00 00 50 02 .V...P........P.
0030 20 00 0C EE 00 00 47 45 54 20 2F 69 6E 64 65 78 .....GET /index
0040 2E 68 74 6D 6C 20 48 54 54 50 2F 31 2E 30 20 0A .html HTTP/1.0 .
0050 0A .
>>>
现在,我想知道,例如,
dport
中的TCP
字段有什么偏移量。或者所有层中的所有字段。
我可以用
scapy
打印它们吗?有没有一种方法可以适用于所有协议,包括自定义协议?
有趣的问题。我不相信目前有任何内置的方法可以做到这一点,而且我真的想不出一个用例。
最接近的东西,纯粹为了提供信息,可能是:
pdfdump()
(及类似)功能:https://scapy.readthedocs.io/en/latest/usage.html#graphical-dumps-pdf-psrfc()
功能>>> rfc(TCP)
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| SPORT | DPORT |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| SEQ |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ACK |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|DATAOFS|RESER| FLAGS | WINDOW |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| CHKSUM | URGPTR |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| OPTIONS |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Fig. TCP
但是如果你真的想要一个数值,匹配一个字段从第一个字节开始的偏移量,你自己做起来并不难,比如:
def calc_offset(packet, layer, field):
"""Calculate the offset of a field, in a packet"""
offset = 0
while packet: # for each payload
for fld in packet.fields_desc: # for each field
if fld.name == field and isinstance(packet, layer):
return int(offset)
offset += fld.i2len(packet, packet.getfieldval(fld.name)) # add length
packet = packet.payload
return -1
在你的例子中:
>>> a=Ether()/IP(dst="www.slashdot.org")/TCP()/"GET /index.html HTTP/1.0 \n\n"
>>> calc_offset(a, TCP, "dport")
36
>>> struct.unpack("!H", bytes(a)[36:36+2])[0]
80
>>> a.dport
80
希望这有帮助
为了完整起见,这里有一个函数来获取/打印所有字段的偏移量。
def field_offsets(packet):
offsets = []
offset = 0
while packet:
for field in packet.fields_desc:
offsets.append((f'{packet.name}.{field.name}', offset))
offset += math.ceil(field.i2len(packet, packet.getfieldval(field.name)))
packet = packet.payload
return offsets
for (f, o) in field_offsets(a):
print(f'{f}: {o}')
Ethernet.dst: 0
Ethernet.src: 6
Ethernet.type: 12
IP.version: 14
IP.ihl: 15
IP.tos: 16
IP.len: 17
IP.id: 19
IP.flags: 21
IP.frag: 22
IP.ttl: 24
IP.proto: 25
IP.chksum: 26
IP.src: 28
IP.dst: 32
IP.options: 36
TCP.sport: 36
TCP.dport: 38
TCP.seq: 40
TCP.ack: 44
TCP.dataofs: 48
TCP.reserved: 49
TCP.flags: 50
TCP.window: 52
TCP.chksum: 54
TCP.urgptr: 56
TCP.options: 58
Raw.load: 58