python_scapy实现ARP扫描

1,在直连的设备上进行ARP扫描,可以准确的判断出主机的状态,比PING扫描来的更块更准确,

      因为现在大多数的设备都已经禁止PING技术了。


2,ARP数据包分析

      ARP_Request包:

python_scapy实现ARP扫描_第1张图片

    因为是个ARP包,所以以太二层的dst是广播(FF:FF:FF:FF:FF:FF),源地址是出接口的mac地址。

    arp_request的操作码是1,arp_reply的操作码是2

    arp协议的源mac和ip是出接口的mac和ip,目的mac是00:00:00:00:00:00(这就是问题),目的ip就

    是要查询的ip,如果找到,则在回复包中就会作为源mac地址发送回来。

  

     ARP_Reply包:

python_scapy实现ARP扫描_第2张图片

    arp_reply包就回答了arp_request包的问题,所以以太二层的源mac就成功回复方的mac地址,目标mac

    就是给谁回的mac地址,arp协议中操作码为2,代表arp_reply,以及发送方的mac和ip,目的地址的mac

    和IP。


3,使用scapy铸造ARP数据包

    arp_request=Ether(dst='FF:FF:FF:FF:FF:FF')/ARP(op=1,hwdst='00:00:00:00:00:00',pdst='192.168.219.180')

    arp_request.show()可以查看铸造的包的信息。

    python_scapy实现ARP扫描_第3张图片

    根据实际情况对包的数据进行填写,已达到所需要的要求。

4,发送3铸造的数据包

    应为这里铸造的包是一个以太二层的数据包,所以在发送该数据包的时候,应该使用srp()函数,

    srp()可以发送一个以太二层的数据包并等待回复,这里的回复是一个复杂的数据结构,这里对

    这个回复做简单的解释。

   python_scapy实现ARP扫描_第4张图片

    这里srp函数的返回值是一个特殊的类,分为收到结果的包,和未收到结果的包。这里可以看到,

    srp将返回值做成了一个元组。arp[0]就是收到的数据包,在收到的数据包中,又是列表,列表

    中的每一元素都是有发送的数据包和接收到的数据包组成,arp[0].res可以产生这个列表作为一

    个清单。清单的第一个元素(就是第一个响应的数据包)的第二个位置就是保存的接收到的数据包。

    在此位置查看此包的hwsrc字段,就是问题的答案,就是目标的mac地址。


5,实现arp数据包铸造和发送的程序代码

#--------------------------------------------------------------------------------------------------------------------------------

#!/usr/bin/python3.4

# _*_ coding=utf-8 _*_


#   清除报错

import logging

logging.getLogger("scapy.runtime").setLevel(logging.ERROR)

from scapy.all import *


#构造发送数据包并接受响应函数,两个参数,一个IP地址,一个队列,默认为None

def arp_request(ip_address,queue=None):

    #发送二层数据帧

    result_raw=srp(Ether(dst='FF:FF:FF:FF:FF:FF')/ARP(op=1,hwdst='00:00:00:00:00:00'

                             ,pdst=ipaddress,timeout=1,verbose=False)

    try:

        #把响应的数据包对,产生清单

        result_list=result_raw[0].res

        #[0]第一组响应数据包

        #[1]接收到的包,[0]为发送的数据包

        #[1]ARP头部字段中的['hwsrc']字段,作为返回值返回

        if queue==None:

            return result_list[0][1].getlayer(ARP).fields['hwsrc']

        else:

            queue.put((ip_address,result_list[0][1].getlayer(ARP).fields['hwsrc']))

    except:

        return


if __name_=='__main__':

    import sys

    print(arp_request(sys.argv[1]))

#--------------------------------------------------------------------------------------------------------------------------------

这里使用队列是为了进程间的通信,在这个进程中将所有响应的ip地址和mac放入队列中

,然后再另外一个进程将其都出来,以此实现进程间的通信。



6,实现arp扫描


#!/usr/bin/python3.4

# _*_ coding=utf-8 _*_

import logging

logging.getLogger(''scapy.runtime'').setLevel(logging.ERROR)

import ipaddress

import time

from arp_request import arp_request

from multiprocessing import Process,Queue

def arp_scan(network):

    queue=Queue()

    net=ipaddress.ip_network(network)

    for ip in net:

        ip_addr=str(ip)

        arp_one=Process(target=arp_request,args=(ip_addr,queue))

        arp_one.start()

    time.sleep(2)

    ip_mac_list=[]

    while True:

        if queue.empty():

            break;

        else:

            ip,mac=queue.get()

            ip_mac_list.append((ip,mac))

    return ip_mac_list

if  __name__=='__main__':

    import sys

    active_ip_mac=arp_scan(sys.argv[1])

    print('活动IP与MAC地址如下:')

    for ip,mac in active_ip_mac:

        print(ip,mac)

    print('总个数为:'+str(len(active_ip_mac))





   


你可能感兴趣的:(python)