--永恒的烦恼

Python探测局域网存活主机

脚本仅用于学习与测试使用,请勿用于非法用途

脚本说明

使用了多线程进行探测,速度非常快。脚本会创建一个txt文本文件,用于存放存活的主机,请注意该脚本协议是ICMP,同时每运行一次便会重置TXT文本文件,该脚本默认的ip地址范围是 192.168.0.1 – 192.168.19.255,由于计算子网比较繁琐直接改用两个遍历进行,如果你想增加范围,参考最下面的案例。

import socket
import struct
import time
import array
import random
import threading

class IcmpScan:

    def __init__(self, ip_list, timeout=3):
        self.ips = ip_list
        self.__data = struct.pack('d', time.time())  # 需要发送的数据
        self.__id = random.randint(1000, 65535)
        self.timeout = timeout
        self.socket = self.rawSocket
        self.finished = False

    @property
    def rawSocket(self):
        try:
            Sock = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.getprotobyname("icmp"))
            Sock.settimeout(self.timeout)
        except:
            Sock = self.rawSocket
        return Sock

    def inCksum(self, packet):
        if len(packet) & 1:
            packet = packet + '\0'
        words = array.array('h', packet)
        sum = 0
        for word in words:
            sum += (word & 0xffff)
        sum = (sum >> 16) + (sum & 0xffff)
        sum = sum + (sum >> 16)
        return (~sum) & 0xffff

    def create_packet(self):
        header = struct.pack('bbHHh', 8, 0, 0, self.__id, 0)
        packet = header + self.__data
        chkSum = self.inCksum(packet)
        header = struct.pack('bbHHh', 8, 0, chkSum, self.__id, 0)
        return header + self.__data

    def recv_packet(self):
        while 1:
            try:
                recv_packet, addr = self.socket.recvfrom(1024)
                type, code, checksum, packet_ID, sequence = struct.unpack("bbHHh", recv_packet[20:28])
                if packet_ID == self.__id:
                    ttl = struct.unpack("!BBHHHBBHII", recv_packet[:20])[5]
                    print(f"检测到存活设备: {addr[0]}  ttl: {ttl}")
                    with open('内网ip.txt', 'a', encoding='utf-8') as f:
                        f.write(f'{addr[0]}\n')  # 添加到列表里面
            except:
                if self.finished:
                    break

    def start(self):
        random.shuffle(self.ips)  # 乱序一下地址
        packet = self.create_packet()
        time_space = 1 / 1000
        t = threading.Thread(target=self.recv_packet,)
        t.start()
        for i, ip in enumerate(self.ips):
            try:
                self.socket.sendto(packet, (ip, 0))
                time.sleep(time_space)
            except socket.timeout:
                break
            except:
                pass
        self.finished = True
        time.sleep(self.timeout + 1)
        self.socket.close()
        t.join()

if __name__ == '__main__':
    ip_list = []
    with open('内网ip.txt', 'w', encoding='utf-8') as f:
        pass
    for ip1 in range(0, 20):
        for ip2 in range(1, 255):
            ip_list.append('192.168.{}.{}'.format(ip1, ip2, ))
    icmp_scan = IcmpScan(ip_list)
    icmp_scan.start()

以下案例是172.16.0.1 – 192.168.10.255全部的ip范围,请注意其中探测到的主机可能是公网的主机,该案例范围很大,这里仅提供参考思路,您应该根据自己的情况去调整使用。

for ip1 in range(172, 193):
        for ip2 in range(16, 255):
            for ip3 in range(0, 255):
                for ip4 in range(0, 255):
                    ip_list.append('{}.{}.{}.{}'.format(ip1, ip2,ip3, ip4 ))

赞(2) 打赏
转载请带上源站链接:玖伴一鹏 » Python探测局域网存活主机

觉得文章有用就打赏一下文章作者

非常感谢你的打赏,我们将继续给力更多优质内容,让我们一起创建更加美好的网络世界!

支付宝扫一扫打赏

微信扫一扫打赏