手把手教你写一个图形化的端口扫描工具

前言

关于学习群,有想要交流学习的朋友们可以在后台菜单栏加群奥~

由于我使用masscan进行纯端口扫描的时候,遇到扫描不出结果的情况,我就考虑了自己写一个端口扫描脚本,还挺好用。

image-20240805144645079

库介绍

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))

执行结果

image-20240805150702536

那么添加一个ui界面呢

image-20240805154953735

多个ip扫描

image-20240805155216447

代码如下:

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

开始扫描

image-20240805160052094

当然使用nmap的-sS参数syn扫描,速度也比较快,但是也得指定端口,不指定端口的话呢就像这样,使用默认的1-10000范围内的端口号(大致范围)

image-20240805145421710

指定范围就可以使用了

image-20240805145530386

后期我会把他写成一个多功能的工具,大家敬请期待

posted @   白小雨  阅读(60)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具

阅读目录(Content)

此页目录为空

点击右上角即可分享
微信分享提示