结合调试开发板的前期需求,需要一个工具来完成发送指定信息报文的作用,几经搜索之下发现了较为强大的Spacy工具,在此对其进行相关功能测试。本测试的最终目的是能够使得开发板能够发送指定目的MAC及VLAN ID的数据包,并随着不同实验的进行可以按照计划发送大量符合计划的数据包。
1. Scapy简介
1.1 概述
Scapy
是一个可以让用户发送、侦听和解析并伪装网络报文的Python程序。这些功能可以用于制作侦测、扫描和攻击网络的工具。
换言之,Scapy
是一个强大的操纵报文的交互程序。它可以伪造或者解析多种协议的报文,还具有发送、捕获、匹配请求和响应这些报文以及更多的功能。Scapy
可以轻松地做到像扫描(scanning)、路由跟踪(tracerouting)、探测(probing)、单元测试(unit tests)、攻击(attacks)和发现网络(network discorvery)这样的传统任务。它可以代替hping
,arpspoof
,arp-sk
,arping
,p0f
甚至是部分的Namp
,tcpdump
和tshark
的功能。
Scapy
在大多数其它工具无法完成的特定任务中也表现优异,比如发送无效帧、添加自定义的802.11的帧、多技术的结合(跳跃攻击(VLAN hopping)+ARP缓存中毒(ARP cache poisoning)、在WEP加密信道(WEP encrypted channel)上的VOIP解码(VOIP decoding))等等等等。
理念非常简单。Scapy
主要做两件事:发送报文和接收回应。通过人工定义一系列的报文,它发送这些报文,收到回应,将收到的回应和请求匹配,返回一个存放着(request, answer)即(请求, 回应)的报文对(packet couples)的列表(list)和一个没有匹配的报文的列表(list)。这样对于像Nmap
和hping
这样的工具有一个巨大的优势:回应没有被减少 (open/closed/filtered)而是完整的报文。
1.2 基于Python的快速报文设计
其它的工具坚持命令行运行的模式,这导致描述一个报文需要糟糕的语法。对于这些工具,解决的方法是在其作者想像的情景下,采用一种更高层但是功能更弱的描述方法。举例来说,在端口扫描的情景中,端口扫描器必需的参数只有IP地址。即使情景有所改变,情况依然如此(Even if the scenario is tweaked a bit, you still are stuck to a port scan)。
Scapy
的原则是推荐使用一种特定领域语言(Domain Specific Language ,DSL)以达到对于任何种类报文的功能强大并快速的描述。使用Python
语法和Python
解释器作为特定领域语言(DSL)的语法和解释器有许多优势:没有必要写一个单独的解释器,用户不需要再学一种新语言并可以从这个完整、简约且非常强大的语言中受益。
Scapy
允许用户将一个或一系列报文描述成为一个个堆起来的层(layer)。每层的数据域有有用的且可重载的默认值。Scapy
不强制用户使用预先定义的方法和模板。这样每次碰到不同的情景时写新工具的需要得到了减少。在C语言中,描述一个报文可能平均要用60行代码。使用Scapy
,发送的报文可能仅需一行代码描述再加一行打印结果的代码。90%的网络探测工具可以使用Scapy
使用2行代码重新实现。
2. 生成数据包相关语法简要介绍
2.1 生成数据包相关命令
在scapy中,应用层之下的数据包,基本使用协议大写对应的方法就可以直接生成。如:
# 使用Ether()方法生成一个以太网层数据包
eth_packet = Ether()
# 使用IP()方法生成一个网络层数据包
ip_packet = IP()
# 使用TCP()方法生成一个tcp数据包
tcp_packet = TCP()
# 使用UDP()方法生成一个udp数据包
udp_packet = UDP()
# 使用ICMP()方法生成一个udp数据包
icmp_packet = ICMP()
若有IP地址,MAC地址,VLAN ID等详细信息的指定,可在( )之内进行相关信息的描述。具体示例可见后续的简单测试。
2.2 查看数据包内容相关命令
生成数据包后需查看数据包的详细信息时可使用此部分相关命令。大部分协议的数据包查看都是类似的,我们这里以一个tcp数据包为例,查看其他协议的数据包类似操作即可。
# 使用IP()方法生成一个tcp数据包
ip_packet = IP()
#方法一:使用ls() 查看数据包可以有哪些参数。
ls(IP())
# 方法二:使用raw()方法查看
raw(ip_packet)
# 方法三:使用hexdump()查看。类似Wireshark,查看数据包的字节信息。
hexdump(ip_packet)
# 方法四:使用raw()配合协议类查看,为最佳方法
# 查看该数据包以太网层内容(下层内容不层示,上层内容不解析只以load形式展示)
Ether(raw(ip_packet))
# 查看该数据包网络层内容(下层内容不层示,上层内容不解析只以load形式展示)
IP(raw(ip_packet))
2.3 自定义字段值
若在IP( )中不指定任何信息则数据包中各字段的值都是根据本机信息自动生成的,下面介绍自定义各字段值的方法。
定义字段的值有两个种方法,一种是在构造时直接传递参数,另一种是在生成后重新赋值;
以修改源IP地址为例,使用IP(src="114.114.114.114",ttl=128) 来创建一个源地址是 114.114.114.114 、ttl是128的数据包,再使用 ls() 可以看到数据包的源地址已经修改。
# 方法一,在构造时直接传递参数
# 给src传值114.14.114.114,ttl传值128;字段为字符的以字符串形式传,字段为数值的以数值形式传
ip_packet = IP(src="114.14.114.114",ttl=128)
# 查看数据包各项值,确认src项是否为114.14.114.114,ttl项是否为128
ls(ip_packet))
# 方法二,在生成后重新赋值
# 给src赋值192.14.114.114,ttl赋值128;字段为字符的以字符串形式赋,字段为数值的以数值形式赋
ip_packet.src = "192.14.114.114"
ip_packet.ttl = 200
# 查看数据包各项值,确认src项是否为192.14.114.114,ttl项是否为200
IP(raw(ip_packet))
也可以使用 show 方法来查看数据包信息。
使用summary()方法查看概要信息。
2.4 同时定义多层协议的字段
在定义源IP地址后可通过构造多层协议来同时指定源MAC地址,进行跨层数据的指定,构造函数可使用“/”隔开,低层函数在前高层函数在后;最后使用构造函数中的最低层函数即可查看数据包内容。
# 构造一个IP数据包,源mac设置为"00:00:00:00:00:11",源ip设置为"10.10.6.92"
ip_packet = Ether(src="00:00:00:00:00:11")/IP(src="10.10.6.92")
# 当前构造函中最低层为Ether
Ether(raw(ip_packet))
# 定义一个TCP数据包,源mac设置为"00:00:00:00:00:11",源ip设置为"10.10.6.92",源端口设置为1234
tcp_packet = Ether(src="00:00:00:00:00:11")/IP(src="10.10.6.92")/TCP(sport=1234)
# 当前构造函中最低层为Ether
Ether(raw(tcp_packet))
# 定义一个应用层数据包,应用层内容为"GET / HTTP/1.0\r\n\r\n"
app_packet = IP()/TCP()/"GET / HTTP/1.0\r\n\r\n"
# 当前构造函中最低层为IP
IP(raw(app_packet))
3. 发送数据包
3.1 发送数据包相关命令
经过以上章节构造完数据包,就可以发送了。scapy发送数据包有常用的如下几种方法:
(1)send(pkt) 发送三层数据包,但不会受到返回的结果。
(2)sr(pkt) 发送三层数据包,返回两个结果,分别是接收到响应的数据包和未收到响应的数据包。
(3)sr1(pkt) 发送三层数据包,仅仅返回接收到响应的数据包。
(4)sendp(pkt) 发送二层数据包。
(5)srp(pkt) 发送二层数据包,并等待响应。
(6)srp1(pkt) 发送第二层数据包,并返回响应的数据包。
3.2 相关示例
例1:使用生成数据包命令发送一个源IP地址为192.168.137.33,目的MAC地址为 7E:6A:4B:00:00:01的数据包并进行发送。
#构造符合条件的数据包
ip_packet = Ether(dst="7E:6A:4B:00:00:01")/IP(src="192.168.137.33")
#发送相应数据包
sendp(ip_packet)
传输层及应用层数据报生成同理。
# 定义一个TCP数据包,源mac设置为"00:00:00:00:00:11",源ip设置为"10.10.6.92",源端口设置为1234
tcp_packet = Ether(src="00:00:00:00:00:11")/IP(src="10.10.6.92")/TCP(sport=1234)
# 当前构造函中最低层为Ether
Ether(raw(tcp_packet))
# 定义一个应用层数据包,应用层内容为"GET / HTTP/1.0\r\n\r\n"
app_packet = IP()/TCP()/"GET / HTTP/1.0\r\n\r\n"
# 当前构造函中最低层为IP
IP(raw(app_packet))
3.3 使用Scapy创建一个指定目的MAC地址并带有VLAN ID的数据包
利用scapy命令生成并发送指定的带有vlan标签的数据包
# 定义一个带有vlan ID的TCP数据包,目的mac设置为"6B:7C:00:01:4E:89",目的ip设置为"10.10.6.92",源端口设置为1234,且携带数据为“Hello World!”
from scapy.all import *
data="Hello world!"
packet_vlan = Ether(dst="6B:7C:00:01:4E:89")/Dot1Q(vlan=1)/IP(dst="192.168.4.2")/TCP(sport=1234)
#发送该数据包
sendp(packet_vlan)
# 当前构造函中最低层为Ether
Ether(raw(tcp_packet))
wireshark默认不捕获带有vlan id的数据包,通过额外设置,wireshark可显示出vlan id信息。具体设置方法见下文。
4. 使用wireshark捕获带有vlan id数据包的方法
捕获带有vlan标签的数据包有很多种方法,在Windows环境下最常用的抓包工具为wireshark,而在开发板环境下则比较推荐tcpdump工具。在本部分内容中先对wireshark捕获带有vlan标签的数据包相关设置方法进行介绍,随着后续开发板调试的进行,再对tcpdump工具使用方法进行学习。
按照搜索显示的最常用的通过菜单栏-编辑-首选项-外观-列-添加vlan列信息的方法对本机并不适用,按照步骤操作后选项中无802.1Q。
修改电脑注册表
早期网卡的驱动不会对VLAN TAG进行处理,而是直接送给上层处理,在这种环境下,WireShark可以正常抓到带VLAN TAG的报文。
而Intel,broadcom,marvell的网卡则会对报文进行处理,去掉TAG后再送到上层处理,所以WireShark在这种情况下通常抓不到VLAN TAG。这时我们需要针对这些网卡做一些设置,WireShark才能够抓取带VLAN TAG的报文。
(1)选择Intel网卡的本地连接,右键属性,选择Microsoft网络客户端,点击配置
(2)选择高级,找到Priority & VLAN(中文版为优先级和VLAN)并选择Disabled(中文版为禁止),确定保存。(部分为使能,根据自身情况设定)
(3)选择详细信息,属性找到驱动程序关键字,记录值。
(4)win键+R,输入regedit,进入注册表编辑器。
(5)进入HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Class{4d36e972-e325-11ce-bfc1-08002be10318}\0014
查看 MonitorMode的值是否为1,MonitorModeEnabled的值是否为1.
若不存在,则新建 DWORD(32位),文件名分别为MonitorMode、MonitorModeEnabled,设置值为1。注意设置完后重启电脑。
(6)重启电脑再进行抓包,本文是又将wireshark卸载再重新安装一次再进行抓包,就发现VLAN tag不会被网卡移除。
参考文档:
1. 【原创】在windows上用Wireshark抓取带有VLAN标记的报文 - Cisco Community
2. 利用scapy发送带vlan标签的以太帧_scapy怎么创建带vlan的以太头-CSDN博客
3. https://www.cnblogs.com/Chinori/p/11560211.html
标签:00,IP,报文,Scapy,packet,测试,ip,工具,数据包 From: https://blog.csdn.net/hqq2312/article/details/136741260