当前位置: 首页 > news >正文

NetBIOS实现主机探测(包含完整实现代码)

目录

前言

NetBIOS

什么是 NetBIOS?

NetBIOS 核心服务

NetBIOS 到底干什么用?

1. 名字解析(主要功能)

2. 服务发现

3. 会话管理

探测原理

存活判断的标准

代码设计思路

两阶段扫描架构

状态机设计

模块1: NetBIOS探测模块

模块2: 协议验证模块

代码分析

构造探测数据

建立连接并发送探测数据

接受并分析响应

源代码

其它


前言

判断存活的标准是服务开启+端口开启,下面进行详细讲解,这种探测方式不太常用。


NetBIOS

什么是 NetBIOS?

网络基本输入/输出系统

NetBIOS(Network Basic Input/Output System)是1983年由IBM开发的网络协议,为局域网应用程序提供统一的命令集。虽然现在逐渐被DNS取代,但在Windows网络中仍然广泛使用。

NetBIOS 核心服务

端口

协议

服务名称

功能

137/UDP

NetBIOS名称服务

NBNS

主机名解析、名称注册查询

138/UDP

NetBIOS数据报服务

NBDS

网络广播、消息传递

139/TCP

NetBIOS会话服务

NBSS

文件/打印机共享连接

NetBIOS 到底干什么用?

1.名字解析(主要功能)

你想联系"财务部电脑",但不知道它的IP地址 → 问NetBIOS:"财务部电脑的IP是多少?" → NetBIOS回答:"192.168.1.105"

2.服务发现

你想知道网络里有哪些电脑共享了打印机 → 问NetBIOS:"谁共享了打印机?" → NetBIOS回答:"技术部电脑、前台电脑"

3.会话管理

你要访问"技术部电脑"的共享文件夹 → NetBIOS帮你建立稳定连接

探测原理

基于NetBIOS名称服务协议

  • 协议: NetBIOS Name Service (NBNS)
  • 端口: UDP 137
  • 机制: 通过发送特定的NetBIOS状态查询包,根据响应判断主机存活状态

存活判断的标准

udp的137端口开启且netbios服务开启


代码设计思路

两阶段扫描架构

阶段1: 主机发现 (TCP端口扫描) → 阶段2: NetBIOS服务探测 (UDP 137端口)

设计理念:先找到存活主机,再针对性地探测服务,避免对不存在的主机进行无谓的UDP探测。

状态机设计

定义了清晰的三种状态:

  • alive: 收到有效的NetBIOS响应
  • filtered: 主机存活但NetBIOS无响应(端口被过滤)
  • dead: 主机不存活或NetBIOS服务关闭

模块1: NetBIOS探测模块

// 设计思路:UDP协议状态探测 输入: 存活主机IP 输出: NetBIOS状态结果 策略: 发送标准NetBIOS查询包,根据响应判断服务状态

模块2: 协议验证模块

// 设计思路:协议格式验证 输入: 原始网络数据 输出: 是否为有效NetBIOS响应 策略: 检查数据包长度和标志位(QR位)

代码分析

构造探测数据

func createNetBIOSQuery() []byte { return []byte{ 0x12, 0x34, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x43, 0x4B, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x00, 0x00, 0x21, 0x00, 0x01, } }

这是一个NetBIOS名称服务状态查询包

这个查询包的作用是:

  • 查询类型: NetBIOS节点状态查询 (NBSTAT)
  • 目标: 请求目标主机返回其NetBIOS名称表
  • 响应内容: 包括主机名、服务类型、MAC地址等

当这个包发送到目标的137端口时:

  • 如果主机存在且运行NetBIOS服务,会返回节点状态信息
  • 如果主机不存在或服务关闭,会超时或无响应
  • 响应包包含详细的NetBIOS名称表和MAC地址

建立连接并发送探测数据

