perf: 优化注释

This commit is contained in:
ZacharyZcR 2025-02-07 12:08:14 +08:00
parent bcb326dbef
commit eb8cda3b7f
4 changed files with 243 additions and 146 deletions

View File

@ -9,52 +9,54 @@ 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,
@ -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,13 +152,15 @@ 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{}{}
@ -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 {

View File

@ -23,12 +23,17 @@ type ScanResult struct {
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)

View File

@ -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},
@ -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,
}) })
} }

View File

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