scapy库
交互式网络分组处理模块。可以用于构造或者解码大量的数据包协议,发送,捕获数据包并匹配请求和回复。
导入scapy库
from scapy.all import *
构造数据包
- 简单构造
- 直接构造默认数据包
>>> 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 \
>>>
- 修改默认数据包的参数
>>> 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 \
>>>
- 构造数据包时指定参数
>>>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. 构造协议栈
一个完整的数据包是由多个协议组成的(即从应用层到物理层会不断封装每一层的协议),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
>>>
查看数据包
- 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 = [] ([])
>>>
- 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 \
>>>
- 以图形化显示数据包内容
````
>>> a.pdfdump()
````
需要安装PyX及其依赖项才可以正常使用
数据包发送与接收
需要管理员权限运行
- 发送
- send():在网络层发送数据包
>>> from scapy.all import *
>>> send(IP(dst="www.bing.com"))
.
Sent 1 packets.#发现send只会发送没有应答
>>>
- sendp():在数据链路层发送数据包
>>> sendp(IP(dst="www.bing.com"))
.
Sent 1 packets.#和send一样
>>>
- 接收
使用可以在发送数据包后接收响应的函数
- 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:数据包等待时间
- 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)] |>
- srp():前两个工作在网络层,srp工作在数据链路层 ,使用方法和sr()一样
- 循环收发函数
>>>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 \
>>>