手把手教你写一个图形化的端口扫描工具
前言
关于学习群,有想要交流学习的朋友们可以在后台菜单栏加群奥~
由于我使用masscan进行纯端口扫描的时候,遇到扫描不出结果的情况,我就考虑了自己写一个端口扫描脚本,还挺好用。
库介绍
1、asyncio
asyncio
是 Python 的一个库,用于编写单线程并发代码。使用 asyncio
,你可以使用异步函数 (async def
) 来编写协程。协程可以被调度执行,执行过程中可以等待其他协程完成,而不必阻塞整个程序的运行。
2、ipaddress
ipaddress
是 Python 的一个标准库模块,主要用于检查和操作 IP 地址。该模块提供了创建、操作和表示 IPv4 和 IPv6 地址及网络的功能。
3、tkinter
Tkinter
是Python标准库中的一个模块,专门用于创建图形用户界面(GUI)应用程序。
可以使用nmap扫描,也可以使用该脚本定制自己的图形界面,和其他功能,比如网站目录扫描,本代码仅供参考
import asyncio import ipaddress # 异步扫描指定IP和端口的函数 async def scan_port(ip, port, semaphore): async with semaphore: # 使用信号量限制并发数量 try: # 尝试连接到指定的IP和端口,设置超时为3秒 reader, writer = await asyncio.wait_for(asyncio.open_connection(ip, port), timeout=3) print(f"端口 {port} 在 {ip} 开启") # 如果连接成功,打印端口开启的信息 writer.close() # 关闭连接 except (ConnectionRefusedError, OSError): # 如果连接被拒绝或发生其他OS错误,则不执行任何操作 pass except asyncio.TimeoutError: # 如果连接超时,则不执行任何操作 pass # 解析IP范围的函数 def parse_ip_range(ip_range): if '/' in ip_range: # 如果IP范围使用CIDR表示法 return [str(ip) for ip in ipaddress.ip_network(ip_range).hosts()] # 返回CIDR范围内的所有IP地址 elif '-' in ip_range: # 如果IP范围使用起始-结束表示法 start_ip, end_ip = ip_range.split('-') # 分割起始和结束IP start_int = int(ipaddress.IPv4Address(start_ip)) # 将起始IP转换为整数 end_int = int(ipaddress.IPv4Address(end_ip)) # 将结束IP转换为整数 return [str(ipaddress.IPv4Address(i)) for i in range(start_int, end_int + 1)] # 返回范围内的所有IP地址 else: # 如果使用单个IP表示法 return [ip_range] # 返回单个IP地址的列表 # 主函数,用于执行端口扫描 async def main(ip_range, ports): ips = parse_ip_range(ip_range) # 解析IP范围 semaphore = asyncio.Semaphore(500) # 创建一个信号量,限制并发连接的数量 tasks = [] # 创建一个任务列表 # 遍历IP范围和端口范围,为每个IP和端口创建一个扫描任务 for ip in ips: for port in ports: task = asyncio.create_task(scan_port(ip, port, semaphore)) # 创建扫描任务 tasks.append(task) # 将任务添加到任务列表中 # 等待所有任务完成,并捕获可能的异常 try: await asyncio.wait(tasks) # 等待所有任务完成 except Exception as e: print(f"An error occurred: {e}") # 如果发生错误,打印错误信息 # 程序入口点 if __name__ == "__main__": # 设置IP范围和要扫描的端口范围 ip_range = "192.168.3.155" # 指定单个IP或IP范围 target_ports = range(80, 60000) # 指定要扫描的端口范围 # 运行主函数,开始端口扫描 asyncio.run(main(ip_range, target_ports))
执行结果
那么添加一个ui界面呢
多个ip扫描
代码如下:
import asyncio import ipaddress import tkinter as tk from tkinter import scrolledtext # 异步扫描指定IP和端口的函数 async def scan_port(ip, port, semaphore, result_queue): async with semaphore: try: reader, writer = await asyncio.wait_for(asyncio.open_connection(ip, port), timeout=3) await result_queue.put(f"端口 {port} 在 {ip} 开启") writer.close() except (ConnectionRefusedError, OSError, asyncio.TimeoutError): pass def parse_ip_range(ip_range): if '/' in ip_range: return [str(ip) for ip in ipaddress.ip_network(ip_range).hosts()] elif '-' in ip_range: start_ip, end_ip = ip_range.split('-') start_int = int(ipaddress.IPv4Address(start_ip)) end_int = int(ipaddress.IPv4Address(end_ip)) return [str(ipaddress.IPv4Address(i)) for i in range(start_int, end_int + 1)] else: return [ip_range] async def main(ip_range, ports, result_queue): ips = parse_ip_range(ip_range) semaphore = asyncio.Semaphore(500) tasks = [] for ip in ips: for port in ports: task = asyncio.create_task(scan_port(ip, port, semaphore, result_queue)) tasks.append(task) await asyncio.wait(tasks) class PortScannerApp: def __init__(self, root): self.root = root self.root.title("端口扫描器") self.ip_label = tk.Label(root, text="IP范围:") self.ip_label.grid(row=0, column=0) self.ip_entry = tk.Entry(root) self.ip_entry.grid(row=0, column=1) self.port_label = tk.Label(root, text="端口范围:") self.port_label.grid(row=1, column=0) self.port_entry = tk.Entry(root) self.port_entry.grid(row=1, column=1) self.start_button = tk.Button(root, text="开始扫描", command=self.start_scan) self.start_button.grid(row=2, column=0, columnspan=2) self.result_text = scrolledtext.ScrolledText(root, wrap=tk.WORD, width=40, height=10) self.result_text.grid(row=3, column=0, columnspan=2) self.result_queue = asyncio.Queue() def start_scan(self): ip_range = self.ip_entry.get() port_range = self.port_entry.get() if '-' in port_range: start_port, end_port = map(int, port_range.split('-')) ports = range(start_port, end_port + 1) else: ports = [int(port_range)] asyncio.run(main(ip_range, ports, self.result_queue)) self.process_results() def process_results(self): while not self.result_queue.empty(): result = self.result_queue.get_nowait() self.result_text.insert(tk.END, result + "\n") self.result_text.yview(tk.END) if __name__ == "__main__": root = tk.Tk() app = PortScannerApp(root) root.mainloop()
开始打包
pip install pyinstaller pyinstaller your_script.py
开始扫描
当然使用nmap的-sS参数syn扫描,速度也比较快,但是也得指定端口,不指定端口的话呢就像这样,使用默认的1-10000范围内的端口号(大致范围)
指定范围就可以使用了
后期我会把他写成一个多功能的工具,大家敬请期待
分类:
网络安全