脚本仅用于学习与测试使用,请勿用于非法用途
脚本说明
使用了多线程进行探测,速度非常快。脚本会创建一个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 ))