scapy库

交互式网络分组处理模块。可以用于构造或者解码大量的数据包协议,发送,捕获数据包并匹配请求和回复。

导入scapy库

from scapy.all import *

构造数据包

  1. 简单构造
  1. 直接构造默认数据包
>>> a=IP() #不带参数表示构造默认的IP数据包
 >>> a.show() #查看数据包a的相关信息
 ###[ IP ]### 
 version   = 4
 ihl       = None
 tos       = 0x0
 len       = None
 id        = 1
 flags     = 
 frag      = 0
 ttl       = 64 
 proto     = hopopt
 chksum    = None
 src       = 127.0.0.1 #源地址
 dst       = 127.0.0.1 #目标地质
 \options   \

 >>>
  1. 修改默认数据包的参数
>>> a.src='123.123.123.123'
 >>> a.dst='2.2.2.2'
 >>> a.show()
 ###[ IP ]### 
 version   = 4
 ihl       = None
 tos       = 0x0
 len       = None
 id        = 1
 flags     = 
 frag      = 0
 ttl       = 64
 proto     = hopopt
 chksum    = None
 src       = 123.123.123.123
 dst       = 2.2.2.2
 \options   \

 >>>
  1. 构造数据包时指定参数
>>>b=IP(src='32.23.23.3',dst='1.1.1.1')
>>> b.show()
###[ IP ]### 
version   = 4
ihl       = None
tos       = 0x0
len       = None
id        = 1
flags     = 
frag      = 0
ttl       = 64
proto     = hopopt
chksum    = None
src       = 32.23.23.3
dst       = 1.1.1.1
\options   \

>>>

对于其他协议数据包上述方法同样适用

2. 构造协议栈

Python实现数据包的发送与信息提取 python 转发数据包_Python实现数据包的发送与信息提取

一个完整的数据包是由多个协议组成的(即从应用层到物理层会不断封装每一层的协议),scapy也可以采用分层次的方式实现各层协议,利用"\"来实现不同协议数据的拼接

>>> IP()
 <IP  |> #当只有一个协议数据包时,发现默认没有字段
 >>> IP()/TCP()
 <IP  frag=0 proto=tcp |<TCP  |>> #当有2层协议时(IP网络层,TCP传输层)时,发现IP数据包的proto字段(即Protocol协议字段,长度8比特。标识了上层所使用的协议。)被重载为tcp,frag字段(即片偏移(Fragment Offset)长度13比特。表示该IP包在该组分片包中位置,接收端靠此来组装还原IP包。)为0
 >>>

查看数据包

  1. ls():显示详细的信息
>>> ls(a)
 version    : BitField  (4 bits)                  = 4               (4)
 ihl        : BitField  (4 bits)                  = None            (None)
 tos        : XByteField                          = 0               (0)
 len        : ShortField                          = None            (None)
 id         : ShortField                          = 1               (1)
 flags      : FlagsField  (3 bits)                = <Flag 0 ()>     (<Flag 0 ()>)
 frag       : BitField  (13 bits)                 = 0               (0)
 ttl        : ByteField                           = 64              (64)
 proto      : ByteEnumField                       = 0               (0)
 chksum     : XShortField                         = None            (None)
 src        : SourceIPField                       = '123.123.123.123' (None)
 dst        : DestIPField                         = '2.2.2.2'       (None)
 options    : PacketListField                     = []              ([])
 >>>
  1. show():显示更为简洁的信息
>>> a.show()
 ###[ IP ]### 
 version   = 4
 ihl       = None
 tos       = 0x0
 len       = None
 id        = 1
 flags     = 
 frag      = 0
 ttl       = 64
 proto     = hopopt
 chksum    = None
 src       = 123.123.123.123
 dst       = 2.2.2.2
 \options   \

 >>>
  1. 以图形化显示数据包内容
````
>>> a.pdfdump()

````
需要安装PyX及其依赖项才可以正常使用

数据包发送与接收

需要管理员权限运行

  1. 发送
  1. send():在网络层发送数据包
>>> from scapy.all import *
 >>> send(IP(dst="www.bing.com"))
 .
 Sent 1 packets.#发现send只会发送没有应答
 >>>
  1. sendp():在数据链路层发送数据包
>>> sendp(IP(dst="www.bing.com"))
 .
 Sent 1 packets.#和send一样
 >>>
  1. 接收
    使用可以在发送数据包后接收响应的函数
  1. sr():返回2个列表,第一个是有应答的answer,第二个是无应答的answer
>>>a,b=sr(IP(dst="202.89.233.101")/TCP(),inter=0.1,retry=1,timeout=1)
Begin emission:
Finished sending 1 packets.
*
Received 1 packets, got 1 answers, remaining 0 packets
>>> a #有应答
<Results: TCP:1 UDP:0 ICMP:0 Other:0>
>>> b #无应答
<Unanswered: TCP:0 UDP:0 ICMP:0 Other:0>
>>> a[0] 
(<IP  frag=0 proto=tcp dst=202.89.233.101 |<TCP  |>>, <IP  version=4 ihl=5 tos=0x0 len=44 id=18168 flags=DF frag=0 ttl=116 proto=tcp chksum=0x1f01 src=202.89.233.101 dst=192.168.44.107 |<TCP  sport=http dport=ftp_data seq=2071897819 ack=1 dataofs=6 reserved=0 flags=SA window=65392 chksum=0xd527 urgptr=0 options=[('MSS', 1440)] |>>)  
>>>

