在前两篇博客中,笔者简单分享了如何使用scapy
进行网络流量的分析,但比较粗略,没有详细说明,本文我们就0开始,一起快速学习一下scapy
框架的使用。
另附之前的两篇博客,有需要快速参考代码的请自取:
使用Scapy框架分析HTTP流量
使用 Scapy 分析网络包:Python 网络编程的利器
Scapy
Scapy is a powerful interactive packet manipulation library written in Python. Scapy is able to forge or decode packets of a wide number of protocols, send them on the wire, capture them, match requests and replies, and much more.
根据官方的说法, scapy
的功能是 “packets manipulation in Python”,即用python操控packet, 这个说法相当贴切。
对于python的版本是有要求的,当前是需要高于 python 3.7
.
安装
可以用pip非常方便的安装
pip install scapy
同时可以clone代码
git clone --depth 1 https://github.com/secdev/scapy
cd scapy
sudo ./run_scapy
应用
下面我们通过一些具体的例子快速学习框架的使用
操作packet
scapy
中有一个特殊的运算符/
,作用是 “stack packets”,把packet堆叠起来.
我们实际操作一下。
>>> packet = IP()/TCP()
>>> Ether()/packet
输出
<Ether type=IPv4 |<IP frag=0 proto=tcp |<TCP |>>>
还可以列出packet中的字段,用ls
方法
>>> ls(IP,verbose=True)
version : BitField (4 bits) = ('4')
ihl : BitField (4 bits) = ('None')
tos : XByteField = ('0')
len : ShortField = ('None')
id : ShortField = ('1')
flags : FlagsField = ('<Flag 0 ()>')MF, DF, evil
frag : BitField (13 bits) = ('0')
ttl : ByteField = ('64')
proto : ByteEnumField = ('0')
chksum : XShortField = ('None')
src : SourceIPField = ('None')
dst : DestIPField = ('None')
options : PacketListField = ('[]')
并且通过scapy,访问堆叠后的packet字段也非常方便
>>> p = Ether()/IP(dst="www.baidu.com")/TCP(flags="F")
>>> p.summary()
'Ether / IP / TCP 192.168.3.176:ftp_data > Net("www.baidu.com/32"):http F'
>>> print(p.dst)
88:44:77:be:33:41
>>> print(p[IP].src)
192.168.3.176
并且,在一个字段中,可以是有多个值的,通过遍历可以取出
>>> [p for p in IP(ttl=(1,5)) / ICMP()]
[<IP frag=0 ttl=1 proto=icmp |<ICMP |>>,<IP frag=0 ttl=2 proto=icmp |<ICMP |>>,<IP frag=0 ttl=3 proto=icmp |<ICMP |>>,<IP frag=0 ttl=4 proto=icmp |<ICMP |>>,<IP frag=0 ttl=5 proto=icmp |<ICMP |>>]
网络交互
我们用一个DNS查询作为例子展现网络交互. 网络交互的时候,通常会用到一个方法sr1
,注意这里是自然数1,不是字母l.
构造并发送数据包:
>>> dns_req=IP(dst="8.8.8.8")/UDP(dport=53)/DNS(rd=1,qd=DNSQR(qname='baidu.com')
...: )
>>> answer = sr1(dns_req,verbose=0)
>>> print(answer[DNS].an)
[<DNSRR rrname='baidu.com.' type=A rclass=IN ttl=484 rdata=39.156.66.10 |>, <DNSRR rrname='baidu.com.' type=A rclass=IN ttl=484 rdata=110.242.68.66 |>]
IP(dst="8.8.8.8")
:构造一个IP层,目标地址设为8.8.8.8,这是Google的公共DNS服务器。UDP()
:构造一个UDP层。DNS()
:构造一个DNS层,默认是一个空的DNS查询。IP() / UDP() / DNS()
:这三个层级的协议组合成一个完整的数据包。sr1()
:发送这个数据包并等待一个响应包。sr1
函数会返回收到的第一个响应数据包。
提取DNS响应:
answer[DNS].an
answer
是响应的数据包。answer[DNS]
:从响应数据包中提取DNS层。answer[DNS].an
:提取DNS层中的答案部分(an
表示answer)。
通过这段代码,你可以发送一个简单的DNS查询请求到8.8.8.8,并获取这个请求的响应包,然后从响应包中提取DNS的答案部分。如果DNS查询成功并且有答案,这个部分将包含DNS响应的详细信息,如域名对应的IP地址等。如果没有答案,answer[DNS].an
可能为None
。
可视化
scapy支持plot图形,可以方便我们进行可视化分析,下面我们看一个可视化的例子,为了方便输出图片,我们用jupyter.
# import所需要的包
from scapy.all import *
我们需要用srloop
这个方法
srloop: Send a packet at layer 3 in loop and print the answer each time
ans, unans = srloop(IP(dst=["8.8.8.8", "8.8.4.4"]) / ICMP(), inter=.1, timeout=.1, count=100, verbose=False)
这段代码的主要功能是发送ICMP(Internet Control Message Protocol,互联网控制消息协议)包到指定的IP地址,然后接收返回的包。
解释如下:
-
IP(dst=["8.8.8.8", "8.8.4.4"]) / ICMP()
:这部分代码创建了一个ICMP包,目标IP地址是"8.8.8.8"和"8.8.4.4"。/
操作符在Scapy中用来组合多个网络层的包。 -
srloop(...)
:这是Scapy的一个函数,用来发送包并接收响应。它会持续发送网络包,直到满足一定的条件。 -
inter=.1
:这是发送包之间的时间间隔,单位是秒。这里设置为0.1秒。 -
timeout=.1
:这是等待响应的超时时间,单位是秒。这里设置为0.1秒。 -
count=100
:这是发送包的数量。 -
verbose=False
:这是一个选项,决定是否打印详细的操作信息,设置为False则不打印。
最后,srloop
函数返回两个值:ans
和unans
。ans
是一个列表,包含了接收到的响应包。unans
也是一个列表,包含了没有接收到响应的包。
然后我们进行可视化
%matplotlib inline
ans.multiplot(lambda x_y: (x_y[1][IP].src, (x_y[1].time, x_y[1][IP].id)), plot_xy=True)
输出效果如下图所示
小结
本文介绍了scapy的安装使用,并通过例子给出了scapy强大功能的直接展现,希望本文能够帮助大家快速入门这个优秀的网络分析库,欢迎交流