ARP协议(地址解析协议)属于数据链路层的协议,主要负责根据网络层地址(IP)来获取数据链路层地址(MAC)。
借助Scapy来编写ARP主机发现脚本,通过脚本对以太网内的每个主机都进行ARP请求。若主机存活,则会响应我们的ARP请求,否则不会响应。
Scapy中的ARP参数如下所示:
op代表消息类型:1为ARP请求,2为ARP响应 hwsrc代表源MAC地址 psrc代表源IP地址 hwdst代表目的MAC地址 pdst代表目的IP地址
Scapy中的Ether参数如下所示:
src表示源MAC地址
dst表示目的MAC地址
#!/usr/bin/python3
#-*- coding: utf-8 -*-
import os
import re
import optparse
from scapy.all import *
#取IP地址和MAC地址获取函数
def HostAddress(iface):
#os.popen执行后返回执行结果
ipData = os.popen('ifconfig '+iface)
#对ipData进行类型转换,再用正则进行匹配
dataLine = ipData.readlines()
#re.search利用正则匹配返回第一个成功匹配的结果,存在结果则为true
#取MAC地址
global MAC
global IP
if re.search('\w\w:\w\w:\w\w:\w\w:\w\w:\w\w',str(dataLine)):
#取出匹配的结果
MAC = re.search('\w\w:\w\w:\w\w:\w\w:\w\w:\w\w',str(dataLine)).group(0)
#取IP地址
if re.search(r'((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)',str(dataLine)):
IP = re.search(r'((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)',str(dataLine)).group(0)
#将IP和MAC通过元组的形式返回
addressInfo = (IP,MAC)
return addressInfo
#ARP扫描函数
def ArpScan(iface='eth0'):
# 通过HostAddres返回的元组取出MAC地址
mac = HostAddress(iface)[1]
#取出本机IP地址
ip = HostAddress(iface)[0]
#对本机IP地址进行分割并作为依据元素,用于生成需要扫描的IP地址
ipSplit = ip.split('.')
#需要扫描的IP地址列表
ipList = []
for i in range(1,255):
ipItem = ipSplit[0] + '.' + ipSplit[1] + '.' + ipSplit[2] + '.' + str(i)
ipList.append(ipItem)
'''
发送ARP包
因为要用到OSI的二层和三层,所以要写成Ether/ARP。
因为最底层用到了二层,所以要用srp()发包
'''
result=srp(Ether(src=mac,dst='FF:FF:FF:FF:FF:FF')/ARP(op=1,hwsrc=mac,hwdst='00:00:00:00:00:00',pdst=ipList),iface=iface,timeout=2,verbose=False)
#读取result中的应答包和应答包内容
resultAns = result[0].res
#存活主机列表
liveHost = []
#number为接收到应答包的总数
number = len(resultAns)
print("=========================")
print("ARP 探测结果")
print("本机IP地址:" + ip)
print("本机MAC地址:" + mac)
print("=========================")
for x in range(number):
IP = resultAns[x][1][1].fields['psrc']
MAC = resultAns[x][1][1].fields['hwsrc']
liveHost.append([IP,MAC])
print("IP:" + IP + "\n\n" + "MAC:" + MAC )
print("============================")
# 把存活主机IP写入文件
resultFile = open("result","w")
for i in range(len(liveHost)):
resultFile.write(liveHost[i][0] + "\n")
resultFile.close()
if __name__ == '__main__':
parser = optparse.OptionParser('usage: python %prog -i interfaces \n\n' 'Example: python %prog -i eth0\n')
#添加网卡参数 -i
parser.add_option('-i','--iface',dest='iface',default='eth0',type='string', help='interfaces name')
(options,args) = parser.parse_args()
ArpScan(options.iface)
脚本测试结果如下:
查看结果文件如下所示: