基本介绍
我曾经写过一篇关于Scapy
使用的文章,但是那篇文章已经是数年前发布的了。而计算机技术发展是爆炸性的,我在发布那篇文章的时候,我常用的 Python 版本是python 2.7
,而直到我现在发出这篇文章的时候,其最新版已经是python 3.12
了。所以几年没上 CSDN 写文章,今天再次回来,我觉得应该首先先再次写一篇这个 Python 之中最为强大的网络编程第三方库——Scapy
的介绍和使用的文章。
那么,接下来便是最首要的几个问题:
1. Scapy是什么?
Scapy是一个功能强大且灵活的Python库,用于操作和探索计算机网络中的数据包。它允许用户构建各种类型的网络数据包,并支持多种网络协议,如TCP、UDP、ICMP、ARP等。Scapy不仅可以发送和接收数据包,还可以捕获、修改和解析网络流量,使用户能够深入研究网络通信并进行网络安全测试。
2. Scapy 的主要功能?
- 构建数据包:Scapy允许用户使用简单的Python代码构建自定义的网络数据包,从头开始创建各种协议的数据包,以满足特定的需求。
- 发送和接收数据包:用户可以使用Scapy发送和接收数据包,通过网络与其他设备进行交互,检查网络服务的可用性或执行自动化网络任务。
- 网络流量捕获:Scapy支持在网络接口上进行实时数据包捕获,并可以将捕获到的流量进行分析和展示。
- 网络流量解析:Scapy可以解析捕获的数据包,从中提取有用的信息,比如源地址、目标地址、协议类型等。
- 网络协议支持:Scapy支持大量网络协议,包括但不限于TCP、UDP、ICMP、ARP、IPv4、IPv6等。
Scapy 使用
构建数据包
你可以使用Scapy
构建任何形式的数据包,它可以使得你无需使用socket
库进行直接定义一个协议的数据包。后者可能常常使得你构建的数据包标识头错误而导致你的数据包失效,而使用Scapy
可以轻松避免这一点。
在使用Scapy
之前,注意不要忘记使用from scapy.all import *
来导入Scapy
中的函数,当然,你也可以指定你需要的内容,譬如from scapy.all import IP, TCP
。
然而,Scapy
这个库的导入比较特殊,事实上,在你指明要从scapy.all
导入的时候,Python 已经完全初始化并导入了所有的Scapy
函数,所以你可以放心大胆的使用*
这么一个通配符来导入Scapy
。
简单一提的是,Scapy
构建数据包实际上是将数据包抽象成了一个Python对象,倘若你对于数据包方面的知识已经有了足够深入的了解,那么实际上你完全可以自己序列化一个原始的数据包并用Python的套接字socket
发送出去。但不管怎么说,Scapy
提供了更方便的接口和使用方法。
1. 构建一个 ACK 数据包
ack_packet = IP(src=source_ip, dst=target_ip)/TCP(sport=RandShort(), dport=target_port, flags="A")
IP
类指明以下信息:
src
:数据包的来源dst
:数据包的发送目的地址
TCP
类指明以下信息:
sport
:指明发出该数据包的本地端口,RandShort()
表示使用随机的未占用端口dport
:指明该数据包发送的目标端口flags
:声明该数据包为ACK
数据包
事实上,这里面s
或者d
开头的其实就是source(来源)
和destination(目的地)
的单词缩写。
黑客常常将src
设置成一个未知的 IP 地址来伪造攻击源,如果你在进行网络安全测试,你可以将dport
设置为80
或者443
来干扰破坏正常计算机的网络访问,因为我们常常使用80
和443
端口作为HTTP
和HTTPS
协议的出端口。
有趣的是,在我数年前写Scapy
的时候,我记得它似乎还并不能像这样创建ACK
数据包。
2. 构建一个 ARP 数据包
arp = ARP()
arp.psrc = selfip
arp.hwsrc = selfmac
arp.pdst = target
arp.op = 2
当然,你也可以这样:
arp = ARP(
psrc=selfip,
hwsrc=selfmac,
pdst=target
op=2
)
这两者是完全等效的,选择哪一种方式纯粹看个人喜好。前者是先声明ARP
类,随后在设置ARP
数据包的相关参数,后者是直接传入所需的参数,在ARP类初始化的过程中就传入数据,但是结果实际上是相同的。在Python解释器更新迭代了这门多年以后,它们的运行效率也几乎没有差别。
类中的参数psrc
是发送者的主机IP
地址,hwsrc
则是该主机的MAC
地址,pdst
则是目标地址。
在Scapy
中,op
参数用于指定ARP数据包的操作码(Operation Code)。ARP数据包的操作码指示ARP请求还是ARP回复,以及其他一些特定类型的ARP消息。
在ARP协议中,有两种主要的操作码:
-
ARP请求(ARP Request):
op = 1
- ARP请求用于查询目标设备的MAC地址。发送ARP请求的设备广播一个ARP请求包,询问网络中是否有某个IP地址对应的MAC地址。
-
ARP回复(ARP Reply):
op = 2
- ARP回复用于响应ARP请求,包含目标设备的MAC地址。当设备接收到对应的ARP请求后,会向发送者回复一个包含MAC地址的ARP回复包。
arp.op = 2
表示构造的ARP数据包是一个ARP回复。这通常用于响应其他设备发送的ARP请求,向其提供目标IP地址对应的MAC地址。
如果你在一个没有实现MAC绑定的网络环境中进行网络干扰的测试,你可以将目的地址pdst
设置为0.0.0.0
,标识该ARP包将在网络环境中广播。
3. 构建一个 SYN 数据包
syn_packet = IP(src=src_ip, dst=target_ip) / TCP(sport=src_port, dport=target_port, flags='S')
打眼一看其实和 ACK 包没什么区别,而实际上,确实没多大的区别。
在 SYN 数据包的构建中,我们声明参数flags
为'S'
,这是告诉Scapy
我们在构建的数据包为 SYN 数据包,清晰明了,SYN 的 flags
是'S'
,ACK 的 flags
是'A'
。
如果没记错的话,在之前我写关于Scapy
文章的时候,构建数据包似乎还没有flags
这种清晰明了的方法。
4. 构建一个 ICMP 数据包
其实 ICMP 应该是所有入坑计算机的人除了 HTTP HTTPS 之外最熟悉的协议,因为它常常用来实现ping
操作。
icmp_packet = IP(src=src_ip, dst=target_ip) / ICMP(type=8, code=0)
对于 IP 这里就不解释了,看上文即可。
ICMP 类中含有两个参数:type
和code
。
type
参数可以是以下括号内的值:
- Echo Reply (type=0): 用于响应ICMP Echo Request消息,通常用于Ping操作。
- Destination Unreachable (type=3): 表示目标不可达,可能由于网络问题、端口未打开等引起。
- Redirect (type=5): 用于重定向流量,指示源主机将流量发送到不同的路由器。
- Echo Request (type=8): 用于发出Ping请求,通常发送到目标主机以检查是否可以到达。
- Time Exceeded (type=11): 表示数据包在路由过程中超过了最大生存时间(TTL),可能由于网络问题引起。
- Parameter Problem (type=12): 表示在IP头部中发现了问题,通常由于配置错误引起。
- Timestamp Request (type=13) 和 Timestamp Reply (type=14): 用于获取和回复时间戳信息。
- Information Request (type=15) 和 Information Reply (type=16): 用于获取和回复网络信息。
- Address Mask Request (type=17) 和 Address Mask Reply (type=18): 用于获取和回复子网掩码信息。
这里我们选择type=8
,这意味着发送该数据包以后,相当于进行了一次ping
响应请求。
这等价于在终端中执行:
ping src_ip
当然,src_ip
应当被替换为合理的IP地址或域名,如果你希望简单的实现更多高级的 ping 操作,你可以选择使用其它的库来完成,例如ping3
。