python内网主机存活探测

python内网主机存活探测

实验环境

1.在Ubuntu系统下进行发包
2.使用python中的scapy模块

ARP知识

​ ARP协议是“Address Resolution Protocol”(地址解析协议)的缩写。其作用是在以太网环境中,数据的传输所依懒的是MAC地址而非IP地址,而将已知IP地址转换为MAC地址的工作是由ARP协议来完成的。

在局域网中,网络中实际传输的是“帧”,帧里面是有目标主机的MAC地址的。在以太网中,一个主机和另一个主机进行直接通信,必须要知道目标主机的MAC地址。但这个目标MAC地址是如何获得的呢?它就是通过地址解析协议获得的。所谓“地址解析”就是主机在发送帧前将目标IP地址转换成目标MAC地址的过程。ARP协议的基本功能就是通过目标设备的IP地址,查询目标设备的MAC地址,以保证通信的顺利进行。

ARP请求

任何时候,当主机需要找出这个网络中的另一个主机的物理地址时,它就可以发送一个ARP请求报文,这个报文包好了发送方的MAC地址和IP地址以及接收方的IP地址。因为发送方不知道接收方的物理地址,所以这个查询分组会在网络层中进行广播。

ARP响应

局域网中的每一台主机都会接受并处理这个ARP请求报文,然后进行验证,查看接收方的IP地址是不是自己的地址,只有验证成功的主机才会返回一个ARP响应报文,这个响应报文包含接收方的IP地址和物理地址。这个报文利用收到的ARP请求报文中的请求方物理地址以单播的方式直接发送给ARP请求报文的请求方。

所以在局域网内进行主机存活探测时我们可以使用广播ARP报文的形式,看看是否收到了ARP报文来判断此主机是否存活。

操作

​ 下面我们创建了一个多线程的子类

使用threading模块

创建多线程子类的模板如下,重写了run方法,在我们启动线程时run()方法就是线程的开始

class MyThread(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
   
    def run(self):
        

我们的子类写得比较简单

class IPscan(threading.Thread):
    def __init__(self, qu,li):#将有保存有IP地址的队列qu传入类中
        threading.Thread.__init__(self)
        self.Qu = qu
        self.li = li
        
    def CreatARP(self, ip):#构造ARP报文
        page = Ether()/ARP(pdst = ip)
        result = srp1(page, timeout = 0.5)#使用srp1第二层发包及按照我们Ether()报头里的格式发
        if result:#因为没有收到响应的响应时,会返回None
            self.li.append(f'the {ip} is host'+'\t' 'the mac:'+ result[ARP].hwsrc)
				#将响应的IP以及物理地址保存
    def run(self):#线程的入口
        while not self.Qu.empty():
            self.CreatICMP(self.Qu.get())

几个发包方式可见scapy几种发送
上面就是我们的多线程子类

接下来我们还的编写一个main()函数

​ 首先对传进去的参数判断是否是一个网段还是单个IP(虽然可以直接ARP(pdst=‘192.168.0.1/24’)便可以直接扫描整个网段,但是为了练习一下正则表达式以及多线程还是一个的发)使用正则表达式进行判断。

thread_list = []
        list_host = []
        threadnumber = 1
        Qu = queue.Queue()
        flag = False
if re.match(r'^\d{0,3}.\d{0,3}.\d{0,3}.\d{0,3}$',ip) !=None:
           Qu.put(ip)#判断是否为单个IP,将得到的IP压入栈中
elif  re.match(r'^\d{0,3}.\d{0,3}.\d{0,3}.\d{0,3}/\d{0,3}$', ip) != None:
            #判断是否为一个网段,然后将所有IP压入栈中
            ip_str = re.match(r'^\d{0,3}.\d{0,3}.\d{0,3}.', ip).group()
            for x in range(0, 256):
                Qu.put(ip_str + str(x))
 else:
            flag = True

​ 如果是单个IP我们就使用一个线程如果是个网段就使用多线程

if flag:
            threadnumber = 10
        for x in range(threadnumber):
            thread_list.append(IPscan(Qu, li=list_host ))#创建一个个的多线程子类对象,将IP队列传入,将list_host传入用来保存存活的IP以及他们的物理地址
        
        for x in thread_list:#启动线程
            x.start()
        for x in thread_list:#在进程中阻塞线程,等待所以线程执行完毕
            x.join()

接下来输出存活的IP

for x in list_host:
            print(x)

完整的代码()

from scapy.all import *
from scapy.layers.l2 import ARP, Ether
import threading
import queue
import re

class IPscan(threading.Thread):
    def __init__(self, qu, li):
        threading.Thread.__init__(self)
        self.Qu = qu
        self.li
        
    def CreatICMP(self, ip):
        page = Ether()/ARP(pdst = ip)
        page.show()
        result = srp1(page, timeout = 0.5)
        print(result)
        if result:
            self.li.append(f'the {ip} is host'+'\t' 'the mac:'+ result[ARP].hwsrc)

    def run(self):
        while not self.Qu.empty():
            self.CreatICMP(self.Qu.get())


def main( ip):#
        thread_list = []
        list_host = []
        threadnumber = 1
        Qu = queue.Queue()
        flag = False
        if re.match(r'^\d{0,3}.\d{0,3}.\d{0,3}.\d{0,3}$',ip) !=None:
           Qu.put(ip)
        elif  re.match(r'^\d{0,3}.\d{0,3}.\d{0,3}.\d{0,3}/\d{0,3}$', ip) != None:
            ip_str = re.match(r'^\d{0,3}.\d{0,3}.\d{0,3}.', ip).group()
            for x in range(0, 256):
                Qu.put(ip_str + str(x))
        else:
            flag = True
        if flag:
            threadnumber = 10
        for x in range(threadnumber):

            thread_list.append(IPscan(Qu, li=list_host ))

        for x in thread_list:
            x.start()
        for x in thread_list:
            x.join()
        for x in list_host:
            print(x)



if __name__ =='__main__':

    main('192.168.0.0/24')

还有这种属于敏感操作得以root权限启动pycharm,我们在编写过程中才更好调试

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值