import asyncio import socket import ipaddress import platform from tqdm import tqdm def get_local_ip(): s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) try: s.connect(('8.8.8.8', 80)) ip = s.getsockname()[0] except Exception: ip = '127.0.0.1' finally: s.close() return ip async def ping(ip): ping_cmd = f"ping -n 1 -w 1000 {ip}" if platform.system() == 'Windows' else f"ping -c 1 -W 1 {ip}" try: proc = await asyncio.create_subprocess_shell( ping_cmd, stdout=asyncio.subprocess.DEVNULL, stderr=asyncio.subprocess.DEVNULL ) returncode = await proc.wait() return returncode == 0 except Exception: return False async def check_port(ip, port, timeout=1): try: reader, writer = await asyncio.wait_for(asyncio.open_connection(ip, port), timeout) try: banner = await asyncio.wait_for(reader.read(1024), 1.0) banner = banner.decode('utf-8', errors='ignore').strip() except: banner = '' writer.close() await writer.wait_closed() return True, banner except: return False, '' async def scan_ip(ip, ports, ports_services): ip_str = str(ip) if not await ping(ip_str): return ip_str, False, [] tasks = [check_port(ip_str, port) for port in ports] results = await asyncio.gather(*tasks) open_ports = [(port, ports_services.get(port, 'Unknown'), banner) for port, (is_open, banner) in zip(ports, results) if is_open] return ip_str, True, open_ports async def full_scan(ip, ports_services): all_ports = range(1, 65536) sem = asyncio.Semaphore(200) with tqdm(total=len(all_ports), desc=f"Full scan {ip}") as pbar: async def check(port): async with sem: is_open, banner = await check_port(ip, port, timeout=0.5) if is_open: service = ports_services.get(port, 'Unknown') pbar.update(1) return (port, service, banner) else: pbar.update(1) return None tasks = [check(port) for port in all_ports] results = await asyncio.gather(*tasks) open_ports = sorted([p for p in results if p is not None]) return ip, open_ports async def get_dns_info(ip_str): loop = asyncio.get_event_loop() for attempt in range(3): try: hostname = (await loop.run_in_executor(None, socket.gethostbyaddr, ip_str))[0] a_record = await loop.run_in_executor(None, socket.gethostbyname, hostname) return hostname, a_record except Exception as e: print(f"Attempt {attempt+1} failed for {ip_str}: {e}") await asyncio.sleep(2) return "Unknown", "Unknown" async def main(): local_ip = get_local_ip() network = ipaddress.IPv4Network(f"{local_ip}/24", strict=False) ports_services = { 1: 'TCPMUX', 7: 'Echo', 9: 'Discard', 13: 'Daytime', 17: 'QOTD', 19: 'Chargen', 20: 'FTP Data', 21: 'FTP Control', 22: 'SSH', 23: 'Telnet', 25: 'SMTP', 37: 'Time', 39: 'RLP', 42: 'Nameserver', 43: 'WHOIS', 49: 'TACACS', 53: 'DNS', 67: 'BOOTPS', 68: 'BOOTPC', 69: 'TFTP', 70: 'Gopher', 79: 'Finger', 80: 'HTTP', 81: 'Hosts2-NS', 88: 'Kerberos', 102: 'ISO-TSAP', 107: 'RTelnet', 109: 'POP2', 110: 'POP3', 111: 'SunRPC', 113: 'Ident', 115: 'SFTP', 119: 'NNTP', 123: 'NTP', 135: 'MS RPC', 137: 'NetBIOS Name', 138: 'NetBIOS Datagram', 139: 'NetBIOS Session', 143: 'IMAP', 161: 'SNMP', 162: 'SNMP Trap', 179: 'BGP', 194: 'IRC', 201: 'AppleTalk Routing', 209: 'QMTP', 213: 'IPX', 220: 'IMAPv3', 389: 'LDAP', 401: 'UPS', 427: 'SLP', 443: 'HTTPS', 445: 'Microsoft DS', 464: 'Kerberos Change', 465: 'SMTPS', 497: 'Dantz Retrospect', 500: 'ISAKMP', 512: 'Exec', 513: 'Login', 514: 'Syslog', 515: 'LPD', 520: 'RIP', 543: 'Klogin', 544: 'Kshell', 546: 'DHCPv6 Client', 547: 'DHCPv6 Server', 554: 'RTSP', 563: 'NNTPS', 587: 'SMTP Submission', 591: 'FileMaker', 593: 'HTTP RPC', 631: 'IPP', 636: 'LDAPS', 639: 'MSDP', 646: 'LDP', 691: 'MS Exchange', 749: 'Kerberos Admin', 873: 'rsync', 990: 'FTPS', 993: 'IMAPS', 994: 'IRCS', 995: 'POP3S', 1080: 'SOCKS', 1194: 'OpenVPN', 1433: 'MSSQL', 1434: 'MSSQL Monitor', 1521: 'Oracle', 1720: 'H.323', 1723: 'PPTP', 1741: 'CiscoWorks', 1812: 'RADIUS', 1813: 'RADIUS Acct', 1984: 'Big Brother Monitor', 1985: 'HSRP', 2000: 'Cisco SCCP', 2049: 'NFS', 2082: 'cPanel', 2083: 'cPanel SSL', 2086: 'WHM', 2087: 'WHM SSL', 2095: 'cPanel Webmail', 2096: 'cPanel Webmail SSL', 2100: 'Oracle XDB FTP', 2222: 'DirectAdmin', 2242: 'Folio Remote Server', 2248: 'User Management Service', 2280: 'LNVPOLLER', 2301: 'Compaq Insight', 2381: 'HP Insight', 2401: 'CVS', 2433: 'MS SQL Analysis', 2483: 'Oracle DB SSL', 2484: 'Oracle DB SSL', 2638: 'Sybase', 2710: 'XBT Tracker', 3000: 'Ruby on Rails', 3050: 'Interbase/Firebird', 3100: 'OpCon/xps', 3128: 'Squid', 3260: 'iSCSI', 3268: 'AD Global Catalog', 3269: 'AD Global Catalog SSL', 3306: 'MySQL', 3389: 'RDP', 3478: 'STUN', 3690: 'SVN', 3784: 'Ventrilo', 3785: 'Ventrilo', 3899: 'Remote Web Workplace', 4000: 'Diablo II', 4190: 'Sieve Mail Filter', 4321: 'BoBo', 4369: 'Erlang EPMD', 4431: 'adWISE Pipe', 4664: 'Google Desktop', 4899: 'Radmin', 4949: 'Munin', 5000: 'UPnP', 5001: 'Synology', 5009: 'Airport Admin', 5051: 'IDA Agent', 5060: 'SIP', 5190: 'AIM/ICQ', 5222: 'XMPP', 5269: 'XMPP SSL', 5432: 'PostgreSQL', 54744: 'Unknown', 5500: 'VNC Hotline', 5554: 'Sasser', 5555: 'ADB', 5631: 'pcAnywhere Data', 5632: 'pcAnywhere Master', 5800: 'VNC HTTP', 5900: 'VNC', 6000: 'X11', 6112: 'Battle.net', 6129: 'DameWare', 6346: 'Gnutella', 6347: 'Gnutella', 6379: 'Redis', 6665: 'IRC', 6666: 'IRC', 6667: 'IRC', 6668: 'IRC', 6669: 'IRC', 6697: 'IRC SSL', 6881: 'BitTorrent', 6969: 'BitTorrent', 7071: 'IWC Replica', 7212: 'GhostSite', 7777: 'Oracle Web', 8000: 'HTTP Alternate', 8001: 'VCOM Tunnel', 8006: 'Proxmox VE', 8008: 'HTTP Alternate', 8009: 'AJP', 8080: 'HTTP Alternate', 8081: 'HTTP Alternate', 8088: 'HTTP Alternate', 8089: 'Splunk', 8090: 'HTTP Alternate', 8118: 'Privoxy', 8200: 'MiniDLNA', 8424: 'Unknown', 8443: 'HTTPS Alternate', 8554: 'RTSP Alternate', 8762: 'Unknown', 8767: 'TeamSpeak', 8888: 'HTTP Alternate', 9000: 'SonarQube', 9001: 'Tor', 9002: 'Dynamix', 9003: 'Unknown', 9030: 'Tor', 9040: 'Tor', 9050: 'Tor', 9100: 'JetDirect', 9119: 'MXit', 9200: 'Elasticsearch', 9230: 'Unknown', 9418: 'Git', 9999: 'Abyss', 10000: 'Webmin', 11371: 'OpenPGP', 12345: 'NetBus', 13720: 'NetBackup', 13721: 'NetBackup', 13724: 'Veritas', 13782: 'Veritas', 13783: 'Veritas', 19226: 'Panda', 19638: 'Ensim', 20000: 'Usermin', 22222: 'EasyEngine', 24800: 'Synergy', 25999: 'Yahoo IM', 27015: 'Half-Life', 27017: 'MongoDB', 27374: 'Sub7', 28015: 'Rust', 31337: 'Back Orifice', 33434: 'Traceroute', 37777: 'Dahua DVR', 40193: 'Novell', 41523: 'MS SQL', 43594: 'Runescape', 43595: 'Runescape', 44818: 'EtherNet/IP', 47808: 'BACnet', 49152: 'Dynamic', 49153: 'Dynamic', 49154: 'Dynamic', 49155: 'Dynamic', 49156: 'Dynamic', 49157: 'Dynamic', 55555: 'FreeCiv', 60000: 'Deep Throat', 65000: 'Stacheldraht' } ports = list(ports_services.keys()) tasks = [scan_ip(ip, ports, ports_services) for ip in network.hosts()] results = await asyncio.gather(*tasks) active_devices = [] common_open_ports = {} for ip, active, open_ports in results: if active: active_devices.append(ip) if open_ports: common_open_ports[str(ip)] = open_ports dns_tasks = [get_dns_info(str(ip)) for ip in active_devices] dns_results = await asyncio.gather(*dns_tasks) dns_infos = {str(active_devices[i]): dns_results[i] for i in range(len(active_devices))} devices_need_full = [] for ip in active_devices: ip_str = str(ip) if common_open_ports.get(ip_str) or dns_infos[ip_str][0] != "Unknown": devices_need_full.append(ip_str) full_tasks = [full_scan(ip, ports_services) for ip in devices_need_full] full_results = await asyncio.gather(*full_tasks) devices_with_open_ports = {} for ip in active_devices: ip_str = str(ip) devices_with_open_ports[ip_str] = common_open_ports.get(ip_str, []) for full_ip, full_open in full_results: devices_with_open_ports[full_ip] = full_open print("Active devices:") for dev in active_devices: print(dev) print("\nDevices with open ports:") for ip, open_ports in devices_with_open_ports.items(): hostname, a_record = dns_infos[ip] print(f"{ip} (Hostname: {hostname}, A: {a_record}):") if hostname != "Unknown": print(f" DNS Records:") print(f" PTR: {hostname}") print(f" A: {a_record}") for port, service, banner in open_ports: print(f" - {port}: {service}" + (f" ({banner})" if banner else "")) asyncio.run(main())