端口扫描工具开发

admin 2025年6月6日23:26:10评论7 views字数 9159阅读30分31秒阅读模式
总感觉自己是脚本小子,还得要学习代码。
代码能力很差,大佬勿喷

利用socket端口扫描

socket原理

Python的socket库是操作系统底层Socket API的封装,直接使用传输层协议(TCP/UDP)。当您调用s.connect()时,实际发生了以下TCP协议交互:1.发送SYN包到目标端口2.若收到SYN+ACK → 端口开放 → 完成握手(发送ACK)3.若超时无响应 → 端口被过滤。

所以这是标准的TCP全连接扫描(非半开扫描),完全依赖操作系统的TCP协议栈实现。

线程教学视频

https://www.bilibili.com/video/BV1wb4y1S7d6/?spm_id_from=333.1007.top_right_bar_window_history.content.click&vd_source=35e4182ce0db72b58a7c3806ee59a0d5

代码

import socket#端口扫描def socket_port(ip):    for port in range(78,100):        try:            s=socket.socket()            s.connect((ip,port))            print(f"端口:{port}可用")            s.close()        except:            print(f"这个端口{port}不可用")if __name__ == '__main__':    socket_port('10.105.66.16')

优化

import socketimport concurrent.futures# 检查单个端口是否开放def check_port(ip, port, timeout=0.5):    try:        s = socket.socket()        s.settimeout(timeout)        s.connect((ip, port))  # 尝试连接        s.close()        return True  # 连接成功    except:        return False  # 连接失败def socket_port(ip, start=78, end=100):    # 创建线程池(最多同时扫描10个端口)    with concurrent.futures.ThreadPoolExecutor(max_workers=50as executor:        # 准备存储任务和端口号的列表        task_list = []        port_list = []        # 为每个端口创建扫描任务        for port in range(start, end + 1):            # 提交扫描任务到线程池            task = executor.submit(check_port, ip, port)   #执行这个函数给到线程池中            # 保存任务对象和对应的端口号            task_list.append(task)  #task_list.append(task) 则是把这些 task 对象收集起来,方便后续统一处理结果            port_list.append(port)        # 处理完成的任务        for i in range(len(task_list)):            # 等待任务完成(按提交顺序)            task = task_list[i]            port = port_list[i]            # 获取扫描结果            is_open = task.result()   #这个返回就是heck_port的函数分return结果            # 打印结果            if is_open:                print(f"端口 {port} ✅ 开放")            # else:            #     print(f"端口 {port} ❌ 关闭或过滤")if __name__ == '__main__':    socket_port('10.105.66.16', start=1, end=65536# 只扫描3个端口作为示例    print("扫描结束")
再优化
import socketimport concurrent.futuresdef check_port(ip, port, timeout=0.5):    try:        with socket.socket() as s:            s.settimeout(timeout)            s.connect((ip, port))        return port, True    except:        return port, Falsedef socket_port(ip, start=78, end=100, max_workers=50):    with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor:        futures = {executor.submit(check_port, ip, port): port for port in range(start, end+1)}  # 这里用字典推导式,将executor.submit返回的对象于port绑定在一起组成一个futures字典        for future in concurrent.futures.as_completed(futures):  # 要求他们不用按照顺序执行,谁先执行谁就来这里循环            port, status = future.result()            if status:                print(f"端口 {port}")if __name__ == '__main__':    socket_port('10.105.66.16', start=1, end=65536)
端口扫描工具开发

借助天欣大佬的视频

【快速入门python安全开发】 https://www.bilibili.com/video/BV1jBD9Y5Euv/?p=6&share_source=copy_web&vd_source=7ff27bdc142f051d6aec8c3424b47cb8

前提条件

1.安装nmap库

pip install python3-nmap
端口扫描工具开发

2.nmap 环境变量

端口扫描工具开发
端口扫描工具开发

原理学习

有时候防火墙会限制某种协议的扫描,要想解决这种问题,就需要换不同的协议去测试

扫描类型/参数

命令

原理与特性

示例

使用场景与注意事项

TCP SYN扫描

nmap -sS <目标>

半开放扫描

:发送SYN包,若收到SYN/ACK则端口开放(立即发送RST终止连接)。隐蔽性强,不触发完整连接日志。需Root权限。

nmap -sS 192.168.1.1

快速探测开放端口,绕过基础日志记录。适用于Linux/Unix系统(需管理员权限)。

TCP Connect扫描

nmap -sT <目标>

全连接扫描

:完成三次握手后断开。依赖系统

connect()

函数,无权限要求,但易被日志记录。

nmap -sT 10.0.0.5 -p 80,443

无Root权限时使用,兼容性好。速度较慢且不够隐蔽,可能触发安全警报。

TCP ACK扫描

nmap -sA <目标>

防火墙探测

:发送ACK包,若收到RST说明端口未被过滤;无响应可能被防火墙拦截。不检测端口状态。

nmap -sA 203.0.113.0 -p 22

