2026-04-25 17:39:16 +08:00
|
|
|
|
package common
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
2026-06-13 19:53:28 +08:00
|
|
|
|
"os"
|
2026-04-25 17:39:16 +08:00
|
|
|
|
"time"
|
|
|
|
|
|
|
|
|
|
|
|
"github.com/shadow1ng/fscan/common/config"
|
2026-06-13 19:53:28 +08:00
|
|
|
|
"golang.org/x/term"
|
2026-04-25 17:39:16 +08:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
flag_config.go - 命令行参数直接解析到Config
|
|
|
|
|
|
|
|
|
|
|
|
flag直接写入配置结构。
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
// =============================================================================
|
|
|
|
|
|
// FlagVars - 命令行参数原始值
|
|
|
|
|
|
// =============================================================================
|
|
|
|
|
|
|
|
|
|
|
|
// FlagVars 存储命令行解析的原始值
|
|
|
|
|
|
// 某些字段需要类型转换(如 int64 秒 → time.Duration)
|
|
|
|
|
|
type FlagVars struct {
|
|
|
|
|
|
// 目标配置
|
|
|
|
|
|
Host string
|
|
|
|
|
|
ExcludeHosts string
|
|
|
|
|
|
ExcludeHostsFile string
|
|
|
|
|
|
Ports string
|
2026-10-01 12:46:29 +08:00
|
|
|
|
PortsExplicit bool
|
2026-04-25 17:39:16 +08:00
|
|
|
|
ExcludePorts string
|
|
|
|
|
|
HostsFile string
|
|
|
|
|
|
PortsFile string
|
|
|
|
|
|
|
|
|
|
|
|
// 扫描控制
|
2026-06-12 15:30:44 +08:00
|
|
|
|
ScanMode string
|
|
|
|
|
|
ThreadNum int
|
|
|
|
|
|
ThreadNumExplicit bool // 用户显式指定了 -t
|
|
|
|
|
|
ModuleThreadNum int
|
|
|
|
|
|
ModuleThreadNumExplicit bool
|
|
|
|
|
|
TimeoutSec int64 // 秒,需转换为 time.Duration
|
|
|
|
|
|
TimeoutExplicit bool
|
|
|
|
|
|
GlobalTimeout int64
|
2026-06-27 16:42:32 +08:00
|
|
|
|
GlobalTimeoutExplicit bool
|
2026-06-12 15:30:44 +08:00
|
|
|
|
DisablePing bool
|
|
|
|
|
|
DisableTcpProbe bool
|
2026-06-27 16:02:18 +08:00
|
|
|
|
DisableSubnetProbe bool
|
2026-06-12 15:30:44 +08:00
|
|
|
|
LocalPlugin string
|
|
|
|
|
|
AliveOnly bool
|
|
|
|
|
|
DisableBrute bool
|
|
|
|
|
|
MaxRetries int
|
|
|
|
|
|
MaxRetriesExplicit bool
|
2026-04-25 17:39:16 +08:00
|
|
|
|
|
|
|
|
|
|
// 认证凭据
|
|
|
|
|
|
Username string
|
|
|
|
|
|
Password string
|
|
|
|
|
|
AddUsers string
|
|
|
|
|
|
AddPasswords string
|
|
|
|
|
|
UsersFile string
|
|
|
|
|
|
PasswordsFile string
|
|
|
|
|
|
UserPassFile string
|
|
|
|
|
|
HashFile string
|
|
|
|
|
|
HashValue string
|
|
|
|
|
|
Domain string
|
|
|
|
|
|
SSHKeyPath string
|
|
|
|
|
|
|
|
|
|
|
|
// Web扫描
|
|
|
|
|
|
TargetURL string
|
|
|
|
|
|
URLsFile string
|
|
|
|
|
|
Cookie string
|
|
|
|
|
|
UserAgent string
|
|
|
|
|
|
Accept string
|
|
|
|
|
|
WebTimeout int64 // 秒
|
|
|
|
|
|
MaxRedirects int
|
|
|
|
|
|
HTTPProxy string
|
|
|
|
|
|
Socks5Proxy string
|
|
|
|
|
|
Iface string
|
|
|
|
|
|
|
|
|
|
|
|
// POC测试
|
|
|
|
|
|
PocPath string
|
|
|
|
|
|
PocName string
|
|
|
|
|
|
PocFull bool
|
|
|
|
|
|
DNSLog bool
|
|
|
|
|
|
PocNum int
|
2026-06-12 15:30:44 +08:00
|
|
|
|
PocNumExplicit bool
|
2026-04-25 17:39:16 +08:00
|
|
|
|
DisablePocScan bool
|
|
|
|
|
|
|
|
|
|
|
|
// Redis利用
|
|
|
|
|
|
RedisFile string
|
|
|
|
|
|
RedisShell string
|
|
|
|
|
|
RedisWritePath string
|
|
|
|
|
|
RedisWriteContent string
|
|
|
|
|
|
RedisWriteFile string
|
|
|
|
|
|
DisableRedis bool
|
|
|
|
|
|
|
|
|
|
|
|
// 发包频率
|
2026-06-12 15:30:44 +08:00
|
|
|
|
PacketRateLimit int64
|
|
|
|
|
|
MaxPacketCount int64
|
|
|
|
|
|
ICMPRate float64
|
|
|
|
|
|
ICMPRateExplicit bool
|
2026-04-25 17:39:16 +08:00
|
|
|
|
|
|
|
|
|
|
// 输出控制
|
|
|
|
|
|
Outputfile string
|
|
|
|
|
|
OutputFormat string
|
|
|
|
|
|
DisableSave bool
|
|
|
|
|
|
Silent bool
|
|
|
|
|
|
NoColor bool
|
|
|
|
|
|
LogLevel string
|
2026-05-13 14:41:23 +08:00
|
|
|
|
Debug bool
|
2026-04-25 17:39:16 +08:00
|
|
|
|
DisableProgress bool
|
|
|
|
|
|
PerfStats bool
|
|
|
|
|
|
Language string
|
|
|
|
|
|
|
|
|
|
|
|
// 高级功能
|
|
|
|
|
|
Shellcode string
|
|
|
|
|
|
ReverseShellTarget string
|
|
|
|
|
|
Socks5ProxyPort int
|
|
|
|
|
|
ForwardShellPort int
|
|
|
|
|
|
PersistenceTargetFile string
|
|
|
|
|
|
WinPEFile string
|
|
|
|
|
|
KeyloggerOutputFile string
|
|
|
|
|
|
DownloadURL string
|
|
|
|
|
|
DownloadSavePath string
|
|
|
|
|
|
|
|
|
|
|
|
// 帮助
|
2026-10-01 12:46:29 +08:00
|
|
|
|
ShowHelp bool
|
|
|
|
|
|
ListPlugins bool
|
2026-04-25 17:39:16 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// =============================================================================
|
|
|
|
|
|
// 全局 FlagVars 实例(仅在解析阶段使用)
|
|
|
|
|
|
// =============================================================================
|
|
|
|
|
|
|
|
|
|
|
|
var flagVars = &FlagVars{}
|
|
|
|
|
|
|
|
|
|
|
|
// GetFlagVars 获取解析后的命令行参数(供 parse.go 等使用)
|
|
|
|
|
|
func GetFlagVars() *FlagVars {
|
|
|
|
|
|
return flagVars
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// =============================================================================
|
|
|
|
|
|
// BuildConfigFromFlags - 从 FlagVars 构建 Config
|
|
|
|
|
|
// =============================================================================
|
|
|
|
|
|
|
|
|
|
|
|
// BuildConfigFromFlags 从命令行参数构建配置对象
|
|
|
|
|
|
func BuildConfigFromFlags(fv *FlagVars) *Config {
|
|
|
|
|
|
return &Config{
|
|
|
|
|
|
// 高频字段
|
2026-06-12 15:30:44 +08:00
|
|
|
|
Timeout: time.Duration(fv.TimeoutSec) * time.Second,
|
|
|
|
|
|
TimeoutExplicit: fv.TimeoutExplicit,
|
|
|
|
|
|
ThreadNum: fv.ThreadNum,
|
|
|
|
|
|
ThreadNumExplicit: fv.ThreadNumExplicit,
|
|
|
|
|
|
ModuleThreadNum: fv.ModuleThreadNum,
|
|
|
|
|
|
ModuleThreadNumExplicit: fv.ModuleThreadNumExplicit,
|
|
|
|
|
|
DisableBrute: fv.DisableBrute,
|
|
|
|
|
|
DisablePing: fv.DisablePing,
|
|
|
|
|
|
DisableTcpProbe: fv.DisableTcpProbe,
|
2026-06-27 16:02:18 +08:00
|
|
|
|
DisableSubnetProbe: fv.DisableSubnetProbe,
|
2026-04-25 17:39:16 +08:00
|
|
|
|
|
|
|
|
|
|
// 扫描模式
|
2026-06-12 15:30:44 +08:00
|
|
|
|
Mode: fv.ScanMode,
|
|
|
|
|
|
LocalMode: fv.LocalPlugin != "",
|
|
|
|
|
|
LocalPlugin: fv.LocalPlugin,
|
|
|
|
|
|
AliveOnly: fv.AliveOnly,
|
|
|
|
|
|
MaxRetries: fv.MaxRetries,
|
|
|
|
|
|
MaxRetriesExplicit: fv.MaxRetriesExplicit,
|
2026-04-25 17:39:16 +08:00
|
|
|
|
|
|
|
|
|
|
// 高级功能
|
|
|
|
|
|
Shellcode: fv.Shellcode,
|
|
|
|
|
|
LocalPluginsList: nil, // 后续解析
|
|
|
|
|
|
DNSLog: fv.DNSLog,
|
|
|
|
|
|
PersistenceTargetFile: fv.PersistenceTargetFile,
|
|
|
|
|
|
WinPEFile: fv.WinPEFile,
|
2026-06-12 19:49:07 +08:00
|
|
|
|
PortMap: clonePortMap(config.DefaultPortMap),
|
|
|
|
|
|
DefaultMap: cloneStringSlice(config.DefaultProbeMap),
|
2026-04-25 17:39:16 +08:00
|
|
|
|
|
2026-06-13 23:04:22 +08:00
|
|
|
|
// 全局超时
|
2026-06-27 16:42:32 +08:00
|
|
|
|
GlobalTimeout: time.Duration(fv.GlobalTimeout) * time.Second,
|
|
|
|
|
|
GlobalTimeoutExplicit: fv.GlobalTimeoutExplicit,
|
2026-06-13 23:04:22 +08:00
|
|
|
|
|
2026-04-25 17:39:16 +08:00
|
|
|
|
// SOCKS5代理端口
|
|
|
|
|
|
Socks5ProxyPort: fv.Socks5ProxyPort,
|
|
|
|
|
|
|
|
|
|
|
|
// 分组配置
|
|
|
|
|
|
Credentials: CredentialConfig{
|
|
|
|
|
|
Username: fv.Username,
|
|
|
|
|
|
Password: fv.Password,
|
|
|
|
|
|
Domain: fv.Domain,
|
2026-06-12 19:49:07 +08:00
|
|
|
|
Userdict: cloneStringSliceMap(config.DefaultUserDict),
|
|
|
|
|
|
Passwords: cloneStringSlice(config.DefaultPasswords),
|
2026-04-25 17:39:16 +08:00
|
|
|
|
UserPassPairs: nil, // 后续解析
|
|
|
|
|
|
SSHKeyPath: fv.SSHKeyPath,
|
|
|
|
|
|
},
|
|
|
|
|
|
Network: NetworkConfig{
|
2026-06-12 15:30:44 +08:00
|
|
|
|
HTTPProxy: fv.HTTPProxy,
|
|
|
|
|
|
Socks5Proxy: fv.Socks5Proxy,
|
|
|
|
|
|
Iface: fv.Iface,
|
|
|
|
|
|
WebTimeout: time.Duration(fv.WebTimeout) * time.Second,
|
|
|
|
|
|
MaxRedirects: fv.MaxRedirects,
|
|
|
|
|
|
PacketRateLimit: fv.PacketRateLimit,
|
|
|
|
|
|
MaxPacketCount: fv.MaxPacketCount,
|
|
|
|
|
|
ICMPRate: fv.ICMPRate,
|
|
|
|
|
|
ICMPRateExplicit: fv.ICMPRateExplicit,
|
2026-04-25 17:39:16 +08:00
|
|
|
|
},
|
|
|
|
|
|
Output: OutputConfig{
|
|
|
|
|
|
File: fv.Outputfile,
|
|
|
|
|
|
Format: fv.OutputFormat,
|
|
|
|
|
|
DisableSave: fv.DisableSave,
|
2026-06-13 19:53:28 +08:00
|
|
|
|
NoColor: fv.NoColor || !isStdoutTerminal(),
|
2026-04-25 17:39:16 +08:00
|
|
|
|
Silent: fv.Silent,
|
|
|
|
|
|
DisableProgress: fv.DisableProgress,
|
|
|
|
|
|
ShowProgress: !fv.DisableProgress,
|
|
|
|
|
|
LogLevel: fv.LogLevel,
|
|
|
|
|
|
Language: fv.Language,
|
|
|
|
|
|
PerfStats: fv.PerfStats,
|
|
|
|
|
|
},
|
|
|
|
|
|
POC: POCConfig{
|
2026-06-12 15:30:44 +08:00
|
|
|
|
PocPath: fv.PocPath,
|
|
|
|
|
|
PocName: fv.PocName,
|
|
|
|
|
|
Full: fv.PocFull,
|
|
|
|
|
|
Num: fv.PocNum,
|
|
|
|
|
|
NumExplicit: fv.PocNumExplicit,
|
|
|
|
|
|
Disabled: fv.DisablePocScan,
|
2026-04-25 17:39:16 +08:00
|
|
|
|
},
|
|
|
|
|
|
Redis: RedisConfig{
|
|
|
|
|
|
Disabled: fv.DisableRedis,
|
|
|
|
|
|
File: fv.RedisFile,
|
|
|
|
|
|
Shell: fv.RedisShell,
|
|
|
|
|
|
WritePath: fv.RedisWritePath,
|
|
|
|
|
|
WriteContent: fv.RedisWriteContent,
|
|
|
|
|
|
WriteFile: fv.RedisWriteFile,
|
|
|
|
|
|
},
|
|
|
|
|
|
HTTP: HTTPConfig{
|
|
|
|
|
|
Cookie: fv.Cookie,
|
2026-06-15 04:46:25 +08:00
|
|
|
|
UserAgent: defaultUserAgent(fv.UserAgent),
|
2026-04-25 17:39:16 +08:00
|
|
|
|
Accept: fv.Accept,
|
|
|
|
|
|
},
|
|
|
|
|
|
LocalExploit: LocalExploitConfig{
|
|
|
|
|
|
ReverseShellTarget: fv.ReverseShellTarget,
|
|
|
|
|
|
ForwardShellPort: fv.ForwardShellPort,
|
|
|
|
|
|
KeyloggerOutputFile: fv.KeyloggerOutputFile,
|
|
|
|
|
|
DownloadURL: fv.DownloadURL,
|
|
|
|
|
|
DownloadSavePath: fv.DownloadSavePath,
|
|
|
|
|
|
},
|
|
|
|
|
|
Target: TargetConfig{
|
|
|
|
|
|
Ports: fv.Ports,
|
|
|
|
|
|
ExcludePorts: fv.ExcludePorts,
|
|
|
|
|
|
},
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-06-13 19:53:28 +08:00
|
|
|
|
|
|
|
|
|
|
func isStdoutTerminal() bool {
|
|
|
|
|
|
return term.IsTerminal(int(os.Stdout.Fd()))
|
|
|
|
|
|
}
|
2026-06-15 04:46:25 +08:00
|
|
|
|
|
|
|
|
|
|
// defaultUserAgent 用户未通过 -ua 指定时回退到默认 UA,避免发送空 User-Agent 被 WAF 识别
|
|
|
|
|
|
func defaultUserAgent(ua string) string {
|
|
|
|
|
|
if ua != "" {
|
|
|
|
|
|
return ua
|
|
|
|
|
|
}
|
|
|
|
|
|
return "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
|
|
|
|
|
|
}
|