fscan/Common/Parse.go

533 lines
12 KiB
Go
Raw Normal View History

2024-12-18 22:00:18 +08:00
package Common
2020-12-29 17:17:10 +08:00
import (
"bufio"
"encoding/hex"
"flag"
2020-12-29 17:17:10 +08:00
"fmt"
"net/url"
2020-12-29 17:17:10 +08:00
"os"
"strings"
)
2025-04-14 02:36:16 +08:00
// Parse 配置解析的总入口函数
// 协调调用各解析子函数,完成完整的配置处理流程
2024-12-22 02:31:29 +08:00
func Parse(Info *HostInfo) error {
2025-04-14 02:36:16 +08:00
// 按照依赖顺序解析各类配置
if err := ParseUser(); err != nil {
return fmt.Errorf("用户名解析错误: %v", err)
}
if err := ParsePass(Info); err != nil {
return fmt.Errorf("密码与目标解析错误: %v", err)
}
2024-12-22 02:31:29 +08:00
if err := ParseInput(Info); err != nil {
2025-04-14 02:36:16 +08:00
return fmt.Errorf("输入参数解析错误: %v", err)
2024-12-22 02:31:29 +08:00
}
2025-04-14 02:36:16 +08:00
2024-12-22 02:31:29 +08:00
return nil
2020-12-29 17:17:10 +08:00
}
// ParseUser 解析用户名配置
2025-04-14 02:36:16 +08:00
// 处理直接指定的用户名和从文件加载的用户名,更新全局用户字典
func ParseUser() error {
2025-04-14 02:36:16 +08:00
// 如果未指定用户名和用户名文件,无需处理
2024-12-20 03:46:09 +08:00
if Username == "" && UsersFile == "" {
return nil
2021-09-11 16:43:38 +08:00
}
2025-04-14 02:36:16 +08:00
// 收集所有用户名
var usernames []string
2025-04-14 02:36:16 +08:00
// 处理命令行参数指定的用户名列表
2022-07-03 23:41:39 +08:00
if Username != "" {
usernames = strings.Split(Username, ",")
2025-02-07 13:10:06 +08:00
LogInfo(GetText("no_username_specified", len(usernames)))
2020-12-29 17:17:10 +08:00
}
2021-09-11 16:43:38 +08:00
// 从文件加载用户名列表
2024-12-20 03:46:09 +08:00
if UsersFile != "" {
2025-04-14 02:36:16 +08:00
fileUsers, err := ReadFileLines(UsersFile)
if err != nil {
return fmt.Errorf("读取用户名文件失败: %v", err)
}
2025-04-14 02:36:16 +08:00
// 添加非空用户名
for _, user := range fileUsers {
if user != "" {
usernames = append(usernames, user)
2020-12-29 17:17:10 +08:00
}
}
2025-04-14 02:36:16 +08:00
LogInfo(GetText("load_usernames_from_file", len(fileUsers)))
2020-12-29 17:17:10 +08:00
}
// 去重处理
usernames = RemoveDuplicate(usernames)
2025-02-07 13:10:06 +08:00
LogInfo(GetText("total_usernames", len(usernames)))
2025-04-14 02:36:16 +08:00
// 更新所有字典的用户名列表
2021-09-11 16:43:38 +08:00
for name := range Userdict {
Userdict[name] = usernames
2021-09-11 16:43:38 +08:00
}
return nil
2020-12-29 17:17:10 +08:00
}
2025-04-14 02:36:16 +08:00
// ParsePass 解析密码、URL、主机和端口等目标配置
// 处理多种输入源的配置,并更新全局目标信息
2024-12-19 16:15:53 +08:00
func ParsePass(Info *HostInfo) error {
2025-04-14 02:36:16 +08:00
// 处理密码配置
parsePasswords()
// 处理哈希值配置
parseHashes()
// 处理URL配置
parseURLs()
// 处理主机配置
if err := parseHosts(Info); err != nil {
return err
}
// 处理端口配置
if err := parsePorts(); err != nil {
return err
}
return nil
}
// parsePasswords 解析密码配置
// 处理直接指定的密码和从文件加载的密码
func parsePasswords() {
var pwdList []string
2025-04-14 02:36:16 +08:00
// 处理命令行参数指定的密码列表
2022-07-03 23:41:39 +08:00
if Password != "" {
passes := strings.Split(Password, ",")
for _, pass := range passes {
2020-12-29 17:17:10 +08:00
if pass != "" {
pwdList = append(pwdList, pass)
2020-12-29 17:17:10 +08:00
}
}
Passwords = pwdList
2025-02-07 13:10:06 +08:00
LogInfo(GetText("load_passwords", len(pwdList)))
2020-12-29 17:17:10 +08:00
}
// 从文件加载密码列表
2024-12-20 03:46:09 +08:00
if PasswordsFile != "" {
2025-04-14 02:36:16 +08:00
passes, err := ReadFileLines(PasswordsFile)
if err != nil {
2025-04-14 02:36:16 +08:00
LogError(fmt.Sprintf("读取密码文件失败: %v", err))
return
}
2025-04-14 02:36:16 +08:00
for _, pass := range passes {
if pass != "" {
pwdList = append(pwdList, pass)
2020-12-29 17:17:10 +08:00
}
}
Passwords = pwdList
2025-02-07 13:10:06 +08:00
LogInfo(GetText("load_passwords_from_file", len(passes)))
}
2025-04-14 02:36:16 +08:00
}
2025-04-14 02:36:16 +08:00
// parseHashes 解析哈希值配置
// 验证并处理哈希文件中的哈希值
func parseHashes() {
// 处理哈希文件
2025-04-14 02:36:16 +08:00
if HashFile == "" {
return
}
2025-04-14 02:36:16 +08:00
hashes, err := ReadFileLines(HashFile)
if err != nil {
LogError(fmt.Sprintf("读取哈希文件失败: %v", err))
return
}
validCount := 0
for _, line := range hashes {
if line == "" {
continue
}
// 验证哈希长度(MD5哈希为32位)
if len(line) == 32 {
HashValues = append(HashValues, line)
validCount++
} else {
LogError(GetText("invalid_hash", line))
2024-08-29 15:12:30 +08:00
}
}
2025-04-14 02:36:16 +08:00
LogInfo(GetText("load_valid_hashes", validCount))
}
2025-04-14 02:36:16 +08:00
// parseURLs 解析URL目标配置
// 处理命令行和文件指定的URL列表去重后更新全局URL列表
func parseURLs() {
urlMap := make(map[string]struct{})
// 处理命令行参数指定的URL列表
2025-01-04 14:04:41 +08:00
if TargetURL != "" {
urls := strings.Split(TargetURL, ",")
for _, url := range urls {
if url != "" {
2025-04-14 02:36:16 +08:00
urlMap[url] = struct{}{}
2025-01-04 14:04:41 +08:00
}
}
}
// 从文件加载URL列表
if URLsFile != "" {
2025-04-14 02:36:16 +08:00
urls, err := ReadFileLines(URLsFile)
2025-01-04 14:04:41 +08:00
if err != nil {
2025-04-14 02:36:16 +08:00
LogError(fmt.Sprintf("读取URL文件失败: %v", err))
return
2025-01-04 14:04:41 +08:00
}
for _, url := range urls {
if url != "" {
2025-04-14 02:36:16 +08:00
urlMap[url] = struct{}{}
2025-01-04 14:04:41 +08:00
}
}
}
2025-04-14 02:36:16 +08:00
// 更新全局URL列表(已去重)
URLs = make([]string, 0, len(urlMap))
for u := range urlMap {
URLs = append(URLs, u)
}
if len(URLs) > 0 {
LogInfo(GetText("load_urls", len(URLs)))
}
}
// parseHosts 解析主机配置
// 从文件加载主机列表并更新目标信息
func parseHosts(Info *HostInfo) error {
// 如果未指定主机文件,无需处理
if HostsFile == "" {
return nil
}
hosts, err := ReadFileLines(HostsFile)
if err != nil {
return fmt.Errorf("读取主机文件失败: %v", err)
}
// 去重处理
hostMap := make(map[string]struct{})
for _, host := range hosts {
if host != "" {
hostMap[host] = struct{}{}
}
2025-04-14 02:36:16 +08:00
}
2025-04-14 02:36:16 +08:00
// 构建主机列表并更新Info.Host
if len(hostMap) > 0 {
var hostList []string
for host := range hostMap {
hostList = append(hostList, host)
}
2025-04-14 02:36:16 +08:00
hostStr := strings.Join(hostList, ",")
if Info.Host == "" {
Info.Host = hostStr
} else {
Info.Host += "," + hostStr
}
2025-02-07 13:10:06 +08:00
LogInfo(GetText("load_hosts_from_file", len(hosts)))
}
2025-04-14 02:36:16 +08:00
return nil
}
2025-04-14 02:36:16 +08:00
// parsePorts 解析端口配置
// 从文件加载端口列表并更新全局端口配置
func parsePorts() error {
// 如果未指定端口文件,无需处理
if PortsFile == "" {
return nil
}
ports, err := ReadFileLines(PortsFile)
if err != nil {
return fmt.Errorf("读取端口文件失败: %v", err)
}
// 构建端口列表字符串
var portBuilder strings.Builder
for _, port := range ports {
if port != "" {
portBuilder.WriteString(port)
portBuilder.WriteString(",")
}
}
2025-04-14 02:36:16 +08:00
// 更新全局端口配置
Ports = portBuilder.String()
LogInfo(GetText("load_ports_from_file"))
return nil
2020-12-29 17:17:10 +08:00
}
2025-04-14 02:36:16 +08:00
// ReadFileLines 读取文件内容并返回非空行的切片
// 通用的文件读取函数,处理文件打开、读取和错误报告
func ReadFileLines(filename string) ([]string, error) {
// 打开文件
2020-12-29 17:17:10 +08:00
file, err := os.Open(filename)
if err != nil {
2025-02-07 13:10:06 +08:00
LogError(GetText("open_file_failed", filename, err))
return nil, err
2020-12-29 17:17:10 +08:00
}
defer file.Close()
2020-12-29 17:17:10 +08:00
var content []string
scanner := bufio.NewScanner(file)
scanner.Split(bufio.ScanLines)
2025-04-14 02:36:16 +08:00
// 逐行读取文件内容,忽略空行
lineCount := 0
2020-12-29 17:17:10 +08:00
for scanner.Scan() {
text := strings.TrimSpace(scanner.Text())
if text != "" {
content = append(content, text)
lineCount++
2020-12-29 17:17:10 +08:00
}
}
// 检查扫描过程中是否有错误
if err := scanner.Err(); err != nil {
2025-02-07 13:10:06 +08:00
LogError(GetText("read_file_failed", filename, err))
return nil, err
}
2025-02-07 13:10:06 +08:00
LogInfo(GetText("read_file_success", filename, lineCount))
2020-12-29 17:17:10 +08:00
return content, nil
}
// ParseInput 解析和验证输入参数配置
2025-04-14 02:36:16 +08:00
// 处理多种配置的冲突检查、格式验证和参数处理
2024-12-19 16:15:53 +08:00
func ParseInput(Info *HostInfo) error {
2025-04-14 02:36:16 +08:00
// 检查扫描模式冲突
if err := validateScanMode(Info); err != nil {
return err
}
// 处理端口配置组合
processPortsConfig()
// 处理额外用户名和密码
processExtraCredentials()
// 处理代理配置
if err := processProxySettings(); err != nil {
return err
}
// 处理哈希值
if err := processHashValues(); err != nil {
return err
}
return nil
}
// validateScanMode 验证扫描模式
// 检查互斥的扫描模式配置,避免参数冲突
func validateScanMode(Info *HostInfo) error {
// 检查互斥的扫描模式(主机扫描、URL扫描、本地模式)
modes := 0
if Info.Host != "" || HostsFile != "" {
modes++
}
2025-04-14 02:36:16 +08:00
if len(URLs) > 0 || TargetURL != "" || URLsFile != "" {
modes++
}
if LocalMode {
modes++
}
2025-04-14 02:36:16 +08:00
// 处理扫描模式验证结果
if modes == 0 {
// 无参数时显示帮助
flag.Usage()
2025-02-07 13:10:06 +08:00
return fmt.Errorf(GetText("specify_scan_params"))
} else if modes > 1 {
2025-02-07 13:10:06 +08:00
return fmt.Errorf(GetText("params_conflict"))
2024-12-21 18:26:44 +08:00
}
2025-04-14 02:36:16 +08:00
return nil
}
2022-11-30 10:49:02 +08:00
2025-04-14 02:36:16 +08:00
// processPortsConfig 处理端口配置
// 合并默认端口和附加端口配置
func processPortsConfig() {
// 如果使用主要端口添加Web端口
2024-12-20 03:46:09 +08:00
if Ports == MainPorts {
Ports += "," + WebPorts
2021-04-21 00:13:04 +08:00
}
2025-04-14 02:36:16 +08:00
// 处理附加端口
2024-12-20 03:46:09 +08:00
if AddPorts != "" {
2023-11-13 16:23:19 +08:00
if strings.HasSuffix(Ports, ",") {
2024-12-20 03:46:09 +08:00
Ports += AddPorts
} else {
2024-12-20 03:46:09 +08:00
Ports += "," + AddPorts
}
2025-02-07 13:10:06 +08:00
LogInfo(GetText("extra_ports", AddPorts))
}
2025-04-14 02:36:16 +08:00
}
2022-01-07 10:51:36 +08:00
2025-04-14 02:36:16 +08:00
// processExtraCredentials 处理额外的用户名和密码
// 添加命令行指定的额外用户名和密码到现有配置
func processExtraCredentials() {
// 处理额外用户名
2024-12-20 03:46:09 +08:00
if AddUsers != "" {
users := strings.Split(AddUsers, ",")
for dict := range Userdict {
Userdict[dict] = append(Userdict[dict], users...)
Userdict[dict] = RemoveDuplicate(Userdict[dict])
2022-01-07 10:51:36 +08:00
}
2025-02-07 13:10:06 +08:00
LogInfo(GetText("extra_usernames", AddUsers))
2022-01-07 10:51:36 +08:00
}
2025-04-14 02:36:16 +08:00
// 处理额外密码
2024-12-20 03:46:09 +08:00
if AddPasswords != "" {
passes := strings.Split(AddPasswords, ",")
Passwords = append(Passwords, passes...)
2022-01-07 10:51:36 +08:00
Passwords = RemoveDuplicate(Passwords)
2025-02-07 13:10:06 +08:00
LogInfo(GetText("extra_passwords", AddPasswords))
2022-01-07 10:51:36 +08:00
}
2025-04-14 02:36:16 +08:00
}
2025-04-14 02:36:16 +08:00
// processProxySettings 处理代理设置
// 解析并验证Socks5和HTTP代理配置
func processProxySettings() error {
// 处理Socks5代理
if Socks5Proxy != "" {
2025-04-14 02:36:16 +08:00
if err := setupSocks5Proxy(); err != nil {
return err
}
}
2025-04-14 02:36:16 +08:00
// 处理HTTP代理
2024-12-20 03:46:09 +08:00
if HttpProxy != "" {
2025-04-14 02:36:16 +08:00
if err := setupHttpProxy(); err != nil {
return err
}
2025-04-14 02:36:16 +08:00
}
return nil
}
2025-04-14 02:36:16 +08:00
// setupSocks5Proxy 设置Socks5代理
// 格式化和验证Socks5代理URL
func setupSocks5Proxy() error {
// 规范化Socks5代理URL格式
if !strings.HasPrefix(Socks5Proxy, "socks5://") {
if !strings.Contains(Socks5Proxy, ":") {
// 仅指定端口时使用本地地址
Socks5Proxy = "socks5://127.0.0.1:" + Socks5Proxy
} else {
// 指定IP:PORT时添加协议前缀
Socks5Proxy = "socks5://" + Socks5Proxy
}
2025-04-14 02:36:16 +08:00
}
2025-04-14 02:36:16 +08:00
// 验证代理URL格式
_, err := url.Parse(Socks5Proxy)
if err != nil {
return fmt.Errorf(GetText("socks5_proxy_error", err))
}
// 使用Socks5代理时禁用Ping(无法通过代理进行ICMP)
DisablePing = true
LogInfo(GetText("socks5_proxy", Socks5Proxy))
return nil
}
// setupHttpProxy 设置HTTP代理
// 处理多种HTTP代理简写形式并验证URL格式
func setupHttpProxy() error {
// 处理HTTP代理简写形式
switch HttpProxy {
case "1":
// 快捷方式1: 本地8080端口(常用代理工具默认端口)
HttpProxy = "http://127.0.0.1:8080"
case "2":
// 快捷方式2: 本地1080端口(常见SOCKS端口)
HttpProxy = "socks5://127.0.0.1:1080"
default:
// 仅指定端口时使用本地HTTP代理
if !strings.Contains(HttpProxy, "://") {
HttpProxy = "http://127.0.0.1:" + HttpProxy
}
}
2025-04-14 02:36:16 +08:00
// 验证代理协议
if !strings.HasPrefix(HttpProxy, "socks") && !strings.HasPrefix(HttpProxy, "http") {
return fmt.Errorf(GetText("unsupported_proxy"))
}
// 验证代理URL格式
_, err := url.Parse(HttpProxy)
if err != nil {
return fmt.Errorf(GetText("proxy_format_error", err))
}
LogInfo(GetText("http_proxy", HttpProxy))
return nil
}
// processHashValues 处理哈希值
// 验证单个哈希值并处理哈希列表
func processHashValues() error {
// 处理单个哈希值
2024-12-20 03:46:09 +08:00
if HashValue != "" {
2025-04-14 02:36:16 +08:00
// MD5哈希必须是32位十六进制字符
2024-12-20 03:46:09 +08:00
if len(HashValue) != 32 {
2025-02-07 13:10:06 +08:00
return fmt.Errorf(GetText("hash_length_error"))
}
2024-12-20 03:46:09 +08:00
HashValues = append(HashValues, HashValue)
2024-08-29 15:12:30 +08:00
}
2025-04-14 02:36:16 +08:00
// 处理哈希值列表
2024-12-20 03:46:09 +08:00
HashValues = RemoveDuplicate(HashValues)
for _, hash := range HashValues {
2025-04-14 02:36:16 +08:00
// 将十六进制字符串转换为字节数组
hashByte, err := hex.DecodeString(hash)
if err != nil {
2025-02-07 13:10:06 +08:00
LogError(GetText("hash_decode_failed", hash))
2024-08-29 15:12:30 +08:00
continue
}
HashBytes = append(HashBytes, hashByte)
}
2025-04-14 02:36:16 +08:00
// 清空原始哈希值列表,仅保留字节形式
2024-12-20 03:46:09 +08:00
HashValues = []string{}
return nil
2020-12-29 17:17:10 +08:00
}
2025-04-14 02:36:16 +08:00
// RemoveDuplicate 对字符串切片进行去重
func RemoveDuplicate(old []string) []string {
temp := make(map[string]struct{})
var result []string
for _, item := range old {
if _, exists := temp[item]; !exists {
temp[item] = struct{}{}
result = append(result, item)
}
}
return result
}