0x00 scapy安装以及环境配置
学习自知乎大佬 ——弈心——网络工程师的Python之路—Scapy基础篇
复现了一波
scapy安装:
pip install scapy
导入scapy方式:
from scapy.all import *
然后是环境配置
kali的IP地址为192.168.43.245,使用的网卡为eth0
物理机的IP地址为192.168.43.1,就是kali的网关
进入scapy,这里我是在kali2020里面进行发送scapy构造的数据包,然后在本机用wireshark进行抓包接收。
物理机监听kali使用的这块网卡
然后是scapy的一些基本用法
首先是ls()命令,用来查看scapy支持的网络协议
除了ls()外,还可以用lsc()函数来查看scapy的指令集(函数)
这里还可以用使用ls()的携带参数模式,比如ls(IP)来查看IP包的各种默认参数。
0x01 实验1
实验目的:使用IP()函数构造一个目的地址为192.168.2.11(即拓扑中的交换机S1)的IP报文,然后用send()函数将该IP报文发送给S1,在S1上开启debug ip packet以验证是否收到该报文。
首先用IP()函数构造一个目的地址为192.168.43.1的IP报文,将其实例化给ip这个变量
ls(ip)查看这个报文的内容
然后用send()将这个数据包发送给物理机,send()函数只发送不接受
可以看到物理机已经接收到了这个ip报文
0x02 实验2
实验目的:除了send()外,scapy还有个sendp()函数,两者的区别是前者是发送三层报文,后者则是发送二层报文,实验2将演示如何用sendp()来构造二层报文。
除了send()外,scapy还有个sendp()函数,两者的区别是前者是发送三层报文,后者则是发送二层报文,实验2将演示如何用sendp()来构造二层报文。
先构造一个arp报文,如下
arp = Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(hwsrc="00:0c:29:ef:29:24",psrc="192.168.43.245",pdst="192.168.43.1")/'abc'
这里我们构造了一个源MAC地址为00:0c:29:ef:29:24, 源IP地址为192.168.43.245,,目标IP地址为192.168.43.1,payload为abc的ARP报文。
然后sendp()发送出去
sendp(arp)
可以看到物理机接收到了来自kali的arp数据包,询问192.168.43.1的mac地址,并且物理机也把自己的mac地址返回给了kali
0x03 实验3
实验目的:从实验1和实验2的例子可以看出:send()和sendp()函数只能发送报文,而不能接收返回的报文。如果要想查看返回的3层报文,需要用到sr()函数,实验3将演示如何使用sr()函数。
先构造一个目的地址为物理机的ICMP()包。可以看到返回的结果是一个tuple(元组),该元组里的元素是两个列表,其中一个列表叫Results(响应),另一个叫Unanswered(未响应)。
我们可以将sr()函数返回的元组里的两个元素分别赋值给两个变量,第一个变量叫ans,对应Results(响应)这个元素,第二个变量叫unans,对应Unanswered(未响应)这个元素。
wireshark捕获到了发送给物理机的icmp包和物理机的应答包
0x04 实验4
实验目的:实验3讲到了sr(),它是用来接收返回的3层报文。实验4将使用srp()来接收返回的2层报文。
用srp()配合Ether()和ARP()构造一个arp报文,二层目的地址为ff:ff:ff:ff:ff:ff,三层目的地址为192.168.2.0/24, 因为我们是向整个/24网络发送arp, 耗时会很长,所以这里用timeout = 5,表示将整个过程限制在5秒钟之内完成
ans, unans = srp(Ether(dst = "ff:ff:ff:ff:ff:ff") / ARP(pdst = "192.168.43.0/24"), timeout = 5)
wireshark捕获到了从192.168.43.1到192.168.43.254的整个c段的arp包,因为只有192.168.43.1(物理机)、192.168.43.2(dns服务器)和192.168.43.245(kali),所以只会收到三个应答包
下面用ans.summary()来具体看看到底是哪3个IP响应了我们的’who has’类型的arp报文。
ans.summary()
用unans.summary()来查看那些没有给予我们’who has’类型arp报文回复的IP地址
可以看到询问其他IP的’who has’类型arp报文没有人响应。我们可以用这个方法来写一个python判断存活主机的脚本,向局域网整个段发送arp、icmp请求,如果收到回应即为存活,否则为不存活。可以参考这篇博客:使用python的scapy和nmap模块进行主机存活探测
0x04 实验5
实验目的:使用tcp()函数构造四层报文,理解和应用RandShort(),RandNum()和Fuzz()函数。
用nmap来扫描一下物理机开启了哪些端口,这里就用8082端口来测试
在scapy上使用ip()和tcp()函数来构造一个目的地IP为192.168.43.1(物理机),源端口为30,目的端口为8082的TCP SYN报文。
ans, unans = sr(IP(dst = "192.168.43.1") / TCP(sport = 30, dport = 8082, flags = "S"))
wireshark捕获到了三次tcp握手
TCP端口号除了手动指定外,还可以使用RandShort(), RandNum()和Fuzz()这几个函数来让scapy帮你自动生成一个随机的端口号,通常可以用作sport(源端口号)。
首先来看RandShort(),RandShort()会在1-65535的范围内随机生成一个TCP端口号,将上面的sport = 30 替换成 sport = RandShort()即可使用。
ans, unans = sr(IP(dst = "192.168.43.1") / TCP(sport = RandShort(), dport = 8082, flags = "S")/"test")
这里可以看到RandShort()替我们随机生成了53780这个TCP源端口号
如果你想指定scapy生成端口号的范围,可以使用RandNum(),比如你只想在1000-1500这个范围内生成端口号,可以使用RandNum(1000,1500)来指定,举例如下:
ans, unans = sr(IP(dst = "192.168.43.1") / TCP(sport = RandNum(666,888), dport = 8082, flags = "S")/"test")
这里RandNum()帮我们生成了837这个源端口号
转载:https://blog.csdn.net/qq_44657899/article/details/115838385