赞
踩
Scapy是一个强大的交互式数据包处理程序(使用python编写)。它能够伪造或者解码大量的网络协议数据包,能够发送、捕捉、匹配请求和回复包等等。
Scapy起源于Linux,但在windows上也可以安装,具体步骤见下面链接:
https://www.cnblogs.com/qingkongwuyun/p/8508733.html
但是Scapy学习资料比较少,涉及的网络协议比较复杂,所以不太好学。我们首先来看一个简单的例子:
- # -*- coding: utf-8 -*-
- from scapy.all import srp, Ether, ARP
-
- arp_request=Ether(dst='FF:FF:FF:FF:FF:FF')/ARP(pdst='192.168.1.232')
- arp_request.show()
先来看看ARP函数结构:
- >>> ls(ARP)
- hwtype : XShortField = (1)
- ptype : XShortEnumField = (2048)
- hwlen : ByteField = (6)
- plen : ByteField = (4)
- op : ShortEnumField = (1) 取值为1或者2,代表ARP请求或者响应包。{"who-has":1, "is-at":2}
-
- hwsrc : ARPSourceMACField = (None) 发送方Mac地址。
- psrc : SourceIPField = (None) 发送方IP地址。
- hwdst : MACField = ('00:00:00:00:00:00') 目标Mac地址。
- pdst : IPField = ('0.0.0.0') 目标IP地址。
Ether函数:
- >>> ls(Ether)
- dst : DestMACField = (None) 目的MAC
- src : SourceMACField = (None) 源MAC
- type : XShortEnumField = (36864)
- 这个op选项很重要,1为ARP请求,2为ARP应答。
- 构造一个以太网数据包通常需要指定目标和源MAC地址,如果不指定,
- 默认发出的就是广播包ff:ff:ff:ff:ff:ff,即向同一网段内的所有主机发出询问
关于Ether协议,上面的三个属性只代表Ether的头部,完整的Ether由以下几部分组成:
FCS(Frame Check Sequence)表示尾帧,用来检查帧在传输的过程中是否损坏。类型(type)表示后面的数据是属于哪种类型的数据,例如Type为0x0800时为IP协议包,Type为8060时,后面为ARP协议包,RARP为8035,IPv6为86DD等。
Ether本身不是个完整的东西,它只是传递其它协议数据的中转站。
关于ARP的op值,我们举个例子:
- arp_frame = Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(op=1, pdst="10.0.0.3")
- resp,unans = srp(arp_frame)
- #可以看出,op=1时,构造一个ARP请求,既然是请求,就需要应答,所以srp函数接受应答的数据。
- ....
- packet = scapy.ARP(op=2, pdst=dest_ip, hwdst=dest_mac, psrc=source_ip, hwsrc=source_mac)
- scapy.send(packet, count=4, verbose=False)
- #此时op=2,表示告知对方某某事物,不需要回答,所以采用send函数就可以了
上面的程序构建了一个Ether()/ARP()数据包。‘/’符号被重载为“叠加”,即在Ether数据包上面再叠加一层ARP数据。运行结果如下:
从上面的图可以看出,[ARP]后面的东西就是ARP()数据包叠加的相关数据参数。
关于以太网的数据格式及传输,可参考下面文章:
http://www.cnblogs.com/qishui/p/5437301.html
下面回到正题,扫描局域网上存活的主机及MAC地址,先贴代码:
- # -*- coding: utf-8 -*-
- from scapy.all import srp, Ether, ARP
-
- IpScan = '192.168.0.0/24'
- try:
- #使用Ether()/ARP()构造ARP包
- packet = Ether(dst="FF:FF:FF:FF:FF:FF")/ARP(pdst=IpScan)
- #srp():发送与接收ARP包,返回一个元组。元组的第一个元素就是收到的数据包,第二个指未收到的包
- ans,_ = srp(packet, timeout=2)
- except Exception as e:
- print(e)
- else:
- #解析获取的包的信息,得到局域网中存活的主机的IP地址和MAC地址
- for _, rcv in ans:
- # ListMACAddr = rcv.sprintf("%Ether.src%---%ARP.psrc%")
- # print(ListMACAddr)
- print(rcv[ARP].psrc,'----',rcv.src)
上面代码中的rcv变量,存放的就是类似于Ether()/ARP()构造的数据包,可以依据前面列出的相关属性进行访问。
其实还有个极简单的方式扫描局域网,那就是arping()方法,如下:
一步到位,真强!
参考文章:
https://zhuanlan.zhihu.com/p/34843290
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。