func netbios_scan_survival(ipaddres []string) { // 阶段1: NetBIOS扫描(只对存活主机) fmt.Println("阶段1: NetBIOS扫描...") sem := make(chan struct{}, 50) for _, ip := range aliveHosts { wg.Add(1) go func(ip string) { defer wg.Done() sem <- struct{}{} defer func() { <-sem }() result := netbiosProbe(ip) mu.Lock() if result.Status != "dead" { results = append(results, result) } mu.Unlock() }(ip) } wg.Wait() ...... } // NetBIOS探测 - 只对已知存活的主机进行 func netbiosProbe(ip string) NetBIOSResult { result := NetBIOSResult{ IP: ip, Status: "dead", Port137: "关闭", } // UDP 137端口探测 conn, err := net.DialTimeout("udp", fmt.Sprintf("%s:%d", ip, 137), 3*time.Second) if err != nil { return result } defer conn.Close() conn.SetDeadline(time.Now().Add(3 * time.Second)) // 发送查询 query := createNetBIOSQuery() if _, err := conn.Write(query); err != nil { return result } ...... return result }

接受并分析响应

// NetBIOS探测 - 只对已知存活的主机进行 func netbiosProbe(ip string) NetBIOSResult { result := NetBIOSResult{ IP: ip, Status: "dead", Port137: "关闭", } ...... // 接收响应 buffer := make([]byte, 1024) n, err := conn.Read(buffer) if err != nil { if netErr, ok := err.(net.Error); ok && netErr.Timeout() { // 已知存活的主机 + UDP超时 = open|filtered result.Status = "filtered" result.Port137 = "开放或被过滤" } return result } // 收到有效响应 if n > 0 && validateNetBIOSResponse(buffer[:n]) { result.Status = "alive" result.Port137 = "开放" } return result } // 验证 NetBIOS 响应 func validateNetBIOSResponse(data []byte) bool { if len(data) < 12 { return false } // 检查响应标志位 (第3字节的最高位) flags := binary.BigEndian.Uint16(data[2:4]) isResponse := (flags & 0x8000) != 0 // 检查答案数量 answerCount := binary.BigEndian.Uint16(data[6:8]) //之前的代码没有,新添加的 return isResponse && answerCount > 0 }

长度检查

if len(data) < 12 { return false }
  • 原因: NetBINS响应包头部至少12字节
  • 作用: 过滤掉太短的无意义数据包

提取标志位

flags := binary.BigEndian.Uint16(data[2:4])
  • 位置: 数据包的第3-4字节(0-based索引2:4)
  • 格式: 大端序16位无符号整数
  • 含义: 提取NetBIOS响应标志字段

源代码

直接给出完整源代码

https://github.com/yty0v0/ReconQuiver/blob/main/internal/discovery/netbios_host/netbios.go


其它

在我写完针对多协议端口扫描和主机探测的工具后,希望通过文章整理用到的知识点,非常欢迎各位大佬指正文章内容的错误和工具的问题。

这里附上工具链接 https://github.com/yty0v0/ReconQuiver

http://www.cnnetsun.cn/news/42160.html

相关文章:

  • LangChain 文档转换器与字符分割器组件的使用
  • 科研绘图不用愁!虎贲等考 AI 用算法代替画笔,手残党也能轻松搞定学术视觉表达
  • 告别论文恐惧!虎贲等考 AI 化身灵感合伙人,带你解锁课程论文的知识创造之旅
  • ComfyUI-SeedVR2视频超分项目FP8量化技术深度解析
  • 全网最全的软件测试面试八股文(含真题答案+文档)
  • OpenResume专业简历制作工具完整使用指南
  • springboot肿瘤患者康复回访系统_109a2sb0-
  • 【KL 散度】深入理解 Kullback-Leibler Divergence:AI 如何衡量“像不像”的问题
  • 5分钟掌握LIBERO:开启终身机器人学习的革命性平台
  • 文件上传革命:jQuery File Upload如何让开发效率飙升500%
  • SolidWorks三维模型与工程图差距分析介绍
  • COMSOL模拟锌离子电池锌负极电场模型教程:从零开始构建并详细解析源文件,适合初学者的电场建模教学
  • 终极指南:如何用PIKE-RAG打造领域专属的智能问答系统
  • 5分钟从文档小白到OCR专家:Zerox如何让文字识别变得像拍照一样简单
  • RocketMQ如何防止消息丢失?
  • CSS尺寸、盒子模型、定位、浮动与布局(Flex/Grid)
  • 《构建游戏实时流失预警模型的核心逻辑》
  • 两个步骤,打包war,tomcat使用war包
  • idea修改maven的刷新引入依赖快捷键
  • 纯电动汽车Simulink仿真模型建模详细步骤。 通过文档的形式,跟着文档一步一步操作,既可以...
  • 同花顺平衡多空看图操作多空理论
  • 通达信222222测试帖别下载
  • 通达信大盘个股共振指标公式
  • 这些核心特征,让芯片散料转编带设备成行业刚需
  • ~给媳妇的新称呼~
  • java计算机毕业设计社区服务微信小程序 基于微信生态的社区便民服务平台 SpringBoot+微信小程智慧社区服务系统
  • SynthPose-VitPose终极部署指南:从零到精通的人体姿态估计实战
  • DataEase vs PowerBI:当数据分析遇见选择困难症,你该如何破局?
  • android 之 AAudio
  • anoconda简单操作