参数说明:
inter:设置数据包发送的时间间隔
retry:设置无应答数据包的重发次数,设为负数则一直发送
timeout:数据包等待时间

  1. sr1():只返回1个列表,有应答的answer。
>>>a=sr1(IP(dst="202.89.233.101")/TCP(),inter=0.1,retry=1,timeout=1)
 Begin emission:
 Finished sending 1 packets.
 ......*
 Received 7 packets, got 1 answers, remaining 0 packets
 >>> a
 <IP  version=4 ihl=5 tos=0x0 len=44 id=26888 flags=DF frag=0 ttl=116 proto=tcp chksum=0xfcf0 src=202.89.233.101 dst=192.168.44.107 |<TCP  sport=http dport=ftp_data seq=2352355025 ack=1 dataofs=6 reserved=0 flags=SA window=65392 chksum=0x547a urgptr=0 options=[('MSS', 1440)] |>>
 >>>a[0]
 <IP  version=4 ihl=5 tos=0x0 len=44 id=26888 flags=DF frag=0 ttl=116 proto=tcp chksum=0xfcf0 src=202.89.233.101 dst=192.168.44.107 |<TCP  sport=http dport=ftp_data seq=2352355025 ack=1 dataofs=6 reserved=0 flags=SA window=65392 chksum=0x547a urgptr=0 options=[('MSS', 1440)] |>>
 >>> a[1]
 <TCP  sport=http dport=ftp_data seq=2352355025 ack=1 dataofs=6 reserved=0 flags=SA window=65392 chksum=0x547a urgptr=0 options=[('MSS', 1440)] |>
  1. srp():前两个工作在网络层,srp工作在数据链路层 ,使用方法和sr()一样
  1. 循环收发函数
>>>a,b=srloop(IP(dst="202.89.233.101")/TCP(),inter=0.1,retry=1,timeout=1)
 RECV 1: IP / TCP 202.89.233.101:http > 192.168.44.107:ftp_data SA
 RECV 1: IP / TCP 202.89.233.101:http > 192.168.44.107:ftp_data SA
 RECV 1: IP / TCP 202.89.233.101:http > 192.168.44.107:ftp_data SA
 RECV 1: IP / TCP 202.89.233.101:http > 192.168.44.107:ftp_data SA
 RECV 1: IP / TCP 202.89.233.101:http > 192.168.44.107:ftp_data SA
 RECV 1: IP / TCP 202.89.233.101:http > 192.168.44.107:ftp_data SA
 RECV 1: IP / TCP 202.89.233.101:http > 192.168.44.107:ftp_data SA
 RECV 1: IP / TCP 202.89.233.101:http > 192.168.44.107:ftp_data SA
 RECV 1: IP / TCP 202.89.233.101:http > 192.168.44.107:ftp_data SA
 RECV 1: IP / TCP 202.89.233.101:http > 192.168.44.107:ftp_data SA
 RECV 1: IP / TCP 202.89.233.101:http > 192.168.44.107:ftp_data SA
 RECV 1: IP / TCP 202.89.233.101:http > 192.168.44.107:ftp_data SA
 RECV 1: IP / TCP 202.89.233.101:http > 192.168.44.107:ftp_data SA
 RECV 1: IP / TCP 202.89.233.101:http > 192.168.44.107:ftp_data SA
 RECV 1: IP / TCP 202.89.233.101:http > 192.168.44.107:ftp_data SA
 RECV 1: IP / TCP 202.89.233.101:http > 192.168.44.107:ftp_data SA
 RECV 1: IP / TCP 202.89.233.101:http > 192.168.44.107:ftp_data SA
 RECV 1: IP / TCP 202.89.233.101:http > 192.168.44.107:ftp_data SA
 RECV 1: IP / TCP 202.89.233.101:http > 192.168.44.107:ftp_data SA
 ^C d... 
 Sent 19 packets, received 19 packets. 100.0% hits. #发送19个数据包
 >>> a
 <Results: TCP:19 UDP:0 ICMP:0 Other:0># 19个回复包
 >>>

随机值填充协议字段

fuzz()函数使用一个随机值填充字段

>>> a=IP()
>>> a.show()
###[ IP ]### 
version   = 4
ihl       = None
tos       = 0x0
len       = None
id        = 1
flags     = 
frag      = 0
ttl       = 64
proto     = hopopt
chksum    = None
src       = 127.0.0.1
dst       = 127.0.0.1
\options   \
>>> a=fuzz(IP())#使用fuzz函数模糊默认IP数据包
>>> a.show()
###[ IP ]### 
version   = <RandNum>
ihl       = None
tos       = <RandByte>
len       = None
id        = <RandShort>
flags     = MF+evil
frag      = <RandNum>
ttl       = <RandByte>
proto     = <RandByte>
chksum    = None
src       = 127.0.0.1
dst       = 127.0.0.1
\options   \
>>>