前言
关于学习群
由于我使用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范围内的端口号(大致范围)
指定范围就可以使用了
后期我会把他写成一个多功能的工具,大家敬请期待