1 Scapy 中的 TCP/IP 类

对于 TCP/IP 中的每个协议,Scapy 都定义了一个对应的类,包括 Ether, ARP, IP, ICMP, TCP, UDP, DNS 等等。要构造数据包的头部,我们需要知道每个头部字段的名字。可以使用 ls 函数找到这些名字。

以下是一个示例,它列出了 IP 头部的所有字段名(第三列表示未设置值时使用的默认值):

$ python3
>>> from scapy.all import *
>>> ls(IP)
version    : BitField  (4 bits)       = (4)
ihl        : BitField  (4 bits)       = (None)
tos        : XByteField               = (0)
len        : ShortField               = (None)
id         : ShortField               = (1)
flags      : FlagsField  (3 bits)     = (<Flag 0 ()>)
frag       : BitField  (13 bits)      = (0)
ttl        : ByteField                = (64)
proto      : ByteEnumField            = (0)
chksum     : XShortField              = (None)
src        : SourceIPField            = (None)
dst        : DestIPField              = (None)
options    : PacketListField          = ([])

 

2 获取每层的信息

每个数据包都有多个层。给定一个数据包,我们经常需要访问该数据包中的某个特定层。了解 Scapy 如何组织这些层可以帮助我们更好地理解如何访问这些层。以下示例首先创建了一个由 Ethernet、IP、UDP 和数据层组成的数据包。

>>> pkt = Ether()/IP()/UDP()/"hello"
>>> pkt
<Ether type=IPv4 |<IP frag=0 proto=udp |<UDP |<Raw load='hello' |>>>

每个层的数据部分包含整个下一层,该层由一个对象表示。在 Scapy 中,数据部分的字段名称为 payload。在我们的例子中,该数据包是一个 Ether 对象。其 payload 字段是 IP 对象。IP 对象的 payload 字段是 UDP 对象,而 UDP 对象的 payload 字段是 Raw 对象。最后,Raw对象的 load 字段是实际负载,即字符串 "hello"。

>>> pkt.payload                        🢀 一个 IP 对象
<IP  frag=0 proto=udp |<UDP  |<Raw  load='hello' |>>

>>> pkt.payload.payload                🢀 一个 UDP 对象
<UDP  |<Raw  load='hello' |>>

>>> pkt.payload.payload.payload        🢀 一个 Raw 对象
<Raw  load='hello' |>

>>> pkt.payload.payload.payload.load   🢀 实际负载
b'hello'

以这种方式访问层将非常繁琐。Scapy 为每个协议类实现了一个名为 getlayer() 的函数,帮助我们获取内层的对象。我们也可以使用数组索引来获取内层对象(实际也是调用了这个函数)。见以下示例。

>>> pkt.getlayer(UDP)
<UDP  |<Raw  load='hello' |>>
>>> pkt[UDP]
<UDP  |<Raw  load='hello' |>>

>>> pkt.getlayer(Raw)
<Raw  load='hello' |>
>>> pkt[Raw]
<Raw  load='hello' |>

如果想检查某个内层是否存在,可以调用 haslayer() ,见以下示例。

>>> pkt.haslayer(UDP)
True
>>> pkt.haslayer(TCP)
0
>>> pkt.haslayer(Raw)
True

 

内容来源:书, Network Security Basics,ch 6

Last modified: Monday, 8 September 2025, 3:55 PM