mirror of
https://github.com/shadow1ng/fscan.git
synced 2025-07-13 12:52:44 +08:00
perf: 优化注释
This commit is contained in:
parent
bcb326dbef
commit
eb8cda3b7f
116
Core/PortInfo.go
116
Core/PortInfo.go
@ -9,56 +9,58 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 服务信息结构
|
// ServiceInfo 定义服务识别的结果信息
|
||||||
type ServiceInfo struct {
|
type ServiceInfo struct {
|
||||||
Name string // 服务名称
|
Name string // 服务名称,如 http、ssh 等
|
||||||
Banner string // 服务横幅
|
Banner string // 服务返回的横幅信息
|
||||||
Version string // 版本信息
|
Version string // 服务版本号
|
||||||
Extras map[string]string // 额外信息
|
Extras map[string]string // 其他额外信息,如操作系统、产品名等
|
||||||
}
|
}
|
||||||
|
|
||||||
// Result 结构体
|
// Result 定义单次探测的结果
|
||||||
type Result struct {
|
type Result struct {
|
||||||
Service Service
|
Service Service // 识别出的服务信息
|
||||||
Banner string
|
Banner string // 服务横幅
|
||||||
Extras map[string]string
|
Extras map[string]string // 额外信息
|
||||||
Send []byte // 发送的数据
|
Send []byte // 发送的探测数据
|
||||||
Recv []byte // 接收到的数据
|
Recv []byte // 接收到的响应数据
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Service 定义服务的基本信息
|
||||||
type Service struct {
|
type Service struct {
|
||||||
Name string
|
Name string // 服务名称
|
||||||
Extras map[string]string
|
Extras map[string]string // 服务的额外属性
|
||||||
}
|
}
|
||||||
|
|
||||||
// 扫描器相关结构
|
// Info 定义单个端口探测的上下文信息
|
||||||
type Info struct {
|
type Info struct {
|
||||||
Address string
|
Address string // 目标IP地址
|
||||||
Port int
|
Port int // 目标端口
|
||||||
Conn net.Conn
|
Conn net.Conn // 网络连接
|
||||||
Result Result
|
Result Result // 探测结果
|
||||||
Found bool
|
Found bool // 是否成功识别服务
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PortInfoScanner 定义端口服务识别器
|
||||||
type PortInfoScanner struct {
|
type PortInfoScanner struct {
|
||||||
Address string
|
Address string // 目标IP地址
|
||||||
Port int
|
Port int // 目标端口
|
||||||
Conn net.Conn
|
Conn net.Conn // 网络连接
|
||||||
Timeout time.Duration
|
Timeout time.Duration // 超时时间
|
||||||
info *Info
|
info *Info // 探测上下文
|
||||||
}
|
}
|
||||||
|
|
||||||
// 预定义探测器
|
// 预定义的基础探测器
|
||||||
var (
|
var (
|
||||||
null = new(Probe)
|
null = new(Probe) // 空探测器,用于基本协议识别
|
||||||
common = new(Probe)
|
common = new(Probe) // 通用探测器,用于常见服务识别
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewPortInfoScanner 创建新的端口服务识别器
|
// NewPortInfoScanner 创建新的端口服务识别器实例
|
||||||
func NewPortInfoScanner(addr string, port int, conn net.Conn, timeout time.Duration) *PortInfoScanner {
|
func NewPortInfoScanner(addr string, port int, conn net.Conn, timeout time.Duration) *PortInfoScanner {
|
||||||
return &PortInfoScanner{
|
return &PortInfoScanner{
|
||||||
Address: addr,
|
Address: addr,
|
||||||
Port: port,
|
Port: port,
|
||||||
Conn: conn,
|
Conn: conn,
|
||||||
Timeout: timeout,
|
Timeout: timeout,
|
||||||
info: &Info{
|
info: &Info{
|
||||||
@ -72,12 +74,12 @@ func NewPortInfoScanner(addr string, port int, conn net.Conn, timeout time.Durat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Identify 识别端口服务
|
// Identify 执行服务识别,返回识别结果
|
||||||
func (s *PortInfoScanner) Identify() (*ServiceInfo, error) {
|
func (s *PortInfoScanner) Identify() (*ServiceInfo, error) {
|
||||||
Common.LogDebug(fmt.Sprintf("开始识别服务 %s:%d", s.Address, s.Port))
|
Common.LogDebug(fmt.Sprintf("开始识别服务 %s:%d", s.Address, s.Port))
|
||||||
s.info.PortInfo()
|
s.info.PortInfo()
|
||||||
|
|
||||||
// 转换识别结果
|
// 构造返回结果
|
||||||
serviceInfo := &ServiceInfo{
|
serviceInfo := &ServiceInfo{
|
||||||
Name: s.info.Result.Service.Name,
|
Name: s.info.Result.Service.Name,
|
||||||
Banner: s.info.Result.Banner,
|
Banner: s.info.Result.Banner,
|
||||||
@ -94,13 +96,13 @@ func (s *PortInfoScanner) Identify() (*ServiceInfo, error) {
|
|||||||
return serviceInfo, nil
|
return serviceInfo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// PortInfo 用于获取端口服务信息
|
// PortInfo 执行端口服务识别的主要逻辑
|
||||||
func (i *Info) PortInfo() {
|
func (i *Info) PortInfo() {
|
||||||
// 首次尝试读取响应
|
// 1. 首先尝试读取服务的初始响应
|
||||||
if response, err := i.Read(); err == nil && len(response) > 0 {
|
if response, err := i.Read(); err == nil && len(response) > 0 {
|
||||||
Common.LogDebug(fmt.Sprintf("收到初始响应: %d 字节", len(response)))
|
Common.LogDebug(fmt.Sprintf("收到初始响应: %d 字节", len(response)))
|
||||||
|
|
||||||
// 依次使用 null 和 common 探测器检查响应
|
// 使用基础探测器检查响应
|
||||||
Common.LogDebug("尝试使用基础探测器(null/common)检查响应")
|
Common.LogDebug("尝试使用基础探测器(null/common)检查响应")
|
||||||
if i.tryProbes(response, []*Probe{null, common}) {
|
if i.tryProbes(response, []*Probe{null, common}) {
|
||||||
Common.LogDebug("基础探测器匹配成功")
|
Common.LogDebug("基础探测器匹配成功")
|
||||||
@ -111,10 +113,10 @@ func (i *Info) PortInfo() {
|
|||||||
Common.LogDebug(fmt.Sprintf("读取初始响应失败: %v", err))
|
Common.LogDebug(fmt.Sprintf("读取初始响应失败: %v", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
// 记录已使用的探测器
|
// 记录已使用的探测器,避免重复使用
|
||||||
usedProbes := make(map[string]struct{})
|
usedProbes := make(map[string]struct{})
|
||||||
|
|
||||||
// 处理特定端口映射的探测
|
// 2. 尝试使用端口专用探测器
|
||||||
Common.LogDebug(fmt.Sprintf("尝试使用端口 %d 的专用探测器", i.Port))
|
Common.LogDebug(fmt.Sprintf("尝试使用端口 %d 的专用探测器", i.Port))
|
||||||
if i.processPortMapProbes(usedProbes) {
|
if i.processPortMapProbes(usedProbes) {
|
||||||
Common.LogDebug("端口专用探测器匹配成功")
|
Common.LogDebug("端口专用探测器匹配成功")
|
||||||
@ -122,7 +124,7 @@ func (i *Info) PortInfo() {
|
|||||||
}
|
}
|
||||||
Common.LogDebug("端口专用探测器未匹配")
|
Common.LogDebug("端口专用探测器未匹配")
|
||||||
|
|
||||||
// 使用默认探测器进行检测
|
// 3. 使用默认探测器列表
|
||||||
Common.LogDebug("尝试使用默认探测器列表")
|
Common.LogDebug("尝试使用默认探测器列表")
|
||||||
if i.processDefaultProbes(usedProbes) {
|
if i.processDefaultProbes(usedProbes) {
|
||||||
Common.LogDebug("默认探测器匹配成功")
|
Common.LogDebug("默认探测器匹配成功")
|
||||||
@ -130,14 +132,14 @@ func (i *Info) PortInfo() {
|
|||||||
}
|
}
|
||||||
Common.LogDebug("默认探测器未匹配")
|
Common.LogDebug("默认探测器未匹配")
|
||||||
|
|
||||||
// 如果未能识别服务,标记为未知
|
// 4. 如果所有探测都失败,标记为未知服务
|
||||||
if strings.TrimSpace(i.Result.Service.Name) == "" {
|
if strings.TrimSpace(i.Result.Service.Name) == "" {
|
||||||
Common.LogDebug("未识别出服务,标记为 unknown")
|
Common.LogDebug("未识别出服务,标记为 unknown")
|
||||||
i.Result.Service.Name = "unknown"
|
i.Result.Service.Name = "unknown"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// tryProbes 尝试使用给定的探测器列表检查响应
|
// tryProbes 尝试使用指定的探测器列表检查响应
|
||||||
func (i *Info) tryProbes(response []byte, probes []*Probe) bool {
|
func (i *Info) tryProbes(response []byte, probes []*Probe) bool {
|
||||||
for _, probe := range probes {
|
for _, probe := range probes {
|
||||||
Common.LogDebug(fmt.Sprintf("尝试探测器: %s", probe.Name))
|
Common.LogDebug(fmt.Sprintf("尝试探测器: %s", probe.Name))
|
||||||
@ -150,16 +152,18 @@ func (i *Info) tryProbes(response []byte, probes []*Probe) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// processPortMapProbes 处理端口映射中的探测器
|
// processPortMapProbes 处理端口映射中的专用探测器
|
||||||
func (i *Info) processPortMapProbes(usedProbes map[string]struct{}) bool {
|
func (i *Info) processPortMapProbes(usedProbes map[string]struct{}) bool {
|
||||||
|
// 检查是否存在端口专用探测器
|
||||||
if len(Common.PortMap[i.Port]) == 0 {
|
if len(Common.PortMap[i.Port]) == 0 {
|
||||||
Common.LogDebug(fmt.Sprintf("端口 %d 没有专用探测器", i.Port))
|
Common.LogDebug(fmt.Sprintf("端口 %d 没有专用探测器", i.Port))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 遍历端口专用探测器
|
||||||
for _, name := range Common.PortMap[i.Port] {
|
for _, name := range Common.PortMap[i.Port] {
|
||||||
Common.LogDebug(fmt.Sprintf("尝试端口专用探测器: %s", name))
|
Common.LogDebug(fmt.Sprintf("尝试端口专用探测器: %s", name))
|
||||||
usedProbes[name] = struct{}{}
|
usedProbes[name] = struct{}{}
|
||||||
probe := v.ProbesMapKName[name]
|
probe := v.ProbesMapKName[name]
|
||||||
|
|
||||||
// 解码探测数据
|
// 解码探测数据
|
||||||
@ -169,7 +173,7 @@ func (i *Info) processPortMapProbes(usedProbes map[string]struct{}) bool {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// 建立连接获取响应
|
// 发送探测数据并获取响应
|
||||||
Common.LogDebug(fmt.Sprintf("发送探测数据: %d 字节", len(probeData)))
|
Common.LogDebug(fmt.Sprintf("发送探测数据: %d 字节", len(probeData)))
|
||||||
if response := i.Connect(probeData); len(response) > 0 {
|
if response := i.Connect(probeData); len(response) > 0 {
|
||||||
Common.LogDebug(fmt.Sprintf("收到响应: %d 字节", len(response)))
|
Common.LogDebug(fmt.Sprintf("收到响应: %d 字节", len(response)))
|
||||||
@ -198,11 +202,12 @@ func (i *Info) processPortMapProbes(usedProbes map[string]struct{}) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// processDefaultProbes 处理默认探测器
|
// processDefaultProbes 处理默认探测器列表
|
||||||
func (i *Info) processDefaultProbes(usedProbes map[string]struct{}) bool {
|
func (i *Info) processDefaultProbes(usedProbes map[string]struct{}) bool {
|
||||||
failCount := 0
|
failCount := 0
|
||||||
const maxFailures = 10
|
const maxFailures = 10 // 最大失败次数
|
||||||
|
|
||||||
|
// 遍历默认探测器列表
|
||||||
for _, name := range Common.DefaultMap {
|
for _, name := range Common.DefaultMap {
|
||||||
// 跳过已使用的探测器
|
// 跳过已使用的探测器
|
||||||
if _, used := usedProbes[name]; used {
|
if _, used := usedProbes[name]; used {
|
||||||
@ -215,7 +220,7 @@ func (i *Info) processDefaultProbes(usedProbes map[string]struct{}) bool {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// 建立连接获取响应
|
// 发送探测数据并获取响应
|
||||||
response := i.Connect(probeData)
|
response := i.Connect(probeData)
|
||||||
if len(response) == 0 {
|
if len(response) == 0 {
|
||||||
failCount++
|
failCount++
|
||||||
@ -260,11 +265,11 @@ func (i *Info) processDefaultProbes(usedProbes map[string]struct{}) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetInfo 分析响应数据并获取服务信息
|
// GetInfo 分析响应数据并提取服务信息
|
||||||
func (i *Info) GetInfo(response []byte, probe *Probe) {
|
func (i *Info) GetInfo(response []byte, probe *Probe) {
|
||||||
Common.LogDebug(fmt.Sprintf("开始分析响应数据,长度: %d", len(response)))
|
Common.LogDebug(fmt.Sprintf("开始分析响应数据,长度: %d", len(response)))
|
||||||
|
|
||||||
// 响应数据长度检查
|
// 响应数据有效性检查
|
||||||
if len(response) <= 0 {
|
if len(response) <= 0 {
|
||||||
Common.LogDebug("响应数据为空")
|
Common.LogDebug("响应数据为空")
|
||||||
return
|
return
|
||||||
@ -276,8 +281,8 @@ func (i *Info) GetInfo(response []byte, probe *Probe) {
|
|||||||
softFound bool
|
softFound bool
|
||||||
)
|
)
|
||||||
|
|
||||||
Common.LogDebug(fmt.Sprintf("处理探测器 %s 的主要匹配规则", probe.Name))
|
|
||||||
// 处理主要匹配规则
|
// 处理主要匹配规则
|
||||||
|
Common.LogDebug(fmt.Sprintf("处理探测器 %s 的主要匹配规则", probe.Name))
|
||||||
if matched, match := i.processMatches(response, probe.Matchs); matched {
|
if matched, match := i.processMatches(response, probe.Matchs); matched {
|
||||||
Common.LogDebug("找到硬匹配")
|
Common.LogDebug("找到硬匹配")
|
||||||
return
|
return
|
||||||
@ -304,14 +309,14 @@ func (i *Info) GetInfo(response []byte, probe *Probe) {
|
|||||||
|
|
||||||
// 处理未找到匹配的情况
|
// 处理未找到匹配的情况
|
||||||
if !i.Found {
|
if !i.Found {
|
||||||
Common.LogDebug("未找到硬匹配,处理未匹配情况")
|
Common.LogDebug("未找到硬匹配,处理未匹配情况")
|
||||||
i.handleNoMatch(response, result, softFound, softMatch)
|
i.handleNoMatch(response, result, softFound, softMatch)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// processMatches 处理匹配规则集
|
// processMatches 处理匹配规则集
|
||||||
func (i *Info) processMatches(response []byte, matches *[]Match) (bool, *Match) {
|
func (i *Info) processMatches(response []byte, matches *[]Match) (bool, *Match) {
|
||||||
Common.LogDebug(fmt.Sprintf("开始处理匹配规则,共 %d 条", len(*matches)))
|
Common.LogDebug(fmt.Sprintf("开始处理匹配规则,共 %d 条", len(*matches)))
|
||||||
var softMatch *Match
|
var softMatch *Match
|
||||||
|
|
||||||
for _, match := range *matches {
|
for _, match := range *matches {
|
||||||
@ -387,7 +392,7 @@ func (i *Info) Connect(msg []byte) []byte {
|
|||||||
return reply
|
return reply
|
||||||
}
|
}
|
||||||
|
|
||||||
const WrTimeout = 5 // 默认超时时间(秒)
|
const WrTimeout = 5 // 默认读写超时时间(秒)
|
||||||
|
|
||||||
// Write 写入数据到连接
|
// Write 写入数据到连接
|
||||||
func (i *Info) Write(msg []byte) error {
|
func (i *Info) Write(msg []byte) error {
|
||||||
@ -402,7 +407,7 @@ func (i *Info) Write(msg []byte) error {
|
|||||||
_, err := i.Conn.Write(msg)
|
_, err := i.Conn.Write(msg)
|
||||||
if err != nil && strings.Contains(err.Error(), "close") {
|
if err != nil && strings.Contains(err.Error(), "close") {
|
||||||
i.Conn.Close()
|
i.Conn.Close()
|
||||||
// 重试连接
|
// 连接关闭时重试
|
||||||
i.Conn, err = net.DialTimeout("tcp4", fmt.Sprintf("%s:%d", i.Address, i.Port), time.Duration(6)*time.Second)
|
i.Conn, err = net.DialTimeout("tcp4", fmt.Sprintf("%s:%d", i.Address, i.Port), time.Duration(6)*time.Second)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
i.Conn.SetWriteDeadline(time.Now().Add(time.Second * time.Duration(WrTimeout)))
|
i.Conn.SetWriteDeadline(time.Now().Add(time.Second * time.Duration(WrTimeout)))
|
||||||
@ -430,7 +435,6 @@ func (i *Info) Read() ([]byte, error) {
|
|||||||
// 读取数据
|
// 读取数据
|
||||||
result, err := readFromConn(i.Conn)
|
result, err := readFromConn(i.Conn)
|
||||||
if err != nil && strings.Contains(err.Error(), "close") {
|
if err != nil && strings.Contains(err.Error(), "close") {
|
||||||
// 连接关闭的错误处理
|
|
||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -444,7 +448,7 @@ func (i *Info) Read() ([]byte, error) {
|
|||||||
|
|
||||||
// readFromConn 从连接读取数据的辅助函数
|
// readFromConn 从连接读取数据的辅助函数
|
||||||
func readFromConn(conn net.Conn) ([]byte, error) {
|
func readFromConn(conn net.Conn) ([]byte, error) {
|
||||||
size := 2 * 1024
|
size := 2 * 1024 // 读取缓冲区大小
|
||||||
var result []byte
|
var result []byte
|
||||||
|
|
||||||
for {
|
for {
|
||||||
|
@ -19,16 +19,21 @@ type Addr struct {
|
|||||||
// ScanResult 扫描结果
|
// ScanResult 扫描结果
|
||||||
type ScanResult struct {
|
type ScanResult struct {
|
||||||
Address string // IP地址
|
Address string // IP地址
|
||||||
Port int // 端口号
|
Port int // 端口号
|
||||||
Service *ServiceInfo // 服务信息
|
Service *ServiceInfo // 服务信息
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PortScan 执行端口扫描
|
||||||
|
// hostslist: 待扫描的主机列表
|
||||||
|
// ports: 待扫描的端口范围
|
||||||
|
// timeout: 超时时间(秒)
|
||||||
|
// 返回活跃地址列表
|
||||||
func PortScan(hostslist []string, ports string, timeout int64) []string {
|
func PortScan(hostslist []string, ports string, timeout int64) []string {
|
||||||
var results []ScanResult
|
var results []ScanResult
|
||||||
var aliveAddrs []string // 新增:存储活跃地址
|
var aliveAddrs []string
|
||||||
var mu sync.Mutex
|
var mu sync.Mutex
|
||||||
|
|
||||||
// 解析端口列表
|
// 解析并验证端口列表
|
||||||
probePorts := Common.ParsePort(ports)
|
probePorts := Common.ParsePort(ports)
|
||||||
if len(probePorts) == 0 {
|
if len(probePorts) == 0 {
|
||||||
Common.LogError(fmt.Sprintf("端口格式错误: %s", ports))
|
Common.LogError(fmt.Sprintf("端口格式错误: %s", ports))
|
||||||
@ -38,14 +43,14 @@ func PortScan(hostslist []string, ports string, timeout int64) []string {
|
|||||||
// 排除指定端口
|
// 排除指定端口
|
||||||
probePorts = excludeNoPorts(probePorts)
|
probePorts = excludeNoPorts(probePorts)
|
||||||
|
|
||||||
// 创建通道
|
// 初始化并发控制
|
||||||
workers := Common.ThreadNum
|
workers := Common.ThreadNum
|
||||||
addrs := make(chan Addr, 100)
|
addrs := make(chan Addr, 100) // 待扫描地址通道
|
||||||
scanResults := make(chan ScanResult, 100)
|
scanResults := make(chan ScanResult, 100) // 扫描结果通道
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
var workerWg sync.WaitGroup
|
var workerWg sync.WaitGroup
|
||||||
|
|
||||||
// 启动扫描协程
|
// 启动扫描工作协程
|
||||||
for i := 0; i < workers; i++ {
|
for i := 0; i < workers; i++ {
|
||||||
workerWg.Add(1)
|
workerWg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
@ -56,7 +61,7 @@ func PortScan(hostslist []string, ports string, timeout int64) []string {
|
|||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 接收扫描结果
|
// 启动结果处理协程
|
||||||
var resultWg sync.WaitGroup
|
var resultWg sync.WaitGroup
|
||||||
resultWg.Add(1)
|
resultWg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
@ -64,14 +69,13 @@ func PortScan(hostslist []string, ports string, timeout int64) []string {
|
|||||||
for result := range scanResults {
|
for result := range scanResults {
|
||||||
mu.Lock()
|
mu.Lock()
|
||||||
results = append(results, result)
|
results = append(results, result)
|
||||||
// 构造活跃地址字符串
|
|
||||||
aliveAddr := fmt.Sprintf("%s:%d", result.Address, result.Port)
|
aliveAddr := fmt.Sprintf("%s:%d", result.Address, result.Port)
|
||||||
aliveAddrs = append(aliveAddrs, aliveAddr)
|
aliveAddrs = append(aliveAddrs, aliveAddr)
|
||||||
mu.Unlock()
|
mu.Unlock()
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// 添加扫描目标
|
// 分发扫描任务
|
||||||
for _, port := range probePorts {
|
for _, port := range probePorts {
|
||||||
for _, host := range hostslist {
|
for _, host := range hostslist {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
@ -79,6 +83,7 @@ func PortScan(hostslist []string, ports string, timeout int64) []string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 等待所有任务完成
|
||||||
close(addrs)
|
close(addrs)
|
||||||
workerWg.Wait()
|
workerWg.Wait()
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
@ -88,6 +93,11 @@ func PortScan(hostslist []string, ports string, timeout int64) []string {
|
|||||||
return aliveAddrs
|
return aliveAddrs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PortConnect 执行单个端口连接检测
|
||||||
|
// addr: 待检测的地址
|
||||||
|
// results: 结果通道
|
||||||
|
// timeout: 超时时间
|
||||||
|
// wg: 等待组
|
||||||
func PortConnect(addr Addr, results chan<- ScanResult, timeout int64, wg *sync.WaitGroup) {
|
func PortConnect(addr Addr, results chan<- ScanResult, timeout int64, wg *sync.WaitGroup) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
||||||
@ -95,6 +105,7 @@ func PortConnect(addr Addr, results chan<- ScanResult, timeout int64, wg *sync.W
|
|||||||
var err error
|
var err error
|
||||||
var conn net.Conn
|
var conn net.Conn
|
||||||
|
|
||||||
|
// 尝试建立TCP连接
|
||||||
conn, err = Common.WrapperTcpWithTimeout("tcp4",
|
conn, err = Common.WrapperTcpWithTimeout("tcp4",
|
||||||
fmt.Sprintf("%s:%v", addr.ip, addr.port),
|
fmt.Sprintf("%s:%v", addr.ip, addr.port),
|
||||||
time.Duration(timeout)*time.Second)
|
time.Duration(timeout)*time.Second)
|
||||||
@ -107,10 +118,11 @@ func PortConnect(addr Addr, results chan<- ScanResult, timeout int64, wg *sync.W
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 记录开放端口
|
||||||
address := fmt.Sprintf("%s:%d", addr.ip, addr.port)
|
address := fmt.Sprintf("%s:%d", addr.ip, addr.port)
|
||||||
Common.LogSuccess(fmt.Sprintf("端口开放 %s", address))
|
Common.LogSuccess(fmt.Sprintf("端口开放 %s", address))
|
||||||
|
|
||||||
// 保存端口开放信息
|
// 保存端口扫描结果
|
||||||
portResult := &Common.ScanResult{
|
portResult := &Common.ScanResult{
|
||||||
Time: time.Now(),
|
Time: time.Now(),
|
||||||
Type: Common.PORT,
|
Type: Common.PORT,
|
||||||
@ -122,19 +134,19 @@ func PortConnect(addr Addr, results chan<- ScanResult, timeout int64, wg *sync.W
|
|||||||
}
|
}
|
||||||
Common.SaveResult(portResult)
|
Common.SaveResult(portResult)
|
||||||
|
|
||||||
// 创建扫描结果
|
// 构造扫描结果
|
||||||
result := ScanResult{
|
result := ScanResult{
|
||||||
Address: addr.ip,
|
Address: addr.ip,
|
||||||
Port: addr.port,
|
Port: addr.port,
|
||||||
}
|
}
|
||||||
|
|
||||||
// 服务识别
|
// 执行服务识别
|
||||||
if !Common.SkipFingerprint && conn != nil {
|
if !Common.SkipFingerprint && conn != nil {
|
||||||
scanner := NewPortInfoScanner(addr.ip, addr.port, conn, time.Duration(timeout)*time.Second)
|
scanner := NewPortInfoScanner(addr.ip, addr.port, conn, time.Duration(timeout)*time.Second)
|
||||||
if serviceInfo, err := scanner.Identify(); err == nil {
|
if serviceInfo, err := scanner.Identify(); err == nil {
|
||||||
result.Service = serviceInfo
|
result.Service = serviceInfo
|
||||||
|
|
||||||
// 构造日志消息
|
// 构造服务识别日志
|
||||||
var logMsg strings.Builder
|
var logMsg strings.Builder
|
||||||
logMsg.WriteString(fmt.Sprintf("服务识别 %s => ", address))
|
logMsg.WriteString(fmt.Sprintf("服务识别 %s => ", address))
|
||||||
|
|
||||||
@ -146,27 +158,36 @@ func PortConnect(addr Addr, results chan<- ScanResult, timeout int64, wg *sync.W
|
|||||||
logMsg.WriteString(fmt.Sprintf(" 版本:%s", serviceInfo.Version))
|
logMsg.WriteString(fmt.Sprintf(" 版本:%s", serviceInfo.Version))
|
||||||
}
|
}
|
||||||
|
|
||||||
// 构造服务详情
|
// 收集服务详细信息
|
||||||
details := map[string]interface{}{
|
details := map[string]interface{}{
|
||||||
"port": addr.port,
|
"port": addr.port,
|
||||||
"service": serviceInfo.Name,
|
"service": serviceInfo.Name,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 添加版本信息
|
||||||
if serviceInfo.Version != "" {
|
if serviceInfo.Version != "" {
|
||||||
details["version"] = serviceInfo.Version
|
details["version"] = serviceInfo.Version
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 添加产品信息
|
||||||
if v, ok := serviceInfo.Extras["vendor_product"]; ok && v != "" {
|
if v, ok := serviceInfo.Extras["vendor_product"]; ok && v != "" {
|
||||||
details["product"] = v
|
details["product"] = v
|
||||||
logMsg.WriteString(fmt.Sprintf(" 产品:%s", v))
|
logMsg.WriteString(fmt.Sprintf(" 产品:%s", v))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 添加操作系统信息
|
||||||
if v, ok := serviceInfo.Extras["os"]; ok && v != "" {
|
if v, ok := serviceInfo.Extras["os"]; ok && v != "" {
|
||||||
details["os"] = v
|
details["os"] = v
|
||||||
logMsg.WriteString(fmt.Sprintf(" 系统:%s", v))
|
logMsg.WriteString(fmt.Sprintf(" 系统:%s", v))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 添加额外信息
|
||||||
if v, ok := serviceInfo.Extras["info"]; ok && v != "" {
|
if v, ok := serviceInfo.Extras["info"]; ok && v != "" {
|
||||||
details["info"] = v
|
details["info"] = v
|
||||||
logMsg.WriteString(fmt.Sprintf(" 信息:%s", v))
|
logMsg.WriteString(fmt.Sprintf(" 信息:%s", v))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 添加Banner信息
|
||||||
if len(serviceInfo.Banner) > 0 && len(serviceInfo.Banner) < 100 {
|
if len(serviceInfo.Banner) > 0 && len(serviceInfo.Banner) < 100 {
|
||||||
details["banner"] = strings.TrimSpace(serviceInfo.Banner)
|
details["banner"] = strings.TrimSpace(serviceInfo.Banner)
|
||||||
logMsg.WriteString(fmt.Sprintf(" Banner:[%s]", strings.TrimSpace(serviceInfo.Banner)))
|
logMsg.WriteString(fmt.Sprintf(" Banner:[%s]", strings.TrimSpace(serviceInfo.Banner)))
|
||||||
@ -190,6 +211,9 @@ func PortConnect(addr Addr, results chan<- ScanResult, timeout int64, wg *sync.W
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NoPortScan 生成端口列表(不进行扫描)
|
// NoPortScan 生成端口列表(不进行扫描)
|
||||||
|
// hostslist: 主机列表
|
||||||
|
// ports: 端口范围
|
||||||
|
// 返回地址列表
|
||||||
func NoPortScan(hostslist []string, ports string) []string {
|
func NoPortScan(hostslist []string, ports string) []string {
|
||||||
var AliveAddress []string
|
var AliveAddress []string
|
||||||
|
|
||||||
@ -208,6 +232,8 @@ func NoPortScan(hostslist []string, ports string) []string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// excludeNoPorts 排除指定的端口
|
// excludeNoPorts 排除指定的端口
|
||||||
|
// ports: 原始端口列表
|
||||||
|
// 返回过滤后的端口列表
|
||||||
func excludeNoPorts(ports []int) []int {
|
func excludeNoPorts(ports []int) []int {
|
||||||
noPorts := Common.ParsePort(Common.ExcludePorts)
|
noPorts := Common.ParsePort(Common.ExcludePorts)
|
||||||
if len(noPorts) == 0 {
|
if len(noPorts) == 0 {
|
||||||
@ -220,11 +246,12 @@ func excludeNoPorts(ports []int) []int {
|
|||||||
temp[port] = struct{}{}
|
temp[port] = struct{}{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 移除需要排除的端口
|
||||||
for _, port := range noPorts {
|
for _, port := range noPorts {
|
||||||
delete(temp, port)
|
delete(temp, port)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 转换为切片并排序
|
// 转换为有序切片
|
||||||
var newPorts []int
|
var newPorts []int
|
||||||
for port := range temp {
|
for port := range temp {
|
||||||
newPorts = append(newPorts, port)
|
newPorts = append(newPorts, port)
|
||||||
|
@ -5,8 +5,11 @@ import (
|
|||||||
"github.com/shadow1ng/fscan/Plugins"
|
"github.com/shadow1ng/fscan/Plugins"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// init 初始化并注册所有扫描插件
|
||||||
|
// 包括标准端口服务扫描、特殊扫描类型和本地信息收集等
|
||||||
func init() {
|
func init() {
|
||||||
// 注册标准端口服务扫描
|
// 1. 标准网络服务扫描插件
|
||||||
|
// 文件传输和远程访问服务
|
||||||
Common.RegisterPlugin("ftp", Common.ScanPlugin{
|
Common.RegisterPlugin("ftp", Common.ScanPlugin{
|
||||||
Name: "FTP",
|
Name: "FTP",
|
||||||
Ports: []int{21},
|
Ports: []int{21},
|
||||||
@ -14,7 +17,7 @@ func init() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
Common.RegisterPlugin("ssh", Common.ScanPlugin{
|
Common.RegisterPlugin("ssh", Common.ScanPlugin{
|
||||||
Name: "SSH",
|
Name: "SSH",
|
||||||
Ports: []int{22, 2222},
|
Ports: []int{22, 2222},
|
||||||
ScanFunc: Plugins.SshScan,
|
ScanFunc: Plugins.SshScan,
|
||||||
})
|
})
|
||||||
@ -25,6 +28,7 @@ func init() {
|
|||||||
ScanFunc: Plugins.TelnetScan,
|
ScanFunc: Plugins.TelnetScan,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Windows网络服务
|
||||||
Common.RegisterPlugin("findnet", Common.ScanPlugin{
|
Common.RegisterPlugin("findnet", Common.ScanPlugin{
|
||||||
Name: "FindNet",
|
Name: "FindNet",
|
||||||
Ports: []int{135},
|
Ports: []int{135},
|
||||||
@ -43,39 +47,41 @@ func init() {
|
|||||||
ScanFunc: Plugins.SmbScan,
|
ScanFunc: Plugins.SmbScan,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 数据库服务
|
||||||
Common.RegisterPlugin("mssql", Common.ScanPlugin{
|
Common.RegisterPlugin("mssql", Common.ScanPlugin{
|
||||||
Name: "MSSQL",
|
Name: "MSSQL",
|
||||||
Ports: []int{1433, 1434}, // 支持多个端口
|
Ports: []int{1433, 1434},
|
||||||
ScanFunc: Plugins.MssqlScan,
|
ScanFunc: Plugins.MssqlScan,
|
||||||
})
|
})
|
||||||
|
|
||||||
Common.RegisterPlugin("oracle", Common.ScanPlugin{
|
Common.RegisterPlugin("oracle", Common.ScanPlugin{
|
||||||
Name: "Oracle",
|
Name: "Oracle",
|
||||||
Ports: []int{1521, 1522, 1526}, // Oracle 可能的多个端口
|
Ports: []int{1521, 1522, 1526},
|
||||||
ScanFunc: Plugins.OracleScan,
|
ScanFunc: Plugins.OracleScan,
|
||||||
})
|
})
|
||||||
|
|
||||||
Common.RegisterPlugin("mysql", Common.ScanPlugin{
|
Common.RegisterPlugin("mysql", Common.ScanPlugin{
|
||||||
Name: "MySQL",
|
Name: "MySQL",
|
||||||
Ports: []int{3306, 3307, 13306, 33306}, // MySQL 可能的端口
|
Ports: []int{3306, 3307, 13306, 33306},
|
||||||
ScanFunc: Plugins.MysqlScan,
|
ScanFunc: Plugins.MysqlScan,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 中间件和消息队列服务
|
||||||
Common.RegisterPlugin("elasticsearch", Common.ScanPlugin{
|
Common.RegisterPlugin("elasticsearch", Common.ScanPlugin{
|
||||||
Name: "Elasticsearch",
|
Name: "Elasticsearch",
|
||||||
Ports: []int{9200, 9300}, // Elasticsearch 默认HTTP和Transport端口
|
Ports: []int{9200, 9300},
|
||||||
ScanFunc: Plugins.ElasticScan,
|
ScanFunc: Plugins.ElasticScan,
|
||||||
})
|
})
|
||||||
|
|
||||||
Common.RegisterPlugin("rabbitmq", Common.ScanPlugin{
|
Common.RegisterPlugin("rabbitmq", Common.ScanPlugin{
|
||||||
Name: "RabbitMQ",
|
Name: "RabbitMQ",
|
||||||
Ports: []int{5672, 5671, 15672, 15671}, // AMQP和管理端口
|
Ports: []int{5672, 5671, 15672, 15671},
|
||||||
ScanFunc: Plugins.RabbitMQScan,
|
ScanFunc: Plugins.RabbitMQScan,
|
||||||
})
|
})
|
||||||
|
|
||||||
Common.RegisterPlugin("kafka", Common.ScanPlugin{
|
Common.RegisterPlugin("kafka", Common.ScanPlugin{
|
||||||
Name: "Kafka",
|
Name: "Kafka",
|
||||||
Ports: []int{9092, 9093}, // Kafka默认端口和SSL端口
|
Ports: []int{9092, 9093},
|
||||||
ScanFunc: Plugins.KafkaScan,
|
ScanFunc: Plugins.KafkaScan,
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -85,12 +91,14 @@ func init() {
|
|||||||
ScanFunc: Plugins.ActiveMQScan,
|
ScanFunc: Plugins.ActiveMQScan,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 目录和认证服务
|
||||||
Common.RegisterPlugin("ldap", Common.ScanPlugin{
|
Common.RegisterPlugin("ldap", Common.ScanPlugin{
|
||||||
Name: "LDAP",
|
Name: "LDAP",
|
||||||
Ports: []int{389, 636}, // LDAP标准端口和LDAPS端口
|
Ports: []int{389, 636},
|
||||||
ScanFunc: Plugins.LDAPScan,
|
ScanFunc: Plugins.LDAPScan,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 邮件服务
|
||||||
Common.RegisterPlugin("smtp", Common.ScanPlugin{
|
Common.RegisterPlugin("smtp", Common.ScanPlugin{
|
||||||
Name: "SMTP",
|
Name: "SMTP",
|
||||||
Ports: []int{25, 465, 587},
|
Ports: []int{25, 465, 587},
|
||||||
@ -99,34 +107,37 @@ func init() {
|
|||||||
|
|
||||||
Common.RegisterPlugin("imap", Common.ScanPlugin{
|
Common.RegisterPlugin("imap", Common.ScanPlugin{
|
||||||
Name: "IMAP",
|
Name: "IMAP",
|
||||||
Ports: []int{143, 993}, // 143是标准端口,993是SSL端口
|
Ports: []int{143, 993},
|
||||||
ScanFunc: Plugins.IMAPScan,
|
ScanFunc: Plugins.IMAPScan,
|
||||||
})
|
})
|
||||||
|
|
||||||
Common.RegisterPlugin("pop3", Common.ScanPlugin{
|
Common.RegisterPlugin("pop3", Common.ScanPlugin{
|
||||||
Name: "POP3",
|
Name: "POP3",
|
||||||
Ports: []int{110, 995}, // POP3和POP3S端口
|
Ports: []int{110, 995},
|
||||||
ScanFunc: Plugins.POP3Scan,
|
ScanFunc: Plugins.POP3Scan,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 网络管理和监控服务
|
||||||
Common.RegisterPlugin("snmp", Common.ScanPlugin{
|
Common.RegisterPlugin("snmp", Common.ScanPlugin{
|
||||||
Name: "SNMP",
|
Name: "SNMP",
|
||||||
Ports: []int{161, 162}, // SNMP默认端口
|
Ports: []int{161, 162},
|
||||||
ScanFunc: Plugins.SNMPScan,
|
ScanFunc: Plugins.SNMPScan,
|
||||||
})
|
})
|
||||||
|
|
||||||
Common.RegisterPlugin("modbus", Common.ScanPlugin{
|
Common.RegisterPlugin("modbus", Common.ScanPlugin{
|
||||||
Name: "Modbus",
|
Name: "Modbus",
|
||||||
Ports: []int{502, 5020}, // Modbus 默认端口
|
Ports: []int{502, 5020},
|
||||||
ScanFunc: Plugins.ModbusScan,
|
ScanFunc: Plugins.ModbusScan,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 数据同步和备份服务
|
||||||
Common.RegisterPlugin("rsync", Common.ScanPlugin{
|
Common.RegisterPlugin("rsync", Common.ScanPlugin{
|
||||||
Name: "Rsync",
|
Name: "Rsync",
|
||||||
Ports: []int{873},
|
Ports: []int{873},
|
||||||
ScanFunc: Plugins.RsyncScan,
|
ScanFunc: Plugins.RsyncScan,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// NoSQL数据库
|
||||||
Common.RegisterPlugin("cassandra", Common.ScanPlugin{
|
Common.RegisterPlugin("cassandra", Common.ScanPlugin{
|
||||||
Name: "Cassandra",
|
Name: "Cassandra",
|
||||||
Ports: []int{9042},
|
Ports: []int{9042},
|
||||||
@ -139,6 +150,7 @@ func init() {
|
|||||||
ScanFunc: Plugins.Neo4jScan,
|
ScanFunc: Plugins.Neo4jScan,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 远程桌面和显示服务
|
||||||
Common.RegisterPlugin("rdp", Common.ScanPlugin{
|
Common.RegisterPlugin("rdp", Common.ScanPlugin{
|
||||||
Name: "RDP",
|
Name: "RDP",
|
||||||
Ports: []int{3389, 13389, 33389},
|
Ports: []int{3389, 13389, 33389},
|
||||||
@ -147,19 +159,20 @@ func init() {
|
|||||||
|
|
||||||
Common.RegisterPlugin("postgres", Common.ScanPlugin{
|
Common.RegisterPlugin("postgres", Common.ScanPlugin{
|
||||||
Name: "PostgreSQL",
|
Name: "PostgreSQL",
|
||||||
Ports: []int{5432, 5433}, // PostgreSQL 可能的端口
|
Ports: []int{5432, 5433},
|
||||||
ScanFunc: Plugins.PostgresScan,
|
ScanFunc: Plugins.PostgresScan,
|
||||||
})
|
})
|
||||||
|
|
||||||
Common.RegisterPlugin("vnc", Common.ScanPlugin{
|
Common.RegisterPlugin("vnc", Common.ScanPlugin{
|
||||||
Name: "VNC",
|
Name: "VNC",
|
||||||
Ports: []int{5900, 5901, 5902}, // VNC 可能的端口
|
Ports: []int{5900, 5901, 5902},
|
||||||
ScanFunc: Plugins.VncScan,
|
ScanFunc: Plugins.VncScan,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 缓存和键值存储服务
|
||||||
Common.RegisterPlugin("redis", Common.ScanPlugin{
|
Common.RegisterPlugin("redis", Common.ScanPlugin{
|
||||||
Name: "Redis",
|
Name: "Redis",
|
||||||
Ports: []int{6379, 6380, 16379}, // Redis 可能的端口
|
Ports: []int{6379, 6380, 16379},
|
||||||
ScanFunc: Plugins.RedisScan,
|
ScanFunc: Plugins.RedisScan,
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -177,11 +190,11 @@ func init() {
|
|||||||
|
|
||||||
Common.RegisterPlugin("mongodb", Common.ScanPlugin{
|
Common.RegisterPlugin("mongodb", Common.ScanPlugin{
|
||||||
Name: "MongoDB",
|
Name: "MongoDB",
|
||||||
Ports: []int{27017, 27018}, // MongoDB 可能的端口
|
Ports: []int{27017, 27018},
|
||||||
ScanFunc: Plugins.MongodbScan,
|
ScanFunc: Plugins.MongodbScan,
|
||||||
})
|
})
|
||||||
|
|
||||||
// 注册特殊扫描类型
|
// 2. 特殊漏洞扫描插件
|
||||||
Common.RegisterPlugin("ms17010", Common.ScanPlugin{
|
Common.RegisterPlugin("ms17010", Common.ScanPlugin{
|
||||||
Name: "MS17010",
|
Name: "MS17010",
|
||||||
Ports: []int{445},
|
Ports: []int{445},
|
||||||
@ -194,19 +207,20 @@ func init() {
|
|||||||
ScanFunc: Plugins.SmbGhost,
|
ScanFunc: Plugins.SmbGhost,
|
||||||
})
|
})
|
||||||
|
|
||||||
// web 相关插件添加 WebPorts 配置
|
// 3. Web应用扫描插件
|
||||||
Common.RegisterPlugin("webtitle", Common.ScanPlugin{
|
Common.RegisterPlugin("webtitle", Common.ScanPlugin{
|
||||||
Name: "WebTitle",
|
Name: "WebTitle",
|
||||||
Ports: Common.ParsePortsFromString(Common.WebPorts), // 将 WebPorts 字符串解析为端口数组
|
Ports: Common.ParsePortsFromString(Common.WebPorts),
|
||||||
ScanFunc: Plugins.WebTitle,
|
ScanFunc: Plugins.WebTitle,
|
||||||
})
|
})
|
||||||
|
|
||||||
Common.RegisterPlugin("webpoc", Common.ScanPlugin{
|
Common.RegisterPlugin("webpoc", Common.ScanPlugin{
|
||||||
Name: "WebPoc",
|
Name: "WebPoc",
|
||||||
Ports: Common.ParsePortsFromString(Common.WebPorts), // 将 WebPorts 字符串解析为端口数组
|
Ports: Common.ParsePortsFromString(Common.WebPorts),
|
||||||
ScanFunc: Plugins.WebPoc,
|
ScanFunc: Plugins.WebPoc,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 4. Windows系统专用插件
|
||||||
Common.RegisterPlugin("smb2", Common.ScanPlugin{
|
Common.RegisterPlugin("smb2", Common.ScanPlugin{
|
||||||
Name: "SMBScan2",
|
Name: "SMBScan2",
|
||||||
Ports: []int{445},
|
Ports: []int{445},
|
||||||
@ -219,21 +233,22 @@ func init() {
|
|||||||
ScanFunc: Plugins.WmiExec,
|
ScanFunc: Plugins.WmiExec,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 5. 本地信息收集插件
|
||||||
Common.RegisterPlugin("localinfo", Common.ScanPlugin{
|
Common.RegisterPlugin("localinfo", Common.ScanPlugin{
|
||||||
Name: "LocalInfo",
|
Name: "LocalInfo",
|
||||||
Ports: []int{}, // 本地信息收集不需要端口
|
Ports: []int{},
|
||||||
ScanFunc: Plugins.LocalInfoScan,
|
ScanFunc: Plugins.LocalInfoScan,
|
||||||
})
|
})
|
||||||
|
|
||||||
Common.RegisterPlugin("dcinfo", Common.ScanPlugin{
|
Common.RegisterPlugin("dcinfo", Common.ScanPlugin{
|
||||||
Name: "DCInfo",
|
Name: "DCInfo",
|
||||||
Ports: []int{}, // 本地信息收集不需要端口
|
Ports: []int{},
|
||||||
ScanFunc: Plugins.DCInfoScan,
|
ScanFunc: Plugins.DCInfoScan,
|
||||||
})
|
})
|
||||||
|
|
||||||
Common.RegisterPlugin("minidump", Common.ScanPlugin{
|
Common.RegisterPlugin("minidump", Common.ScanPlugin{
|
||||||
Name: "MiniDump",
|
Name: "MiniDump",
|
||||||
Ports: []int{}, // 本地信息收集不需要端口
|
Ports: []int{},
|
||||||
ScanFunc: Plugins.MiniDump,
|
ScanFunc: Plugins.MiniDump,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
151
Core/Scanner.go
151
Core/Scanner.go
@ -13,76 +13,89 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 定义在文件开头
|
// 全局变量定义
|
||||||
var (
|
var (
|
||||||
LocalScan bool // 本地扫描模式标识
|
LocalScan bool // 本地扫描模式标识
|
||||||
WebScan bool // Web扫描模式标识
|
WebScan bool // Web扫描模式标识
|
||||||
)
|
)
|
||||||
|
|
||||||
// Scan 执行扫描主流程
|
// Scan 执行扫描主流程
|
||||||
|
// info: 主机信息结构体,包含扫描目标的基本信息
|
||||||
func Scan(info Common.HostInfo) {
|
func Scan(info Common.HostInfo) {
|
||||||
Common.LogInfo("开始信息扫描")
|
Common.LogInfo("开始信息扫描")
|
||||||
|
|
||||||
// 初始化HTTP客户端
|
// 初始化HTTP客户端配置
|
||||||
lib.Inithttp()
|
lib.Inithttp()
|
||||||
|
|
||||||
|
// 初始化并发控制
|
||||||
ch := make(chan struct{}, Common.ThreadNum)
|
ch := make(chan struct{}, Common.ThreadNum)
|
||||||
wg := sync.WaitGroup{}
|
wg := sync.WaitGroup{}
|
||||||
|
|
||||||
// 执行扫描逻辑
|
// 根据扫描模式执行不同的扫描策略
|
||||||
switch {
|
switch {
|
||||||
case Common.LocalMode:
|
case Common.LocalMode:
|
||||||
|
// 本地信息收集模式
|
||||||
executeLocalScan(info, &ch, &wg)
|
executeLocalScan(info, &ch, &wg)
|
||||||
case len(Common.URLs) > 0:
|
case len(Common.URLs) > 0:
|
||||||
|
// Web扫描模式
|
||||||
executeWebScan(info, &ch, &wg)
|
executeWebScan(info, &ch, &wg)
|
||||||
default:
|
default:
|
||||||
|
// 主机扫描模式
|
||||||
executeHostScan(info, &ch, &wg)
|
executeHostScan(info, &ch, &wg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 等待扫描完成
|
// 等待所有扫描任务完成
|
||||||
finishScan(&wg)
|
finishScan(&wg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 执行本地扫描
|
// executeLocalScan 执行本地扫描
|
||||||
|
// info: 主机信息
|
||||||
|
// ch: 并发控制通道
|
||||||
|
// wg: 等待组
|
||||||
func executeLocalScan(info Common.HostInfo, ch *chan struct{}, wg *sync.WaitGroup) {
|
func executeLocalScan(info Common.HostInfo, ch *chan struct{}, wg *sync.WaitGroup) {
|
||||||
Common.LogInfo("执行本地信息收集")
|
Common.LogInfo("执行本地信息收集")
|
||||||
|
|
||||||
// 定义本地模式允许的插件
|
// 获取本地模式支持的插件列表
|
||||||
validLocalPlugins := getValidPlugins(Common.ModeLocal)
|
validLocalPlugins := getValidPlugins(Common.ModeLocal)
|
||||||
|
|
||||||
// 校验扫描模式
|
// 验证扫描模式的合法性
|
||||||
if err := validateScanMode(validLocalPlugins, Common.ModeLocal); err != nil {
|
if err := validateScanMode(validLocalPlugins, Common.ModeLocal); err != nil {
|
||||||
Common.LogError(err.Error())
|
Common.LogError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 输出使用的插件信息
|
||||||
if Common.ScanMode == Common.ModeLocal {
|
if Common.ScanMode == Common.ModeLocal {
|
||||||
Common.LogInfo("使用全部本地插件")
|
Common.LogInfo("使用全部本地插件")
|
||||||
} else {
|
} else {
|
||||||
Common.LogInfo(fmt.Sprintf("使用插件: %s", Common.ScanMode))
|
Common.LogInfo(fmt.Sprintf("使用插件: %s", Common.ScanMode))
|
||||||
}
|
}
|
||||||
|
|
||||||
// 执行扫描
|
// 执行扫描任务
|
||||||
executeScans([]Common.HostInfo{info}, ch, wg)
|
executeScans([]Common.HostInfo{info}, ch, wg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 执行Web扫描
|
// executeWebScan 执行Web扫描
|
||||||
|
// info: 主机信息
|
||||||
|
// ch: 并发控制通道
|
||||||
|
// wg: 等待组
|
||||||
func executeWebScan(info Common.HostInfo, ch *chan struct{}, wg *sync.WaitGroup) {
|
func executeWebScan(info Common.HostInfo, ch *chan struct{}, wg *sync.WaitGroup) {
|
||||||
Common.LogInfo("开始Web扫描")
|
Common.LogInfo("开始Web扫描")
|
||||||
|
|
||||||
// 从 pluginGroups 获取Web模式允许的插件
|
// 获取Web模式支持的插件列表
|
||||||
validWebPlugins := getValidPlugins(Common.ModeWeb)
|
validWebPlugins := getValidPlugins(Common.ModeWeb)
|
||||||
|
|
||||||
// 校验扫描模式
|
// 验证扫描模式的合法性
|
||||||
if err := validateScanMode(validWebPlugins, Common.ModeWeb); err != nil {
|
if err := validateScanMode(validWebPlugins, Common.ModeWeb); err != nil {
|
||||||
Common.LogError(err.Error())
|
Common.LogError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建目标URL信息
|
// 处理目标URL列表
|
||||||
var targetInfos []Common.HostInfo
|
var targetInfos []Common.HostInfo
|
||||||
for _, url := range Common.URLs {
|
for _, url := range Common.URLs {
|
||||||
urlInfo := info
|
urlInfo := info
|
||||||
|
// 确保URL包含协议头
|
||||||
if !strings.HasPrefix(url, "http://") && !strings.HasPrefix(url, "https://") {
|
if !strings.HasPrefix(url, "http://") && !strings.HasPrefix(url, "https://") {
|
||||||
url = "http://" + url
|
url = "http://" + url
|
||||||
}
|
}
|
||||||
@ -90,23 +103,29 @@ func executeWebScan(info Common.HostInfo, ch *chan struct{}, wg *sync.WaitGroup)
|
|||||||
targetInfos = append(targetInfos, urlInfo)
|
targetInfos = append(targetInfos, urlInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 输出使用的插件信息
|
||||||
if Common.ScanMode == Common.ModeWeb {
|
if Common.ScanMode == Common.ModeWeb {
|
||||||
Common.LogInfo("使用全部Web插件")
|
Common.LogInfo("使用全部Web插件")
|
||||||
} else {
|
} else {
|
||||||
Common.LogInfo(fmt.Sprintf("使用插件: %s", Common.ScanMode))
|
Common.LogInfo(fmt.Sprintf("使用插件: %s", Common.ScanMode))
|
||||||
}
|
}
|
||||||
|
|
||||||
// 执行扫描
|
// 执行扫描任务
|
||||||
executeScans(targetInfos, ch, wg)
|
executeScans(targetInfos, ch, wg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 执行主机扫描
|
// executeHostScan 执行主机扫描
|
||||||
|
// info: 主机信息
|
||||||
|
// ch: 并发控制通道
|
||||||
|
// wg: 等待组
|
||||||
func executeHostScan(info Common.HostInfo, ch *chan struct{}, wg *sync.WaitGroup) {
|
func executeHostScan(info Common.HostInfo, ch *chan struct{}, wg *sync.WaitGroup) {
|
||||||
|
// 验证扫描目标
|
||||||
if info.Host == "" {
|
if info.Host == "" {
|
||||||
Common.LogError("未指定扫描目标")
|
Common.LogError("未指定扫描目标")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 解析目标主机
|
||||||
hosts, err := Common.ParseIP(info.Host, Common.HostsFile, Common.ExcludeHosts)
|
hosts, err := Common.ParseIP(info.Host, Common.HostsFile, Common.ExcludeHosts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Common.LogError(fmt.Sprintf("解析主机错误: %v", err))
|
Common.LogError(fmt.Sprintf("解析主机错误: %v", err))
|
||||||
@ -117,7 +136,9 @@ func executeHostScan(info Common.HostInfo, ch *chan struct{}, wg *sync.WaitGroup
|
|||||||
executeScan(hosts, info, ch, wg)
|
executeScan(hosts, info, ch, wg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取合法的插件列表
|
// getValidPlugins 获取指定模式下的有效插件列表
|
||||||
|
// mode: 扫描模式
|
||||||
|
// 返回: 有效插件映射表
|
||||||
func getValidPlugins(mode string) map[string]bool {
|
func getValidPlugins(mode string) map[string]bool {
|
||||||
validPlugins := make(map[string]bool)
|
validPlugins := make(map[string]bool)
|
||||||
for _, plugin := range Common.PluginGroups[mode] {
|
for _, plugin := range Common.PluginGroups[mode] {
|
||||||
@ -126,7 +147,10 @@ func getValidPlugins(mode string) map[string]bool {
|
|||||||
return validPlugins
|
return validPlugins
|
||||||
}
|
}
|
||||||
|
|
||||||
// 校验扫描模式是否有效
|
// validateScanMode 验证扫描模式的合法性
|
||||||
|
// validPlugins: 有效插件列表
|
||||||
|
// mode: 扫描模式
|
||||||
|
// 返回: 错误信息
|
||||||
func validateScanMode(validPlugins map[string]bool, mode string) error {
|
func validateScanMode(validPlugins map[string]bool, mode string) error {
|
||||||
if Common.ScanMode == "" || Common.ScanMode == "All" {
|
if Common.ScanMode == "" || Common.ScanMode == "All" {
|
||||||
Common.ScanMode = mode
|
Common.ScanMode = mode
|
||||||
@ -137,12 +161,16 @@ func validateScanMode(validPlugins map[string]bool, mode string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// executeScan 执行主扫描流程
|
// executeScan 执行主扫描流程
|
||||||
|
// hosts: 目标主机列表
|
||||||
|
// info: 主机信息
|
||||||
|
// ch: 并发控制通道
|
||||||
|
// wg: 等待组
|
||||||
func executeScan(hosts []string, info Common.HostInfo, ch *chan struct{}, wg *sync.WaitGroup) {
|
func executeScan(hosts []string, info Common.HostInfo, ch *chan struct{}, wg *sync.WaitGroup) {
|
||||||
var targetInfos []Common.HostInfo
|
var targetInfos []Common.HostInfo
|
||||||
|
|
||||||
// 扫描主机和端口
|
// 处理主机和端口扫描
|
||||||
if len(hosts) > 0 || len(Common.HostPort) > 0 {
|
if len(hosts) > 0 || len(Common.HostPort) > 0 {
|
||||||
// 处理活跃主机
|
// 检查主机存活性
|
||||||
if shouldPingScan(hosts) {
|
if shouldPingScan(hosts) {
|
||||||
hosts = CheckLive(hosts, Common.UsePing)
|
hosts = CheckLive(hosts, Common.UsePing)
|
||||||
Common.LogInfo(fmt.Sprintf("存活主机数量: %d", len(hosts)))
|
Common.LogInfo(fmt.Sprintf("存活主机数量: %d", len(hosts)))
|
||||||
@ -151,42 +179,48 @@ func executeScan(hosts []string, info Common.HostInfo, ch *chan struct{}, wg *sy
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理活跃端口
|
// 获取存活端口
|
||||||
alivePorts := getAlivePorts(hosts)
|
alivePorts := getAlivePorts(hosts)
|
||||||
if len(alivePorts) > 0 {
|
if len(alivePorts) > 0 {
|
||||||
targetInfos = prepareTargetInfos(alivePorts, info)
|
targetInfos = prepareTargetInfos(alivePorts, info)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 添加 URL 扫描目标
|
// 添加URL扫描目标
|
||||||
targetInfos = appendURLTargets(targetInfos, info)
|
targetInfos = appendURLTargets(targetInfos, info)
|
||||||
|
|
||||||
// 如果有扫描目标,执行漏洞扫描
|
// 执行漏洞扫描
|
||||||
if len(targetInfos) > 0 {
|
if len(targetInfos) > 0 {
|
||||||
Common.LogInfo("开始漏洞扫描")
|
Common.LogInfo("开始漏洞扫描")
|
||||||
executeScans(targetInfos, ch, wg)
|
executeScans(targetInfos, ch, wg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// shouldPingScan 判断是否需要进行 ping 扫描
|
// shouldPingScan 判断是否需要执行ping扫描
|
||||||
|
// hosts: 目标主机列表
|
||||||
|
// 返回: 是否需要ping扫描
|
||||||
func shouldPingScan(hosts []string) bool {
|
func shouldPingScan(hosts []string) bool {
|
||||||
return (Common.DisablePing == false && len(hosts) > 1) || Common.IsICMPScan()
|
return (Common.DisablePing == false && len(hosts) > 1) || Common.IsICMPScan()
|
||||||
}
|
}
|
||||||
|
|
||||||
// getAlivePorts 获取存活端口
|
// getAlivePorts 获取存活端口列表
|
||||||
|
// hosts: 目标主机列表
|
||||||
|
// 返回: 存活端口列表
|
||||||
func getAlivePorts(hosts []string) []string {
|
func getAlivePorts(hosts []string) []string {
|
||||||
var alivePorts []string
|
var alivePorts []string
|
||||||
|
|
||||||
|
// 根据扫描模式选择端口扫描方式
|
||||||
if Common.IsWebScan() {
|
if Common.IsWebScan() {
|
||||||
alivePorts = NoPortScan(hosts, Common.Ports)
|
alivePorts = NoPortScan(hosts, Common.Ports)
|
||||||
} else if len(hosts) > 0 {
|
} else if len(hosts) > 0 {
|
||||||
alivePorts = PortScan(hosts, Common.Ports, Common.Timeout)
|
alivePorts = PortScan(hosts, Common.Ports, Common.Timeout)
|
||||||
Common.LogInfo(fmt.Sprintf("存活端口数量: %d", len(alivePorts)))
|
Common.LogInfo(fmt.Sprintf("存活端口数量: %d", len(alivePorts)))
|
||||||
if Common.IsPortScan() {
|
if Common.IsPortScan() {
|
||||||
return nil // 结束扫描
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 合并传入的端口信息
|
// 合并额外指定的端口
|
||||||
if len(Common.HostPort) > 0 {
|
if len(Common.HostPort) > 0 {
|
||||||
alivePorts = append(alivePorts, Common.HostPort...)
|
alivePorts = append(alivePorts, Common.HostPort...)
|
||||||
alivePorts = Common.RemoveDuplicate(alivePorts)
|
alivePorts = Common.RemoveDuplicate(alivePorts)
|
||||||
@ -197,7 +231,10 @@ func getAlivePorts(hosts []string) []string {
|
|||||||
return alivePorts
|
return alivePorts
|
||||||
}
|
}
|
||||||
|
|
||||||
// appendURLTargets 添加 URL 扫描目标
|
// appendURLTargets 添加URL扫描目标
|
||||||
|
// targetInfos: 现有目标列表
|
||||||
|
// baseInfo: 基础主机信息
|
||||||
|
// 返回: 更新后的目标列表
|
||||||
func appendURLTargets(targetInfos []Common.HostInfo, baseInfo Common.HostInfo) []Common.HostInfo {
|
func appendURLTargets(targetInfos []Common.HostInfo, baseInfo Common.HostInfo) []Common.HostInfo {
|
||||||
for _, url := range Common.URLs {
|
for _, url := range Common.URLs {
|
||||||
urlInfo := baseInfo
|
urlInfo := baseInfo
|
||||||
@ -208,6 +245,9 @@ func appendURLTargets(targetInfos []Common.HostInfo, baseInfo Common.HostInfo) [
|
|||||||
}
|
}
|
||||||
|
|
||||||
// prepareTargetInfos 准备扫描目标信息
|
// prepareTargetInfos 准备扫描目标信息
|
||||||
|
// alivePorts: 存活端口列表
|
||||||
|
// baseInfo: 基础主机信息
|
||||||
|
// 返回: 目标信息列表
|
||||||
func prepareTargetInfos(alivePorts []string, baseInfo Common.HostInfo) []Common.HostInfo {
|
func prepareTargetInfos(alivePorts []string, baseInfo Common.HostInfo) []Common.HostInfo {
|
||||||
var infos []Common.HostInfo
|
var infos []Common.HostInfo
|
||||||
for _, targetIP := range alivePorts {
|
for _, targetIP := range alivePorts {
|
||||||
@ -224,24 +264,27 @@ func prepareTargetInfos(alivePorts []string, baseInfo Common.HostInfo) []Common.
|
|||||||
return infos
|
return infos
|
||||||
}
|
}
|
||||||
|
|
||||||
// 扫描任务结构体定义
|
// ScanTask 扫描任务结构体
|
||||||
type ScanTask struct {
|
type ScanTask struct {
|
||||||
pluginName string
|
pluginName string // 插件名称
|
||||||
target Common.HostInfo
|
target Common.HostInfo // 目标信息
|
||||||
}
|
}
|
||||||
|
|
||||||
// executeScans 执行扫描任务
|
// executeScans 执行扫描任务
|
||||||
|
// targets: 目标列表
|
||||||
|
// ch: 并发控制通道
|
||||||
|
// wg: 等待组
|
||||||
func executeScans(targets []Common.HostInfo, ch *chan struct{}, wg *sync.WaitGroup) {
|
func executeScans(targets []Common.HostInfo, ch *chan struct{}, wg *sync.WaitGroup) {
|
||||||
mode := Common.GetScanMode()
|
mode := Common.GetScanMode()
|
||||||
|
|
||||||
// 获取待执行的插件列表
|
// 获取要执行的插件列表
|
||||||
pluginsToRun, isSinglePlugin := getPluginsToRun(mode)
|
pluginsToRun, isSinglePlugin := getPluginsToRun(mode)
|
||||||
|
|
||||||
var tasks []ScanTask
|
var tasks []ScanTask
|
||||||
actualTasks := 0
|
actualTasks := 0
|
||||||
loadedPlugins := make([]string, 0)
|
loadedPlugins := make([]string, 0)
|
||||||
|
|
||||||
// 遍历目标,收集任务
|
// 收集扫描任务
|
||||||
for _, target := range targets {
|
for _, target := range targets {
|
||||||
targetPort, _ := strconv.Atoi(target.Ports)
|
targetPort, _ := strconv.Atoi(target.Ports)
|
||||||
for _, pluginName := range pluginsToRun {
|
for _, pluginName := range pluginsToRun {
|
||||||
@ -259,22 +302,22 @@ func executeScans(targets []Common.HostInfo, ch *chan struct{}, wg *sync.WaitGro
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 去重并排序插件
|
// 处理插件列表
|
||||||
finalPlugins := getUniquePlugins(loadedPlugins)
|
finalPlugins := getUniquePlugins(loadedPlugins)
|
||||||
|
|
||||||
// 输出加载的插件信息
|
|
||||||
Common.LogInfo(fmt.Sprintf("加载的插件: %s", strings.Join(finalPlugins, ", ")))
|
Common.LogInfo(fmt.Sprintf("加载的插件: %s", strings.Join(finalPlugins, ", ")))
|
||||||
|
|
||||||
// 初始化进度条
|
// 初始化进度条
|
||||||
initializeProgressBar(actualTasks)
|
initializeProgressBar(actualTasks)
|
||||||
|
|
||||||
// 执行收集的任务
|
// 执行扫描任务
|
||||||
for _, task := range tasks {
|
for _, task := range tasks {
|
||||||
AddScan(task.pluginName, task.target, ch, wg)
|
AddScan(task.pluginName, task.target, ch, wg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取待执行插件列表
|
// getPluginsToRun 获取要执行的插件列表
|
||||||
|
// mode: 扫描模式
|
||||||
|
// 返回: 插件列表和是否为单插件模式
|
||||||
func getPluginsToRun(mode string) ([]string, bool) {
|
func getPluginsToRun(mode string) ([]string, bool) {
|
||||||
var pluginsToRun []string
|
var pluginsToRun []string
|
||||||
isSinglePlugin := false
|
isSinglePlugin := false
|
||||||
@ -289,12 +332,17 @@ func getPluginsToRun(mode string) ([]string, bool) {
|
|||||||
return pluginsToRun, isSinglePlugin
|
return pluginsToRun, isSinglePlugin
|
||||||
}
|
}
|
||||||
|
|
||||||
// 收集扫描任务
|
// collectScanTasks 收集扫描任务
|
||||||
|
// plugin: 插件信息
|
||||||
|
// target: 目标信息
|
||||||
|
// targetPort: 目标端口
|
||||||
|
// pluginName: 插件名称
|
||||||
|
// isSinglePlugin: 是否为单插件模式
|
||||||
|
// 返回: 是否添加任务和任务列表
|
||||||
func collectScanTasks(plugin Common.ScanPlugin, target Common.HostInfo, targetPort int, pluginName string, isSinglePlugin bool) (bool, []ScanTask) {
|
func collectScanTasks(plugin Common.ScanPlugin, target Common.HostInfo, targetPort int, pluginName string, isSinglePlugin bool) (bool, []ScanTask) {
|
||||||
var tasks []ScanTask
|
var tasks []ScanTask
|
||||||
taskAdded := false
|
taskAdded := false
|
||||||
|
|
||||||
// Web模式特殊处理
|
|
||||||
if WebScan || LocalScan || isSinglePlugin || len(plugin.Ports) == 0 || plugin.HasPort(targetPort) {
|
if WebScan || LocalScan || isSinglePlugin || len(plugin.Ports) == 0 || plugin.HasPort(targetPort) {
|
||||||
taskAdded = true
|
taskAdded = true
|
||||||
tasks = append(tasks, ScanTask{
|
tasks = append(tasks, ScanTask{
|
||||||
@ -306,7 +354,9 @@ func collectScanTasks(plugin Common.ScanPlugin, target Common.HostInfo, targetPo
|
|||||||
return taskAdded, tasks
|
return taskAdded, tasks
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取去重后的插件列表
|
// getUniquePlugins 获取去重后的插件列表
|
||||||
|
// loadedPlugins: 已加载的插件列表
|
||||||
|
// 返回: 去重并排序后的插件列表
|
||||||
func getUniquePlugins(loadedPlugins []string) []string {
|
func getUniquePlugins(loadedPlugins []string) []string {
|
||||||
uniquePlugins := make(map[string]struct{})
|
uniquePlugins := make(map[string]struct{})
|
||||||
for _, p := range loadedPlugins {
|
for _, p := range loadedPlugins {
|
||||||
@ -322,7 +372,8 @@ func getUniquePlugins(loadedPlugins []string) []string {
|
|||||||
return finalPlugins
|
return finalPlugins
|
||||||
}
|
}
|
||||||
|
|
||||||
// 初始化进度条
|
// initializeProgressBar 初始化进度条
|
||||||
|
// actualTasks: 实际任务数量
|
||||||
func initializeProgressBar(actualTasks int) {
|
func initializeProgressBar(actualTasks int) {
|
||||||
if Common.ShowProgress {
|
if Common.ShowProgress {
|
||||||
Common.ProgressBar = progressbar.NewOptions(actualTasks,
|
Common.ProgressBar = progressbar.NewOptions(actualTasks,
|
||||||
@ -345,20 +396,24 @@ func initializeProgressBar(actualTasks int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// finishScan 完成扫描任务
|
// finishScan 完成扫描任务
|
||||||
|
// wg: 等待组
|
||||||
func finishScan(wg *sync.WaitGroup) {
|
func finishScan(wg *sync.WaitGroup) {
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
// 确保进度条完成,只在存在进度条时调用
|
|
||||||
if Common.ProgressBar != nil {
|
if Common.ProgressBar != nil {
|
||||||
Common.ProgressBar.Finish()
|
Common.ProgressBar.Finish()
|
||||||
fmt.Println() // 添加一个换行
|
fmt.Println()
|
||||||
}
|
}
|
||||||
Common.LogSuccess(fmt.Sprintf("扫描已完成: %v/%v", Common.End, Common.Num))
|
Common.LogSuccess(fmt.Sprintf("扫描已完成: %v/%v", Common.End, Common.Num))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mutex用于保护共享资源的并发访问
|
// Mutex 用于保护共享资源的并发访问
|
||||||
var Mutex = &sync.Mutex{}
|
var Mutex = &sync.Mutex{}
|
||||||
|
|
||||||
// AddScan 添加扫描任务并启动扫描
|
// AddScan 添加扫描任务并启动扫描
|
||||||
|
// plugin: 插件名称
|
||||||
|
// info: 目标信息
|
||||||
|
// ch: 并发控制通道
|
||||||
|
// wg: 等待组
|
||||||
func AddScan(plugin string, info Common.HostInfo, ch *chan struct{}, wg *sync.WaitGroup) {
|
func AddScan(plugin string, info Common.HostInfo, ch *chan struct{}, wg *sync.WaitGroup) {
|
||||||
*ch <- struct{}{}
|
*ch <- struct{}{}
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
@ -369,18 +424,15 @@ func AddScan(plugin string, info Common.HostInfo, ch *chan struct{}, wg *sync.Wa
|
|||||||
<-*ch
|
<-*ch
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// 使用原子操作更新扫描计数
|
|
||||||
atomic.AddInt64(&Common.Num, 1)
|
atomic.AddInt64(&Common.Num, 1)
|
||||||
|
|
||||||
// 执行扫描插件
|
|
||||||
ScanFunc(&plugin, &info)
|
ScanFunc(&plugin, &info)
|
||||||
|
|
||||||
// 更新扫描结束后的状态
|
|
||||||
updateScanProgress(&info)
|
updateScanProgress(&info)
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ScanFunc 执行扫描插件
|
// ScanFunc 执行扫描插件
|
||||||
|
// name: 插件名称
|
||||||
|
// info: 目标信息
|
||||||
func ScanFunc(name *string, info *Common.HostInfo) {
|
func ScanFunc(name *string, info *Common.HostInfo) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := recover(); err != nil {
|
if err := recover(); err != nil {
|
||||||
@ -400,12 +452,11 @@ func ScanFunc(name *string, info *Common.HostInfo) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// updateScanProgress 更新扫描进度
|
// updateScanProgress 更新扫描进度
|
||||||
|
// info: 目标信息
|
||||||
func updateScanProgress(info *Common.HostInfo) {
|
func updateScanProgress(info *Common.HostInfo) {
|
||||||
// 输出互斥锁更新进度条
|
|
||||||
Common.OutputMutex.Lock()
|
Common.OutputMutex.Lock()
|
||||||
atomic.AddInt64(&Common.End, 1)
|
atomic.AddInt64(&Common.End, 1)
|
||||||
if Common.ProgressBar != nil {
|
if Common.ProgressBar != nil {
|
||||||
// 清除当前行并更新进度条
|
|
||||||
fmt.Print("\033[2K\r")
|
fmt.Print("\033[2K\r")
|
||||||
Common.ProgressBar.Add(1)
|
Common.ProgressBar.Add(1)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user