探测防火墙规则,识别过滤端口。需结合其他扫描确定实际开放状态。

TCP FIN扫描

nmap -sF <目标>

隐蔽扫描

:发送FIN包,关闭的端口返回RST,开放的端口无响应(违反RFC 793)。绕过无状态防火墙/IDS。

nmap -sF 192.168.1.100 -T2

隐蔽探测Linux/Unix系统端口。对Windows无效(默认不遵循RFC响应)。

TCP Xmas扫描

nmap -sX <目标>

畸形包扫描

:发送FIN+PSH+URG标志位的包(类似圣诞灯饰)。响应逻辑同FIN扫描。

nmap -sX 10.0.0.10 --top-ports 50

绕过简单防火墙,测试系统协议栈兼容性。对Windows通常无效。

TCP NULL扫描

nmap -sN <目标>

空标志位扫描

:发送无任何标志位的包,依赖目标系统RFC合规性。开放的端口无响应,关闭的端口返回RST。

nmap -sN 192.168.1.200

隐蔽性高,适用于Linux/Unix环境。需多次验证结果准确性。

UDP扫描

nmap -sU <目标>

无连接探测

:发送UDP包,若收到ICMP不可达则端口关闭;无响应可能开放(需二次验证)。速度极慢。

nmap -sU -p 53,123,161 192.168.1.1

检测DNS、NTP、SNMP等UDP服务。建议限定端口范围,结合

--max-retries 1

加速。

服务版本探测

nmap -sV <目标>

协议指纹匹配

:向开放端口发送探针,匹配响应特征与

nmap-service-probes

数据库,识别服务名称及版本。

nmap -sV 192.168.1.1 -p 80,443

漏洞利用前的情报收集。可与

-A

组合使用,获取详细服务信息。

操作系统检测

nmap -O <目标>

协议栈指纹分析

:通过TTL、窗口大小、序列号生成模式等特征,匹配已知操作系统指纹库。

nmap -O --osscan-limit 192.168.1.1

识别目标操作系统类型。需至少一个开放和一个关闭的端口提高准确性。

综合扫描

nmap -A <目标>

全面探测

:启用OS检测(-O)、版本探测(-sV)、脚本扫描(-sC)及Traceroute。

nmap -A -T4 scanme.nmap.org

渗透测试初期信息收集,获取目标完整画像。资源消耗较高,可能触发安全机制。

跳过主机发现

nmap -Pn <目标>

强制扫描

:跳过Ping检测(主机发现),假设所有目标在线,直接进行端口扫描。

nmap -Pn 192.168.1.1

目标屏蔽ICMP请求时使用(如防火墙过滤Ping),避免Nmap误判主机离线。扫描时间可能增加。

空闲扫描

nmap -sI <僵尸机> <目标>

隐蔽源扫描

:利用第三方“僵尸主机”反射流量,隐藏扫描者真实IP。需僵尸机满足空闲且IPID递增条件。

nmap -sI 192.168.1.50 10.0.0.0/24

高度隐蔽的扫描,绕过IP追踪。需提前验证僵尸机可用性。

窗口扫描

nmap -sW <目标>

TCP窗口扫描

:分析返回的RST包中TCP窗口大小,某些系统开放端口与关闭端口的窗口值不同。

nmap -sW 192.168.1.1 -p 1-1000

替代SYN扫描,绕过某些IDS检测。准确度依赖目标系统实现,适用范围有限。

脚本流程图

端口扫描工具开发

脚本代码-初代

