package common import ( "fmt" "strings" "sync" "sync/atomic" "time" "github.com/shadow1ng/fscan/common/config" ) /* globals.go - 全局配置变量 直接定义全局变量,消除base包的双重声明。 */ var ( // ============================================================================= // 核心扫描配置 // ============================================================================= ScanMode string = DefaultScanMode // 扫描模式 ThreadNum int = DefaultThreadNum // 线程数 Timeout int64 = DefaultTimeout // 超时时间 DisablePing bool = false // 禁用ping LocalMode bool = false // 本地模式 LocalPlugin string // 本地插件选择 AliveOnly bool // 仅存活检测 DisableBrute bool // 禁用暴力破解 MaxRetries int = 3 // 最大重试次数 // ============================================================================= // 认证相关配置 // ============================================================================= Username string // 用户名 Password string // 密码 Domain string // 域 Userdict map[string][]string // 用户字典 Passwords []string // 密码列表 // ============================================================================= // 网络配置 // ============================================================================= HttpProxy string // HTTP代理 Socks5Proxy string // SOCKS5代理 WebTimeout int64 = 5 // Web超时时间 // ============================================================================= // 文件路径 // ============================================================================= SshKeyPath string // SSH密钥路径 PersistenceTargetFile string // Linux持久化目标文件 WinPEFile string // Windows PE文件 // ============================================================================= // 功能开关 // ============================================================================= NoColor bool // 禁用颜色 Silent bool // 静默模式 DisableSave bool // 禁用保存 DisableProgress bool // 禁用进度条 Language string = DefaultLanguage // 语言 LogLevel string = DefaultLogLevel // 日志级别 // ============================================================================= // 高级功能 // ============================================================================= Shellcode string // Shellcode LocalPluginsList []string // 本地插件列表 DnsLog bool // DNS日志 ForwardShellActive bool // 正向Shell状态 ReverseShellActive bool // 反向Shell状态 Socks5ProxyActive bool // SOCKS5代理状态 // ============================================================================= // 端口和服务映射 // ============================================================================= PortMap map[int][]string // 端口到服务映射 DefaultMap []string // 默认探测器映射 // ============================================================================= // 输出控制 // ============================================================================= Outputfile string = "result.txt" // 输出文件 OutputFormat string = "txt" // 输出格式 ShowProgress bool = true // 显示进度条 StartTime time.Time // 开始时间 ProgressBar interface{} // 进度条实例 OutputMutex sync.Mutex // 输出互斥锁 // ============================================================================= // 计数器 // ============================================================================= End int64 // 结束计数器 Num int64 // 数量计数器 // 网络包计数器 - 使用原子操作确保线程安全 PacketCount int64 // 总发包数量 TCPPacketCount int64 // TCP包数量总计 TCPSuccessPacketCount int64 // TCP成功连接包数量 TCPFailedPacketCount int64 // TCP失败连接包数量 UDPPacketCount int64 // UDP包数量 HTTPPacketCount int64 // HTTP请求数量 // 发包频率控制变量 PacketRateStartTime int64 // 当前分钟的开始时间戳 PacketRateCurrentCount int64 // 当前分钟内的发包数量 PacketRateMutex sync.Mutex // 发包频率控制互斥锁 // ============================================================================= // 初始化控制 // ============================================================================= initOnce sync.Once // 确保初始化只执行一次 ) // InitGlobalConfig 初始化全局配置 func InitGlobalConfig() { initOnce.Do(func() { // 初始化时间 if StartTime.IsZero() { StartTime = time.Now() } // 初始化映射和切片 if Userdict == nil { Userdict = make(map[string][]string) } if PortMap == nil { PortMap = make(map[int][]string) } if DefaultMap == nil { DefaultMap = make([]string, 0) } if Passwords == nil { Passwords = make([]string, 0) } // 从config模块获取字典和映射 if serviceDict := config.GetGlobalServiceDict(); serviceDict != nil { Userdict = serviceDict.GetAllUserDicts() Passwords = serviceDict.GetPasswords() } if probeMapping := config.GetGlobalProbeMapping(); probeMapping != nil { PortMap = probeMapping.GetAllPortMappings() DefaultMap = probeMapping.GetDefaultProbes() } }) } // init 自动初始化 func init() { InitGlobalConfig() } // POCInfo POC相关信息 type PocInfo struct { Target string PocName string } var Pocinfo PocInfo // 版本信息 const version = "2.2.1" // 日志级别常量 const ( LogLevelAll = "all" LogLevelError = "error" LogLevelBase = "base" LogLevelInfo = "info" LogLevelSuccess = "success" LogLevelDebug = "debug" LogLevelInfoSuccess = "info,success" LogLevelBaseInfoSuccess = "base,info,success" ) // LogWithProgress 已在progressmanager.go中定义,此处不重复 // ============================================================================= // 网络包计数器功能 // ============================================================================= // IncrementPacketCount 增加总包计数(原子操作) func IncrementPacketCount() int64 { return atomic.AddInt64(&PacketCount, 1) } // IncrementTCPSuccessPacketCount 增加TCP成功连接包计数(原子操作) func IncrementTCPSuccessPacketCount() int64 { atomic.AddInt64(&TCPSuccessPacketCount, 1) atomic.AddInt64(&TCPPacketCount, 1) return atomic.AddInt64(&PacketCount, 1) } // IncrementTCPFailedPacketCount 增加TCP失败连接包计数(原子操作) func IncrementTCPFailedPacketCount() int64 { atomic.AddInt64(&TCPFailedPacketCount, 1) atomic.AddInt64(&TCPPacketCount, 1) return atomic.AddInt64(&PacketCount, 1) } // IncrementUDPPacketCount 增加UDP包计数(原子操作) func IncrementUDPPacketCount() int64 { atomic.AddInt64(&UDPPacketCount, 1) return atomic.AddInt64(&PacketCount, 1) } // IncrementHTTPPacketCount 增加HTTP包计数(原子操作) func IncrementHTTPPacketCount() int64 { atomic.AddInt64(&HTTPPacketCount, 1) return atomic.AddInt64(&PacketCount, 1) } // GetPacketCount 获取总包计数(原子操作) func GetPacketCount() int64 { return atomic.LoadInt64(&PacketCount) } // GetTCPPacketCount 获取TCP包计数(原子操作) func GetTCPPacketCount() int64 { return atomic.LoadInt64(&TCPPacketCount) } // GetTCPSuccessPacketCount 获取TCP成功连接包计数(原子操作) func GetTCPSuccessPacketCount() int64 { return atomic.LoadInt64(&TCPSuccessPacketCount) } // GetTCPFailedPacketCount 获取TCP失败连接包计数(原子操作) func GetTCPFailedPacketCount() int64 { return atomic.LoadInt64(&TCPFailedPacketCount) } // GetUDPPacketCount 获取UDP包计数(原子操作) func GetUDPPacketCount() int64 { return atomic.LoadInt64(&UDPPacketCount) } // GetHTTPPacketCount 获取HTTP包计数(原子操作) func GetHTTPPacketCount() int64 { return atomic.LoadInt64(&HTTPPacketCount) } // ResetPacketCounters 重置所有包计数器(原子操作) func ResetPacketCounters() { atomic.StoreInt64(&PacketCount, 0) atomic.StoreInt64(&TCPPacketCount, 0) atomic.StoreInt64(&TCPSuccessPacketCount, 0) atomic.StoreInt64(&TCPFailedPacketCount, 0) atomic.StoreInt64(&UDPPacketCount, 0) atomic.StoreInt64(&HTTPPacketCount, 0) } // ============================================================================= // 发包频率控制功能 // ============================================================================= // CanSendPacket 检查是否可以发包 - 同时检查频率限制和总数限制 // 返回值: (可以发包, 错误信息) func CanSendPacket() (bool, string) { // 检查总数限制 if MaxPacketCount > 0 { currentTotal := atomic.LoadInt64(&PacketCount) if currentTotal >= MaxPacketCount { return false, fmt.Sprintf("已达到最大发包数量限制: %d", MaxPacketCount) } } // 检查频率限制 if PacketRateLimit > 0 { PacketRateMutex.Lock() defer PacketRateMutex.Unlock() currentTime := time.Now().Unix() / 60 // 当前分钟 // 如果是新的分钟,重置计数器 if PacketRateStartTime != currentTime { PacketRateStartTime = currentTime atomic.StoreInt64(&PacketRateCurrentCount, 0) } // 检查当前分钟的发包数是否超限 currentCount := atomic.LoadInt64(&PacketRateCurrentCount) if currentCount >= PacketRateLimit { return false, fmt.Sprintf("已达到每分钟发包频率限制: %d", PacketRateLimit) } // 增加当前分钟的发包计数 atomic.AddInt64(&PacketRateCurrentCount, 1) } return true, "" } // WaitForPacketLimit 等待直到可以发包 - 智能等待策略 func WaitForPacketLimit() error { maxWaitTime := 60 * time.Second // 最大等待1分钟 startWait := time.Now() for { canSend, reason := CanSendPacket() if canSend { return nil } // 如果是总数限制,直接返回错误 if MaxPacketCount > 0 && strings.Contains(reason, "最大发包数量") { return fmt.Errorf(reason) } // 如果等待超时,返回错误 if time.Since(startWait) > maxWaitTime { return fmt.Errorf("等待发包权限超时: %s", reason) } // 短暂休眠后重试 time.Sleep(100 * time.Millisecond) } }