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"
)
// 服务信息结构
// ServiceInfo 定义服务识别的结果信息
type ServiceInfo struct {
Name string // 服务名称
Banner string // 服务横幅
Version string // 版本信息
Extras map[string]string // 额外信息
Name string // 服务名称,如 http、ssh 等
Banner string // 服务返回的横幅信息
Version string // 服务版本号
Extras map[string]string // 其他额外信息,如操作系统、产品名等
}
// Result 结构体
// Result 定义单次探测的结果
type Result struct {
Service Service
Banner string
Extras map[string]string
Send []byte // 发送的数据
Recv []byte // 接收到的数据
Service Service // 识别出的服务信息
Banner string // 服务横幅
Extras map[string]string // 额外信息
Send []byte // 发送的探测数据
Recv []byte // 接收到的响应数据
}
// Service 定义服务的基本信息
type Service struct {
Name string
Extras map[string]string
Name string // 服务名称
Extras map[string]string // 服务的额外属性
}
// 扫描器相关结构
// Info 定义单个端口探测的上下文信息
type Info struct {
Address string
Port int
Conn net.Conn
Result Result
Found bool
Address string // 目标IP地址
Port int // 目标端口
Conn net.Conn // 网络连接
Result Result // 探测结果
Found bool // 是否成功识别服务
}
// PortInfoScanner 定义端口服务识别器
type PortInfoScanner struct {
Address string
Port int
Conn net.Conn
Timeout time.Duration
info *Info
Address string // 目标IP地址
Port int // 目标端口
Conn net.Conn // 网络连接
Timeout time.Duration // 超时时间
info *Info // 探测上下文
}
// 预定义探测器
// 预定义的基础探测器
var (
null = new(Probe)
common = new(Probe)
null = new(Probe) // 空探测器,用于基本协议识别
common = new(Probe) // 通用探测器,用于常见服务识别
)
// NewPortInfoScanner 创建新的端口服务识别器
// NewPortInfoScanner 创建新的端口服务识别器实例
func NewPortInfoScanner(addr string, port int, conn net.Conn, timeout time.Duration) *PortInfoScanner {
return &PortInfoScanner{
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) {
Common.LogDebug(fmt.Sprintf("开始识别服务 %s:%d", s.Address, s.Port))
s.info.PortInfo()
// 转换识别结果
// 构造返回结果
serviceInfo := &ServiceInfo{
Name: s.info.Result.Service.Name,
Banner: s.info.Result.Banner,
@ -94,13 +96,13 @@ func (s *PortInfoScanner) Identify() (*ServiceInfo, error) {
return serviceInfo, nil
}
// PortInfo 用于获取端口服务信息
// PortInfo 执行端口服务识别的主要逻辑
func (i *Info) PortInfo() {
// 首次尝试读取响应
// 1. 首先尝试读取服务的初始响应
if response, err := i.Read(); err == nil && len(response) > 0 {
Common.LogDebug(fmt.Sprintf("收到初始响应: %d 字节", len(response)))
// 依次使用 null 和 common 探测器检查响应
// 使用基础探测器检查响应
Common.LogDebug("尝试使用基础探测器(null/common)检查响应")
if i.tryProbes(response, []*Probe{null, common}) {
Common.LogDebug("基础探测器匹配成功")
@ -111,10 +113,10 @@ func (i *Info) PortInfo() {
Common.LogDebug(fmt.Sprintf("读取初始响应失败: %v", err))
}
// 记录已使用的探测器
// 记录已使用的探测器,避免重复使用
usedProbes := make(map[string]struct{})
// 处理特定端口映射的探测
// 2. 尝试使用端口专用探测器
Common.LogDebug(fmt.Sprintf("尝试使用端口 %d 的专用探测器", i.Port))
if i.processPortMapProbes(usedProbes) {
Common.LogDebug("端口专用探测器匹配成功")
@ -122,7 +124,7 @@ func (i *Info) PortInfo() {
}
Common.LogDebug("端口专用探测器未匹配")
// 使用默认探测器进行检测
// 3. 使用默认探测器列表
Common.LogDebug("尝试使用默认探测器列表")
if i.processDefaultProbes(usedProbes) {
Common.LogDebug("默认探测器匹配成功")
@ -130,14 +132,14 @@ func (i *Info) PortInfo() {
}
Common.LogDebug("默认探测器未匹配")
// 如果未能识别服务,标记为未知
// 4. 如果所有探测都失败,标记为未知服务
if strings.TrimSpace(i.Result.Service.Name) == "" {
Common.LogDebug("未识别出服务标记为 unknown")
Common.LogDebug("未识别出服务,标记为 unknown")
i.Result.Service.Name = "unknown"
}
}
// tryProbes 尝试使用定的探测器列表检查响应
// tryProbes 尝试使用定的探测器列表检查响应
func (i *Info) tryProbes(response []byte, probes []*Probe) bool {
for _, probe := range probes {
Common.LogDebug(fmt.Sprintf("尝试探测器: %s", probe.Name))
@ -150,13 +152,15 @@ func (i *Info) tryProbes(response []byte, probes []*Probe) bool {
return false
}
// processPortMapProbes 处理端口映射中的探测器
// processPortMapProbes 处理端口映射中的专用探测器
func (i *Info) processPortMapProbes(usedProbes map[string]struct{}) bool {
// 检查是否存在端口专用探测器
if len(Common.PortMap[i.Port]) == 0 {
Common.LogDebug(fmt.Sprintf("端口 %d 没有专用探测器", i.Port))
return false
}
// 遍历端口专用探测器
for _, name := range Common.PortMap[i.Port] {
Common.LogDebug(fmt.Sprintf("尝试端口专用探测器: %s", name))
usedProbes[name] = struct{}{}
@ -169,7 +173,7 @@ func (i *Info) processPortMapProbes(usedProbes map[string]struct{}) bool {
continue
}
// 建立连接获取响应
// 发送探测数据并获取响应
Common.LogDebug(fmt.Sprintf("发送探测数据: %d 字节", len(probeData)))
if response := i.Connect(probeData); len(response) > 0 {
Common.LogDebug(fmt.Sprintf("收到响应: %d 字节", len(response)))
@ -198,11 +202,12 @@ func (i *Info) processPortMapProbes(usedProbes map[string]struct{}) bool {
return false
}
// processDefaultProbes 处理默认探测器
// processDefaultProbes 处理默认探测器列表
func (i *Info) processDefaultProbes(usedProbes map[string]struct{}) bool {
failCount := 0
const maxFailures = 10
const maxFailures = 10 // 最大失败次数
// 遍历默认探测器列表
for _, name := range Common.DefaultMap {
// 跳过已使用的探测器
if _, used := usedProbes[name]; used {
@ -215,7 +220,7 @@ func (i *Info) processDefaultProbes(usedProbes map[string]struct{}) bool {
continue
}
// 建立连接获取响应
// 发送探测数据并获取响应
response := i.Connect(probeData)
if len(response) == 0 {
failCount++
@ -260,11 +265,11 @@ func (i *Info) processDefaultProbes(usedProbes map[string]struct{}) bool {
return false
}
// GetInfo 分析响应数据并取服务信息
// GetInfo 分析响应数据并取服务信息
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 {
Common.LogDebug("响应数据为空")
return
@ -276,8 +281,8 @@ func (i *Info) GetInfo(response []byte, probe *Probe) {
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 {
Common.LogDebug("找到硬匹配")
return
@ -304,14 +309,14 @@ func (i *Info) GetInfo(response []byte, probe *Probe) {
// 处理未找到匹配的情况
if !i.Found {
Common.LogDebug("未找到硬匹配处理未匹配情况")
Common.LogDebug("未找到硬匹配,处理未匹配情况")
i.handleNoMatch(response, result, softFound, softMatch)
}
}
// processMatches 处理匹配规则集
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
for _, match := range *matches {
@ -387,7 +392,7 @@ func (i *Info) Connect(msg []byte) []byte {
return reply
}
const WrTimeout = 5 // 默认超时时间(秒)
const WrTimeout = 5 // 默认读写超时时间(秒)
// Write 写入数据到连接
func (i *Info) Write(msg []byte) error {
@ -402,7 +407,7 @@ func (i *Info) Write(msg []byte) error {
_, err := i.Conn.Write(msg)
if err != nil && strings.Contains(err.Error(), "close") {
i.Conn.Close()
// 重试连接
// 连接关闭时重试
i.Conn, err = net.DialTimeout("tcp4", fmt.Sprintf("%s:%d", i.Address, i.Port), time.Duration(6)*time.Second)
if err == nil {
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)
if err != nil && strings.Contains(err.Error(), "close") {
// 连接关闭的错误处理
return result, err
}
@ -444,7 +448,7 @@ func (i *Info) Read() ([]byte, error) {
// readFromConn 从连接读取数据的辅助函数
func readFromConn(conn net.Conn) ([]byte, error) {
size := 2 * 1024
size := 2 * 1024 // 读取缓冲区大小
var result []byte
for {

View File

@ -19,16 +19,21 @@ type Addr struct {
// ScanResult 扫描结果
type ScanResult struct {
Address string // IP地址
Port int // 端口号
Port int // 端口号
Service *ServiceInfo // 服务信息
}
// PortScan 执行端口扫描
// hostslist: 待扫描的主机列表
// ports: 待扫描的端口范围
// timeout: 超时时间(秒)
// 返回活跃地址列表
func PortScan(hostslist []string, ports string, timeout int64) []string {
var results []ScanResult
var aliveAddrs []string // 新增:存储活跃地址
var aliveAddrs []string
var mu sync.Mutex
// 解析端口列表
// 解析并验证端口列表
probePorts := Common.ParsePort(ports)
if len(probePorts) == 0 {
Common.LogError(fmt.Sprintf("端口格式错误: %s", ports))
@ -38,14 +43,14 @@ func PortScan(hostslist []string, ports string, timeout int64) []string {
// 排除指定端口
probePorts = excludeNoPorts(probePorts)
// 创建通道
// 初始化并发控制
workers := Common.ThreadNum
addrs := make(chan Addr, 100)
scanResults := make(chan ScanResult, 100)
addrs := make(chan Addr, 100) // 待扫描地址通道
scanResults := make(chan ScanResult, 100) // 扫描结果通道
var wg sync.WaitGroup
var workerWg sync.WaitGroup
// 启动扫描协程
// 启动扫描工作协程
for i := 0; i < workers; i++ {
workerWg.Add(1)
go func() {
@ -56,7 +61,7 @@ func PortScan(hostslist []string, ports string, timeout int64) []string {
}()
}
// 接收扫描结果
// 启动结果处理协程
var resultWg sync.WaitGroup
resultWg.Add(1)
go func() {
@ -64,14 +69,13 @@ func PortScan(hostslist []string, ports string, timeout int64) []string {
for result := range scanResults {
mu.Lock()
results = append(results, result)
// 构造活跃地址字符串
aliveAddr := fmt.Sprintf("%s:%d", result.Address, result.Port)
aliveAddrs = append(aliveAddrs, aliveAddr)
mu.Unlock()
}
}()
// 添加扫描目标
// 分发扫描任务
for _, port := range probePorts {
for _, host := range hostslist {
wg.Add(1)
@ -79,6 +83,7 @@ func PortScan(hostslist []string, ports string, timeout int64) []string {
}
}
// 等待所有任务完成
close(addrs)
workerWg.Wait()
wg.Wait()
@ -88,6 +93,11 @@ func PortScan(hostslist []string, ports string, timeout int64) []string {
return aliveAddrs
}
// PortConnect 执行单个端口连接检测
// addr: 待检测的地址
// results: 结果通道
// timeout: 超时时间
// wg: 等待组
func PortConnect(addr Addr, results chan<- ScanResult, timeout int64, wg *sync.WaitGroup) {
defer wg.Done()
@ -95,6 +105,7 @@ func PortConnect(addr Addr, results chan<- ScanResult, timeout int64, wg *sync.W
var err error
var conn net.Conn
// 尝试建立TCP连接
conn, err = Common.WrapperTcpWithTimeout("tcp4",
fmt.Sprintf("%s:%v", addr.ip, addr.port),
time.Duration(timeout)*time.Second)
@ -107,10 +118,11 @@ func PortConnect(addr Addr, results chan<- ScanResult, timeout int64, wg *sync.W
return
}
// 记录开放端口
address := fmt.Sprintf("%s:%d", addr.ip, addr.port)
Common.LogSuccess(fmt.Sprintf("端口开放 %s", address))
// 保存端口开放信息
// 保存端口扫描结果
portResult := &Common.ScanResult{
Time: time.Now(),
Type: Common.PORT,
@ -122,19 +134,19 @@ func PortConnect(addr Addr, results chan<- ScanResult, timeout int64, wg *sync.W
}
Common.SaveResult(portResult)
// 创建扫描结果
// 构造扫描结果
result := ScanResult{
Address: addr.ip,
Port: addr.port,
}
// 服务识别
// 执行服务识别
if !Common.SkipFingerprint && conn != nil {
scanner := NewPortInfoScanner(addr.ip, addr.port, conn, time.Duration(timeout)*time.Second)
if serviceInfo, err := scanner.Identify(); err == nil {
result.Service = serviceInfo
// 构造日志消息
// 构造服务识别日志
var logMsg strings.Builder
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))
}
// 构造服务详情
// 收集服务详细信息
details := map[string]interface{}{
"port": addr.port,
"service": serviceInfo.Name,
}
// 添加版本信息
if serviceInfo.Version != "" {
details["version"] = serviceInfo.Version
}
// 添加产品信息
if v, ok := serviceInfo.Extras["vendor_product"]; ok && v != "" {
details["product"] = v
logMsg.WriteString(fmt.Sprintf(" 产品:%s", v))
}
// 添加操作系统信息
if v, ok := serviceInfo.Extras["os"]; ok && v != "" {
details["os"] = v
logMsg.WriteString(fmt.Sprintf(" 系统:%s", v))
}
// 添加额外信息
if v, ok := serviceInfo.Extras["info"]; ok && v != "" {
details["info"] = v
logMsg.WriteString(fmt.Sprintf(" 信息:%s", v))
}
// 添加Banner信息
if len(serviceInfo.Banner) > 0 && len(serviceInfo.Banner) < 100 {
details["banner"] = 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 生成端口列表(不进行扫描)
// hostslist: 主机列表
// ports: 端口范围
// 返回地址列表
func NoPortScan(hostslist []string, ports string) []string {
var AliveAddress []string
@ -208,6 +232,8 @@ func NoPortScan(hostslist []string, ports string) []string {
}
// excludeNoPorts 排除指定的端口
// ports: 原始端口列表
// 返回过滤后的端口列表
func excludeNoPorts(ports []int) []int {
noPorts := Common.ParsePort(Common.ExcludePorts)
if len(noPorts) == 0 {
@ -220,11 +246,12 @@ func excludeNoPorts(ports []int) []int {
temp[port] = struct{}{}
}
// 移除需要排除的端口
for _, port := range noPorts {
delete(temp, port)
}
// 转换为切片并排序
// 转换为有序切片
var newPorts []int
for port := range temp {
newPorts = append(newPorts, port)

View File

@ -5,8 +5,11 @@ import (
"github.com/shadow1ng/fscan/Plugins"
)
// init 初始化并注册所有扫描插件
// 包括标准端口服务扫描、特殊扫描类型和本地信息收集等
func init() {
// 注册标准端口服务扫描
// 1. 标准网络服务扫描插件
// 文件传输和远程访问服务
Common.RegisterPlugin("ftp", Common.ScanPlugin{
Name: "FTP",
Ports: []int{21},
@ -25,6 +28,7 @@ func init() {
ScanFunc: Plugins.TelnetScan,
})
// Windows网络服务
Common.RegisterPlugin("findnet", Common.ScanPlugin{
Name: "FindNet",
Ports: []int{135},
@ -43,39 +47,41 @@ func init() {
ScanFunc: Plugins.SmbScan,
})
// 数据库服务
Common.RegisterPlugin("mssql", Common.ScanPlugin{
Name: "MSSQL",
Ports: []int{1433, 1434}, // 支持多个端口
Ports: []int{1433, 1434},
ScanFunc: Plugins.MssqlScan,
})
Common.RegisterPlugin("oracle", Common.ScanPlugin{
Name: "Oracle",
Ports: []int{1521, 1522, 1526}, // Oracle 可能的多个端口
Ports: []int{1521, 1522, 1526},
ScanFunc: Plugins.OracleScan,
})
Common.RegisterPlugin("mysql", Common.ScanPlugin{
Name: "MySQL",
Ports: []int{3306, 3307, 13306, 33306}, // MySQL 可能的端口
Ports: []int{3306, 3307, 13306, 33306},
ScanFunc: Plugins.MysqlScan,
})
// 中间件和消息队列服务
Common.RegisterPlugin("elasticsearch", Common.ScanPlugin{
Name: "Elasticsearch",
Ports: []int{9200, 9300}, // Elasticsearch 默认HTTP和Transport端口
Ports: []int{9200, 9300},
ScanFunc: Plugins.ElasticScan,
})
Common.RegisterPlugin("rabbitmq", Common.ScanPlugin{
Name: "RabbitMQ",
Ports: []int{5672, 5671, 15672, 15671}, // AMQP和管理端口
Ports: []int{5672, 5671, 15672, 15671},
ScanFunc: Plugins.RabbitMQScan,
})
Common.RegisterPlugin("kafka", Common.ScanPlugin{
Name: "Kafka",
Ports: []int{9092, 9093}, // Kafka默认端口和SSL端口
Ports: []int{9092, 9093},
ScanFunc: Plugins.KafkaScan,
})
@ -85,12 +91,14 @@ func init() {
ScanFunc: Plugins.ActiveMQScan,
})
// 目录和认证服务
Common.RegisterPlugin("ldap", Common.ScanPlugin{
Name: "LDAP",
Ports: []int{389, 636}, // LDAP标准端口和LDAPS端口
Ports: []int{389, 636},
ScanFunc: Plugins.LDAPScan,
})
// 邮件服务
Common.RegisterPlugin("smtp", Common.ScanPlugin{
Name: "SMTP",
Ports: []int{25, 465, 587},
@ -99,34 +107,37 @@ func init() {
Common.RegisterPlugin("imap", Common.ScanPlugin{
Name: "IMAP",
Ports: []int{143, 993}, // 143是标准端口993是SSL端口
Ports: []int{143, 993},
ScanFunc: Plugins.IMAPScan,
})
Common.RegisterPlugin("pop3", Common.ScanPlugin{
Name: "POP3",
Ports: []int{110, 995}, // POP3和POP3S端口
Ports: []int{110, 995},
ScanFunc: Plugins.POP3Scan,
})
// 网络管理和监控服务
Common.RegisterPlugin("snmp", Common.ScanPlugin{
Name: "SNMP",
Ports: []int{161, 162}, // SNMP默认端口
Ports: []int{161, 162},
ScanFunc: Plugins.SNMPScan,
})
Common.RegisterPlugin("modbus", Common.ScanPlugin{
Name: "Modbus",
Ports: []int{502, 5020}, // Modbus 默认端口
Ports: []int{502, 5020},
ScanFunc: Plugins.ModbusScan,
})
// 数据同步和备份服务
Common.RegisterPlugin("rsync", Common.ScanPlugin{
Name: "Rsync",
Ports: []int{873},
ScanFunc: Plugins.RsyncScan,
})
// NoSQL数据库
Common.RegisterPlugin("cassandra", Common.ScanPlugin{
Name: "Cassandra",
Ports: []int{9042},
@ -139,6 +150,7 @@ func init() {
ScanFunc: Plugins.Neo4jScan,
})
// 远程桌面和显示服务
Common.RegisterPlugin("rdp", Common.ScanPlugin{
Name: "RDP",
Ports: []int{3389, 13389, 33389},
@ -147,19 +159,20 @@ func init() {
Common.RegisterPlugin("postgres", Common.ScanPlugin{
Name: "PostgreSQL",
Ports: []int{5432, 5433}, // PostgreSQL 可能的端口
Ports: []int{5432, 5433},
ScanFunc: Plugins.PostgresScan,
})
Common.RegisterPlugin("vnc", Common.ScanPlugin{
Name: "VNC",
Ports: []int{5900, 5901, 5902}, // VNC 可能的端口
Ports: []int{5900, 5901, 5902},
ScanFunc: Plugins.VncScan,
})
// 缓存和键值存储服务
Common.RegisterPlugin("redis", Common.ScanPlugin{
Name: "Redis",
Ports: []int{6379, 6380, 16379}, // Redis 可能的端口
Ports: []int{6379, 6380, 16379},
ScanFunc: Plugins.RedisScan,
})
@ -177,11 +190,11 @@ func init() {
Common.RegisterPlugin("mongodb", Common.ScanPlugin{
Name: "MongoDB",
Ports: []int{27017, 27018}, // MongoDB 可能的端口
Ports: []int{27017, 27018},
ScanFunc: Plugins.MongodbScan,
})
// 注册特殊扫描类型
// 2. 特殊漏洞扫描插件
Common.RegisterPlugin("ms17010", Common.ScanPlugin{
Name: "MS17010",
Ports: []int{445},
@ -194,19 +207,20 @@ func init() {
ScanFunc: Plugins.SmbGhost,
})
// web 相关插件添加 WebPorts 配置
// 3. Web应用扫描插件
Common.RegisterPlugin("webtitle", Common.ScanPlugin{
Name: "WebTitle",
Ports: Common.ParsePortsFromString(Common.WebPorts), // 将 WebPorts 字符串解析为端口数组
Ports: Common.ParsePortsFromString(Common.WebPorts),
ScanFunc: Plugins.WebTitle,
})
Common.RegisterPlugin("webpoc", Common.ScanPlugin{
Name: "WebPoc",
Ports: Common.ParsePortsFromString(Common.WebPorts), // 将 WebPorts 字符串解析为端口数组
Ports: Common.ParsePortsFromString(Common.WebPorts),
ScanFunc: Plugins.WebPoc,
})
// 4. Windows系统专用插件
Common.RegisterPlugin("smb2", Common.ScanPlugin{
Name: "SMBScan2",
Ports: []int{445},
@ -219,21 +233,22 @@ func init() {
ScanFunc: Plugins.WmiExec,
})
// 5. 本地信息收集插件
Common.RegisterPlugin("localinfo", Common.ScanPlugin{
Name: "LocalInfo",
Ports: []int{}, // 本地信息收集不需要端口
Ports: []int{},
ScanFunc: Plugins.LocalInfoScan,
})
Common.RegisterPlugin("dcinfo", Common.ScanPlugin{
Name: "DCInfo",
Ports: []int{}, // 本地信息收集不需要端口
Ports: []int{},
ScanFunc: Plugins.DCInfoScan,
})
Common.RegisterPlugin("minidump", Common.ScanPlugin{
Name: "MiniDump",
Ports: []int{}, // 本地信息收集不需要端口
Ports: []int{},
ScanFunc: Plugins.MiniDump,
})
}

View File

@ -13,76 +13,89 @@ import (
"time"
)
// 定义在文件开头
// 全局变量定义
var (
LocalScan bool // 本地扫描模式标识
WebScan bool // Web扫描模式标识
)
// Scan 执行扫描主流程
// info: 主机信息结构体,包含扫描目标的基本信息
func Scan(info Common.HostInfo) {
Common.LogInfo("开始信息扫描")
// 初始化HTTP客户端
// 初始化HTTP客户端配置
lib.Inithttp()
// 初始化并发控制
ch := make(chan struct{}, Common.ThreadNum)
wg := sync.WaitGroup{}
// 执行扫描逻辑
// 根据扫描模式执行不同的扫描策略
switch {
case Common.LocalMode:
// 本地信息收集模式
executeLocalScan(info, &ch, &wg)
case len(Common.URLs) > 0:
// Web扫描模式
executeWebScan(info, &ch, &wg)
default:
// 主机扫描模式
executeHostScan(info, &ch, &wg)
}
// 等待扫描完成
// 等待所有扫描任务完成
finishScan(&wg)
}
// 执行本地扫描
// executeLocalScan 执行本地扫描
// info: 主机信息
// ch: 并发控制通道
// wg: 等待组
func executeLocalScan(info Common.HostInfo, ch *chan struct{}, wg *sync.WaitGroup) {
Common.LogInfo("执行本地信息收集")
// 定义本地模式允许的插件
// 获取本地模式支持的插件列表
validLocalPlugins := getValidPlugins(Common.ModeLocal)
// 验扫描模式
// 扫描模式的合法性
if err := validateScanMode(validLocalPlugins, Common.ModeLocal); err != nil {
Common.LogError(err.Error())
return
}
// 输出使用的插件信息
if Common.ScanMode == Common.ModeLocal {
Common.LogInfo("使用全部本地插件")
} else {
Common.LogInfo(fmt.Sprintf("使用插件: %s", Common.ScanMode))
}
// 执行扫描
// 执行扫描任务
executeScans([]Common.HostInfo{info}, ch, wg)
}
// 执行Web扫描
// executeWebScan 执行Web扫描
// info: 主机信息
// ch: 并发控制通道
// wg: 等待组
func executeWebScan(info Common.HostInfo, ch *chan struct{}, wg *sync.WaitGroup) {
Common.LogInfo("开始Web扫描")
// 从 pluginGroups 获取Web模式允许的插件
// 获取Web模式支持的插件列表
validWebPlugins := getValidPlugins(Common.ModeWeb)
// 验扫描模式
// 扫描模式的合法性
if err := validateScanMode(validWebPlugins, Common.ModeWeb); err != nil {
Common.LogError(err.Error())
return
}
// 创建目标URL信息
// 处理目标URL列表
var targetInfos []Common.HostInfo
for _, url := range Common.URLs {
urlInfo := info
// 确保URL包含协议头
if !strings.HasPrefix(url, "http://") && !strings.HasPrefix(url, "https://") {
url = "http://" + url
}
@ -90,23 +103,29 @@ func executeWebScan(info Common.HostInfo, ch *chan struct{}, wg *sync.WaitGroup)
targetInfos = append(targetInfos, urlInfo)
}
// 输出使用的插件信息
if Common.ScanMode == Common.ModeWeb {
Common.LogInfo("使用全部Web插件")
} else {
Common.LogInfo(fmt.Sprintf("使用插件: %s", Common.ScanMode))
}
// 执行扫描
// 执行扫描任务
executeScans(targetInfos, ch, wg)
}
// 执行主机扫描
// executeHostScan 执行主机扫描
// info: 主机信息
// ch: 并发控制通道
// wg: 等待组
func executeHostScan(info Common.HostInfo, ch *chan struct{}, wg *sync.WaitGroup) {
// 验证扫描目标
if info.Host == "" {
Common.LogError("未指定扫描目标")
return
}
// 解析目标主机
hosts, err := Common.ParseIP(info.Host, Common.HostsFile, Common.ExcludeHosts)
if err != nil {
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)
}
// 获取合法的插件列表
// getValidPlugins 获取指定模式下的有效插件列表
// mode: 扫描模式
// 返回: 有效插件映射表
func getValidPlugins(mode string) map[string]bool {
validPlugins := make(map[string]bool)
for _, plugin := range Common.PluginGroups[mode] {
@ -126,7 +147,10 @@ func getValidPlugins(mode string) map[string]bool {
return validPlugins
}
// 校验扫描模式是否有效
// validateScanMode 验证扫描模式的合法性
// validPlugins: 有效插件列表
// mode: 扫描模式
// 返回: 错误信息
func validateScanMode(validPlugins map[string]bool, mode string) error {
if Common.ScanMode == "" || Common.ScanMode == "All" {
Common.ScanMode = mode
@ -137,12 +161,16 @@ func validateScanMode(validPlugins map[string]bool, mode string) error {
}
// executeScan 执行主扫描流程
// hosts: 目标主机列表
// info: 主机信息
// ch: 并发控制通道
// wg: 等待组
func executeScan(hosts []string, info Common.HostInfo, ch *chan struct{}, wg *sync.WaitGroup) {
var targetInfos []Common.HostInfo
// 扫描主机和端口
// 处理主机和端口扫描
if len(hosts) > 0 || len(Common.HostPort) > 0 {
// 处理活跃主机
// 检查主机存活性
if shouldPingScan(hosts) {
hosts = CheckLive(hosts, Common.UsePing)
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)
if len(alivePorts) > 0 {
targetInfos = prepareTargetInfos(alivePorts, info)
}
}
// 添加 URL 扫描目标
// 添加URL扫描目标
targetInfos = appendURLTargets(targetInfos, info)
// 如果有扫描目标,执行漏洞扫描
// 执行漏洞扫描
if len(targetInfos) > 0 {
Common.LogInfo("开始漏洞扫描")
executeScans(targetInfos, ch, wg)
}
}
// shouldPingScan 判断是否需要进行 ping 扫描
// shouldPingScan 判断是否需要执行ping扫描
// hosts: 目标主机列表
// 返回: 是否需要ping扫描
func shouldPingScan(hosts []string) bool {
return (Common.DisablePing == false && len(hosts) > 1) || Common.IsICMPScan()
}
// getAlivePorts 获取存活端口
// getAlivePorts 获取存活端口列表
// hosts: 目标主机列表
// 返回: 存活端口列表
func getAlivePorts(hosts []string) []string {
var alivePorts []string
// 根据扫描模式选择端口扫描方式
if Common.IsWebScan() {
alivePorts = NoPortScan(hosts, Common.Ports)
} else if len(hosts) > 0 {
alivePorts = PortScan(hosts, Common.Ports, Common.Timeout)
Common.LogInfo(fmt.Sprintf("存活端口数量: %d", len(alivePorts)))
if Common.IsPortScan() {
return nil // 结束扫描
return nil
}
}
// 合并传入的端口信息
// 合并额外指定的端口
if len(Common.HostPort) > 0 {
alivePorts = append(alivePorts, Common.HostPort...)
alivePorts = Common.RemoveDuplicate(alivePorts)
@ -197,7 +231,10 @@ func getAlivePorts(hosts []string) []string {
return alivePorts
}
// appendURLTargets 添加 URL 扫描目标
// appendURLTargets 添加URL扫描目标
// targetInfos: 现有目标列表
// baseInfo: 基础主机信息
// 返回: 更新后的目标列表
func appendURLTargets(targetInfos []Common.HostInfo, baseInfo Common.HostInfo) []Common.HostInfo {
for _, url := range Common.URLs {
urlInfo := baseInfo
@ -208,6 +245,9 @@ func appendURLTargets(targetInfos []Common.HostInfo, baseInfo Common.HostInfo) [
}
// prepareTargetInfos 准备扫描目标信息
// alivePorts: 存活端口列表
// baseInfo: 基础主机信息
// 返回: 目标信息列表
func prepareTargetInfos(alivePorts []string, baseInfo Common.HostInfo) []Common.HostInfo {
var infos []Common.HostInfo
for _, targetIP := range alivePorts {
@ -224,24 +264,27 @@ func prepareTargetInfos(alivePorts []string, baseInfo Common.HostInfo) []Common.
return infos
}
// 扫描任务结构体定义
// ScanTask 扫描任务结构体
type ScanTask struct {
pluginName string
target Common.HostInfo
pluginName string // 插件名称
target Common.HostInfo // 目标信息
}
// executeScans 执行扫描任务
// targets: 目标列表
// ch: 并发控制通道
// wg: 等待组
func executeScans(targets []Common.HostInfo, ch *chan struct{}, wg *sync.WaitGroup) {
mode := Common.GetScanMode()
// 获取执行的插件列表
// 获取执行的插件列表
pluginsToRun, isSinglePlugin := getPluginsToRun(mode)
var tasks []ScanTask
actualTasks := 0
loadedPlugins := make([]string, 0)
// 遍历目标,收集任务
// 收集扫描任务
for _, target := range targets {
targetPort, _ := strconv.Atoi(target.Ports)
for _, pluginName := range pluginsToRun {
@ -259,22 +302,22 @@ func executeScans(targets []Common.HostInfo, ch *chan struct{}, wg *sync.WaitGro
}
}
// 去重并排序插件
// 处理插件列表
finalPlugins := getUniquePlugins(loadedPlugins)
// 输出加载的插件信息
Common.LogInfo(fmt.Sprintf("加载的插件: %s", strings.Join(finalPlugins, ", ")))
// 初始化进度条
initializeProgressBar(actualTasks)
// 执行收集的任务
// 执行扫描任务
for _, task := range tasks {
AddScan(task.pluginName, task.target, ch, wg)
}
}
// 获取待执行插件列表
// getPluginsToRun 获取要执行的插件列表
// mode: 扫描模式
// 返回: 插件列表和是否为单插件模式
func getPluginsToRun(mode string) ([]string, bool) {
var pluginsToRun []string
isSinglePlugin := false
@ -289,12 +332,17 @@ func getPluginsToRun(mode string) ([]string, bool) {
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) {
var tasks []ScanTask
taskAdded := false
// Web模式特殊处理
if WebScan || LocalScan || isSinglePlugin || len(plugin.Ports) == 0 || plugin.HasPort(targetPort) {
taskAdded = true
tasks = append(tasks, ScanTask{
@ -306,7 +354,9 @@ func collectScanTasks(plugin Common.ScanPlugin, target Common.HostInfo, targetPo
return taskAdded, tasks
}
// 获取去重后的插件列表
// getUniquePlugins 获取去重后的插件列表
// loadedPlugins: 已加载的插件列表
// 返回: 去重并排序后的插件列表
func getUniquePlugins(loadedPlugins []string) []string {
uniquePlugins := make(map[string]struct{})
for _, p := range loadedPlugins {
@ -322,7 +372,8 @@ func getUniquePlugins(loadedPlugins []string) []string {
return finalPlugins
}
// 初始化进度条
// initializeProgressBar 初始化进度条
// actualTasks: 实际任务数量
func initializeProgressBar(actualTasks int) {
if Common.ShowProgress {
Common.ProgressBar = progressbar.NewOptions(actualTasks,
@ -345,20 +396,24 @@ func initializeProgressBar(actualTasks int) {
}
// finishScan 完成扫描任务
// wg: 等待组
func finishScan(wg *sync.WaitGroup) {
wg.Wait()
// 确保进度条完成,只在存在进度条时调用
if Common.ProgressBar != nil {
Common.ProgressBar.Finish()
fmt.Println() // 添加一个换行
fmt.Println()
}
Common.LogSuccess(fmt.Sprintf("扫描已完成: %v/%v", Common.End, Common.Num))
}
// Mutex用于保护共享资源的并发访问
// Mutex 用于保护共享资源的并发访问
var Mutex = &sync.Mutex{}
// AddScan 添加扫描任务并启动扫描
// plugin: 插件名称
// info: 目标信息
// ch: 并发控制通道
// wg: 等待组
func AddScan(plugin string, info Common.HostInfo, ch *chan struct{}, wg *sync.WaitGroup) {
*ch <- struct{}{}
wg.Add(1)
@ -369,18 +424,15 @@ func AddScan(plugin string, info Common.HostInfo, ch *chan struct{}, wg *sync.Wa
<-*ch
}()
// 使用原子操作更新扫描计数
atomic.AddInt64(&Common.Num, 1)
// 执行扫描插件
ScanFunc(&plugin, &info)
// 更新扫描结束后的状态
updateScanProgress(&info)
}()
}
// ScanFunc 执行扫描插件
// name: 插件名称
// info: 目标信息
func ScanFunc(name *string, info *Common.HostInfo) {
defer func() {
if err := recover(); err != nil {
@ -400,12 +452,11 @@ func ScanFunc(name *string, info *Common.HostInfo) {
}
// updateScanProgress 更新扫描进度
// info: 目标信息
func updateScanProgress(info *Common.HostInfo) {
// 输出互斥锁更新进度条
Common.OutputMutex.Lock()
atomic.AddInt64(&Common.End, 1)
if Common.ProgressBar != nil {
// 清除当前行并更新进度条
fmt.Print("\033[2K\r")
Common.ProgressBar.Add(1)
}