import nmap3  #引入 nmap3 的库from openpyxl import Workbook import jsonimport timedef scan(ip,default,args):  #对一个IP进行端口扫描    scaner = nmap3.Nmap()  #对应的类    port_data=scaner.scan_top_ports(ip,default,args)  #输入参数 进行扫描 args 可以传别的参数    return ip,port_data  #这里返回的值如果用 ,分开 返回的结果是元组def write_to_excel_sheet(ip,data,ws):#对上面函数输出的结果,进行数据处理,导入到xlsx文件中    try:        # 探测的ip        scaned_ip=ip        # print(ip,data)        ip_datas=data[ip].get('ports',"")   # 获取返回结果的 字典中 key为IP,vlau值所有列表ports          if ip_datas:            for ip_data in ip_datas:                # 端口协议                port_col=ip_data.get('protocol','')  #获取 上面列表 ports里面的 protocol对应的值 端口协议                # 端口号                port_id=ip_data.get('portid','')     #同上                # 端口服务                port_service=ip_data.get('service','').get('name',''#同上                ws.append([scaned_ip,port_id,port_col,port_service])  #写入到 xlsx文件中    except PermissionError:        print("文件可能处于打开状态,请关闭文件"#报错处理def read_from_txt(filename):   #读取txt文件的内容,将文件IP内容返回成列表    try:        with open(filename,'r'as f:            return [i.strip() for i in f.readlines() if i.strip()] #这个就是去除文件中多以空行和空格,并将txt文件的内容返回成 一个列表    except FileNotFoundError:        print("文件不存在,请检查文件名")if __name__ == '__main__':    start=time.time()    ips = read_from_txt('ips.txt')#利用上面的函数将 txt文件的IP地址提取出来成一个列表     wb = Workbook()    ws = wb.active    ws.append(["IP""开放端口""端口协议""端口服务"])#先输入 数据处理的文件头信息    for ip in ips: #利用for循环,将ips的列表的信息一个一个给到ip        data=scan(ip,100,args=''# 利用上面给到的ip 进行基本的端口扫描工作         write_to_excel_sheet(data[0],data[1],ws)''' #"scan(ip,100,args='')"这个返回的是元组,所以采用“data[0],data[1]”这种方式传参,“write_to_excel_sheet”这个函数就是进行数据处理的'''    wb.save(f'端口扫描脚本初步.xlsx')#保存    print("保存成功")    end=time.time()    cost=end-start    print(f"扫描完成,耗时{cost:.2f}秒")
优化
import jsonimport timefrom openpyxl import Workbookimport nmap3def scan_task(taskIP,top=100,args=''):    nmap = nmap3.Nmap()    results = nmap.scan_top_ports(taskIP, default=top, args=args)    # print(json.dumps(results, indent=2))    return resultsdef get_sheet_wb(detail):#判断是否是详细扫描还是简单扫描    workbook = Workbook()    sheet= workbook.active    sheet.title="端口扫描结果"# 这个的话 其实后期可以添加别的工具自动扫描    if detail: #不为空 就说明是详细,xlsx就是下面的几个数据表头        sheet.append(["目标IP""开放端口""端口服务""端口协议""详细信息""服务版本""服务释义""系统类型"])    else:  #为空 就说明不是详细的,xlsx就是下面的几个数据表头        sheet.append(["目标IP""开放端口""端口服务""端口协议"])    return sheet,workbook  #返回一个原则  sheet 是返回的表头内容,workbook返回的是一个表格的状态def read_file(file_name):    try:        with open(file_name,'r'as f:            return [line.strip() for line in f.readlines() if line.strip()] # 读取文件中的IP地址列表    except FileNotFoundError:        print(f"错误:文件{file_name}未找到")        return False    except Exception as e:        print(f"读取文件时候发生错误:{e}")        return Falsedef write_fails(ip_failed):#将错误的内容输入到这个文件中    with open('failed_ips.txt','w'as f:        for ip in ips_failed:            f.write(ip+'n')def save_results_to_excel(scan_results,sheet):  #将扫描的结果,给到这个函数进行数据的处理    if not isinstance(scan_results, dict):  #看是不是返回的结果是不是 字典         return False    for taskIP, IP_results in scan_results.items():#通过键值对的方式,字典格式 key被taskIP接收,value被IP_results接收         if taskIP=='runtime'#这个我猜的是如果没有正常返回,就会先循环这个runtime 这个字段            break        default_OS=""        # 填写扫描结果        if  IP_results:            if IP_results['ports']:                for port_info in IP_results['ports']:                    if port_info['state'] == 'open':                        # print(port_info)                        if not default_OS and port_info.get('service','').get("ostype",''):                            default_OS = port_info['service'].get("ostype")                        result = [taskIP,                                      port_info['portid'],                                      port_info.get('service','').get("name",""),                                      port_info['protocol']]                        if detail:                            result.extend([port_info.get('service','').get("product",""),                                      port_info.get('service','').get("version",""),                                      port_info.get('service','').get("extrainfo",""),                                      port_info.get('service','').get("ostype",default_OS)])                        sheet.append(result)    return Trueif __name__ == "__main__":    output_file="open_ports_results.xlsx"    args = '-T4 -Pn -sV'    detail ='-sV' in args or '-A' in args#这个就是说,扫描的参数如果有这两个参数,就说明是详细扫描    file_name=input("请输入文件名:")    port_numb=input("请输入你想扫描多少常见端口,-p-为全端口")    scan_port_numb=int(port_numb)    ips_list=read_file(file_name)#调用函数将txt文件写入到ips_list    ips_failed=[]# 创建一个ip列表中,用于保存由于特殊原因未扫描成功的(可能不在线)    sheet,workbook=get_sheet_wb(detail) #看是否详细扫描,    if ips_list:        print("开始扫描...")        for ip in ips_list:            try:                scan_results = scan_task(ip, scan_port_numb, args)                # print(scan_results)                finall = save_results_to_excel(scan_results, sheet)  # ?            except Exception as e:                print(f"这个{ip}有问题:{e}")                ips_failed.append(ip)#将错误ip保存到这个列表中            print(f"这个{ip}探测完毕")        workbook.save(output_file)    if ips_failed:        write_fails(ips_failed)        print(f"扫描失败的IP写入 failed_ips.txt文件")

原文始发于微信公众号(嵩艺):端口扫描工具开发

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年6月6日23:26:10
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   端口扫描工具开发https://cn-sec.com/archives/4143349.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息