feat: i18n

This commit is contained in:
ZacharyZcR 2025-02-07 13:10:06 +08:00
parent eb8cda3b7f
commit 3dde342d65
10 changed files with 1297 additions and 220 deletions

View File

@ -936,6 +936,8 @@ var (
JsonFormat bool // JSON格式输出 JsonFormat bool // JSON格式输出
LogLevel string // 日志输出级别 LogLevel string // 日志输出级别
ShowProgress bool // 是否显示进度条 ShowProgress bool // 是否显示进度条
Language string // 语言
) )
var ( var (

View File

@ -58,115 +58,81 @@ func Flag(Info *HostInfo) {
Banner() Banner()
// 目标配置 // 目标配置
flag.StringVar(&Info.Host, "h", "", "指定目标主机,支持以下格式:\n"+ flag.StringVar(&Info.Host, "h", "", GetText("flag_host"))
" - 单个IP: 192.168.11.11\n"+ flag.StringVar(&ExcludeHosts, "eh", "", GetText("flag_exclude_hosts"))
" - IP范围: 192.168.11.11-255\n"+ flag.StringVar(&Ports, "p", MainPorts, GetText("flag_ports"))
" - 多个IP: 192.168.11.11,192.168.11.12")
flag.StringVar(&ExcludeHosts, "eh", "", "排除指定主机范围,支持CIDR格式,如: 192.168.1.1/24")
flag.StringVar(&Ports, "p", MainPorts, "指定扫描端口,支持以下格式:\n"+
"端口格式:\n"+
" - 单个端口: 22\n"+
" - 端口范围: 1-65535\n"+
" - 多个端口: 22,80,3306\n\n"+
"预定义端口组(别名):\n"+
" - main: 常用端口 (21,22,23,80,81,135,139,443,445,1433,1521,3306,5432,6379,7001,8000,8080,8089,9000,9200,11211,27017)\n"+
" - service: 服务端口 (21,22,23,135,139,445,1433,1521,2222,3306,3389,5432,6379,9000,11211,27017)\n"+
" - db: 数据库端口 (1433,1521,3306,5432,6379,11211,27017)\n"+
" - web: Web服务端口 (包含常见的 80-90,443,800-1080,2000-8000,8080-9000,9090-10000 等Web端口)\n"+
" - all: 全部端口 (1-65535)\n\n"+
"示例:\n"+
" -p main 扫描常用端口\n"+
" -p web 扫描Web端口\n"+
" -p 80,443 扫描指定端口\n"+
" -p 1-1000 扫描1-1000端口范围\n"+
"默认使用 main 端口组")
flag.StringVar(&AddPorts, "pa", "", "在默认端口基础上额外添加端口,如: -pa 3389")
flag.StringVar(&ExcludePorts, "pn", "", "排除指定端口,如: -pn 445")
// 认证配置 // 认证配置
flag.StringVar(&AddUsers, "usera", "", "在默认用户列表基础上添加自定义用户名") flag.StringVar(&AddUsers, "usera", "", GetText("flag_add_users"))
flag.StringVar(&AddPasswords, "pwda", "", "在默认密码列表基础上添加自定义密码") flag.StringVar(&AddPasswords, "pwda", "", GetText("flag_add_passwords"))
flag.StringVar(&Username, "user", "", "指定单个用户名") flag.StringVar(&Username, "user", "", GetText("flag_username"))
flag.StringVar(&Password, "pwd", "", "指定单个密码") flag.StringVar(&Password, "pwd", "", GetText("flag_password"))
flag.StringVar(&Domain, "domain", "", "指定域名(仅用于SMB协议)") flag.StringVar(&Domain, "domain", "", GetText("flag_domain"))
flag.StringVar(&SshKeyPath, "sshkey", "", "指定SSH私钥文件路径(默认为id_rsa)") flag.StringVar(&SshKeyPath, "sshkey", "", GetText("flag_ssh_key"))
// 扫描配置 // 扫描配置
flag.StringVar(&ScanMode, "m", "All", "指定扫描模式:\n"+ flag.StringVar(&ScanMode, "m", "All", GetText("flag_scan_mode"))
"预设扫描模式(大写开头):\n"+ flag.IntVar(&ThreadNum, "t", 60, GetText("flag_thread_num"))
" - All: 全量扫描,包含所有可用插件\n"+ flag.Int64Var(&Timeout, "time", 3, GetText("flag_timeout"))
" - Basic: 基础扫描,包含 web/ftp/ssh/smb/findnet\n"+ flag.IntVar(&LiveTop, "top", 10, GetText("flag_live_top"))
" - Database: 数据库扫描,包含 mysql/mssql/redis/mongodb/postgres/oracle/memcached\n"+ flag.BoolVar(&DisablePing, "np", false, GetText("flag_disable_ping"))
" - Web: Web服务扫描包含 web/fcgi\n"+ flag.BoolVar(&UsePing, "ping", false, GetText("flag_use_ping"))
" - Service: 常见服务扫描,包含 ftp/ssh/telnet/smb/rdp/vnc/netbios\n"+ flag.StringVar(&Command, "c", "", GetText("flag_command"))
" - Vul: 漏洞扫描,包含 ms17010/smbghost/smb2\n"+ flag.BoolVar(&SkipFingerprint, "skip", false, GetText("flag_skip_fingerprint"))
" - Port: 端口扫描模式\n"+
" - ICMP: ICMP存活探测\n"+
" - Local: 本地信息收集\n\n"+
"单个插件模式(小写):\n"+
" Web类: web, fcgi\n"+
" 数据库类: mysql, mssql, redis, mongodb, postgres, oracle, memcached\n"+
" 服务类: ftp, ssh, telnet, smb, rdp, vnc, netbios\n"+
" 漏洞类: ms17010, smbghost, smb2\n"+
" 其他: findnet, wmiexec, localinfo")
//flag.BoolVar(&UseSynScan, "sS", false, "使用SYN扫描替代TCP全连接扫描(需要root/管理员权限)")
flag.IntVar(&ThreadNum, "t", 60, "设置扫描线程数")
flag.Int64Var(&Timeout, "time", 3, "设置连接超时时间(单位:秒)")
flag.IntVar(&LiveTop, "top", 10, "仅显示指定数量的存活主机")
flag.BoolVar(&DisablePing, "np", false, "禁用主机存活探测")
flag.BoolVar(&UsePing, "ping", false, "使用系统ping命令替代ICMP探测")
flag.StringVar(&Command, "c", "", "指定要执行的系统命令(支持ssh和wmiexec)")
flag.BoolVar(&SkipFingerprint, "skip", false, "跳过端口指纹识别")
// 文件配置 // 文件配置
flag.StringVar(&HostsFile, "hf", "", "从文件中读取目标主机列表") flag.StringVar(&HostsFile, "hf", "", GetText("flag_hosts_file"))
flag.StringVar(&UsersFile, "userf", "", "从文件中读取用户名字典") flag.StringVar(&UsersFile, "userf", "", GetText("flag_users_file"))
flag.StringVar(&PasswordsFile, "pwdf", "", "从文件中读取密码字典") flag.StringVar(&PasswordsFile, "pwdf", "", GetText("flag_passwords_file"))
flag.StringVar(&HashFile, "hashf", "", "从文件中读取Hash字典") flag.StringVar(&HashFile, "hashf", "", GetText("flag_hash_file"))
flag.StringVar(&PortsFile, "portf", "", "从文件中读取端口列表") flag.StringVar(&PortsFile, "portf", "", GetText("flag_ports_file"))
// Web配置 // Web配置
flag.StringVar(&TargetURL, "u", "", "指定目标URL") flag.StringVar(&TargetURL, "u", "", GetText("flag_target_url"))
flag.StringVar(&URLsFile, "uf", "", "从文件中读取URL列表") flag.StringVar(&URLsFile, "uf", "", GetText("flag_urls_file"))
flag.StringVar(&Cookie, "cookie", "", "设置HTTP请求Cookie") flag.StringVar(&Cookie, "cookie", "", GetText("flag_cookie"))
flag.Int64Var(&WebTimeout, "wt", 5, "设置Web请求超时时间(单位:秒)") flag.Int64Var(&WebTimeout, "wt", 5, GetText("flag_web_timeout"))
flag.StringVar(&HttpProxy, "proxy", "", "设置HTTP代理服务器") flag.StringVar(&HttpProxy, "proxy", "", GetText("flag_http_proxy"))
flag.StringVar(&Socks5Proxy, "socks5", "", "设置Socks5代理(用于TCP连接,将影响超时设置)") flag.StringVar(&Socks5Proxy, "socks5", "", GetText("flag_socks5_proxy"))
// 本地扫描配置 // 本地扫描配置
flag.BoolVar(&LocalMode, "local", false, "启用本地信息收集模式") flag.BoolVar(&LocalMode, "local", false, GetText("flag_local_mode"))
// POC配置 // POC配置
flag.StringVar(&PocPath, "pocpath", "", "指定自定义POC文件路径") flag.StringVar(&PocPath, "pocpath", "", GetText("flag_poc_path"))
flag.StringVar(&Pocinfo.PocName, "pocname", "", "指定要使用的POC名称,如: -pocname weblogic") flag.StringVar(&Pocinfo.PocName, "pocname", "", GetText("flag_poc_name"))
flag.BoolVar(&PocFull, "full", false, "启用完整POC扫描(如测试shiro全部100个key)") flag.BoolVar(&PocFull, "full", false, GetText("flag_poc_full"))
flag.BoolVar(&DnsLog, "dns", false, "启用dnslog进行漏洞验证") flag.BoolVar(&DnsLog, "dns", false, GetText("flag_dns_log"))
flag.IntVar(&PocNum, "num", 20, "设置POC扫描并发数") flag.IntVar(&PocNum, "num", 20, GetText("flag_poc_num"))
// Redis利用配置 // Redis利用配置
flag.StringVar(&RedisFile, "rf", "", "指定Redis写入的SSH公钥文件") flag.StringVar(&RedisFile, "rf", "", GetText("flag_redis_file"))
flag.StringVar(&RedisShell, "rs", "", "指定Redis写入的计划任务内容") flag.StringVar(&RedisShell, "rs", "", GetText("flag_redis_shell"))
flag.BoolVar(&DisableRedis, "noredis", false, "禁用Redis安全检测") flag.BoolVar(&DisableRedis, "noredis", false, GetText("flag_disable_redis"))
// 暴力破解配置 // 暴力破解配置
flag.BoolVar(&DisableBrute, "nobr", false, "禁用密码暴力破解") flag.BoolVar(&DisableBrute, "nobr", false, GetText("flag_disable_brute"))
flag.IntVar(&MaxRetries, "retry", 3, "设置最大重试次数") flag.IntVar(&MaxRetries, "retry", 3, GetText("flag_max_retries"))
// 其他配置 // 其他配置
flag.StringVar(&RemotePath, "path", "", "指定FCG/SMB远程文件路径") flag.StringVar(&RemotePath, "path", "", GetText("flag_remote_path"))
flag.StringVar(&HashValue, "hash", "", "指定要破解的Hash值") flag.StringVar(&HashValue, "hash", "", GetText("flag_hash_value"))
flag.StringVar(&Shellcode, "sc", "", "指定MS17漏洞利用的shellcode") flag.StringVar(&Shellcode, "sc", "", GetText("flag_shellcode"))
flag.BoolVar(&EnableWmi, "wmi", false, "启用WMI协议扫描") flag.BoolVar(&EnableWmi, "wmi", false, GetText("flag_enable_wmi"))
// 输出配置 // 输出配置
flag.StringVar(&Outputfile, "o", "result.txt", "指定结果输出文件名") flag.StringVar(&Outputfile, "o", "result.txt", GetText("flag_output_file"))
flag.StringVar(&OutputFormat, "f", "txt", "指定输出格式 (txt/json/csv)") flag.StringVar(&OutputFormat, "f", "txt", GetText("flag_output_format"))
flag.BoolVar(&DisableSave, "no", false, "禁止保存扫描结果") flag.BoolVar(&DisableSave, "no", false, GetText("flag_disable_save"))
flag.BoolVar(&Silent, "silent", false, "启用静默扫描模式(减少屏幕输出)") flag.BoolVar(&Silent, "silent", false, GetText("flag_silent_mode"))
flag.BoolVar(&NoColor, "nocolor", false, "禁用彩色输出显示") flag.BoolVar(&NoColor, "nocolor", false, GetText("flag_no_color"))
flag.BoolVar(&JsonFormat, "json", false, "以JSON格式输出结果") flag.BoolVar(&JsonFormat, "json", false, GetText("flag_json_format"))
flag.StringVar(&LogLevel, "log", LogLevelSuccess, "日志输出级别(ALL/SUCCESS/ERROR/INFO/DEBUG)") flag.StringVar(&LogLevel, "log", LogLevelSuccess, GetText("flag_log_level"))
flag.BoolVar(&ShowProgress, "pg", false, "开启进度条显示") flag.BoolVar(&ShowProgress, "pg", false, GetText("flag_show_progress"))
flag.StringVar(&Language, "lang", "en", GetText("flag_language"))
flag.Parse() flag.Parse()
SetLanguage()
} }

View File

@ -1,5 +1,3 @@
// output.go
package Common package Common
import ( import (
@ -48,25 +46,25 @@ type ScanResult struct {
// InitOutput 初始化输出系统 // InitOutput 初始化输出系统
func InitOutput() error { func InitOutput() error {
LogDebug("开始初始化输出系统") LogDebug(GetText("output_init_start"))
// 验证输出格式 // 验证输出格式
switch OutputFormat { switch OutputFormat {
case "txt", "json", "csv": case "txt", "json", "csv":
// 有效的格式 // 有效的格式
default: default:
return fmt.Errorf("不支持的输出格式: %s", OutputFormat) return fmt.Errorf(GetText("output_format_invalid"), OutputFormat)
} }
// 验证输出路径 // 验证输出路径
if Outputfile == "" { if Outputfile == "" {
return fmt.Errorf("输出文件路径不能为空") return fmt.Errorf(GetText("output_path_empty"))
} }
dir := filepath.Dir(Outputfile) dir := filepath.Dir(Outputfile)
if err := os.MkdirAll(dir, 0755); err != nil { if err := os.MkdirAll(dir, 0755); err != nil {
LogDebug(fmt.Sprintf("创建输出目录失败: %v", err)) LogDebug(GetText("output_create_dir_failed", err))
return fmt.Errorf("创建输出目录失败: %v", err) return fmt.Errorf(GetText("output_create_dir_failed", err))
} }
manager := &OutputManager{ manager := &OutputManager{
@ -75,12 +73,12 @@ func InitOutput() error {
} }
if err := manager.initialize(); err != nil { if err := manager.initialize(); err != nil {
LogDebug(fmt.Sprintf("初始化输出管理器失败: %v", err)) LogDebug(GetText("output_init_failed", err))
return fmt.Errorf("初始化输出管理器失败: %v", err) return fmt.Errorf(GetText("output_init_failed", err))
} }
ResultOutput = manager ResultOutput = manager
LogDebug("输出系统初始化完成") LogDebug(GetText("output_init_success"))
return nil return nil
} }
@ -89,52 +87,52 @@ func (om *OutputManager) initialize() error {
defer om.mu.Unlock() defer om.mu.Unlock()
if om.isInitialized { if om.isInitialized {
LogDebug("输出管理器已经初始化,跳过") LogDebug(GetText("output_already_init"))
return nil return nil
} }
LogDebug(fmt.Sprintf("正在打开输出文件: %s", om.outputPath)) LogDebug(GetText("output_opening_file", om.outputPath))
file, err := os.OpenFile(om.outputPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644) file, err := os.OpenFile(om.outputPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
if err != nil { if err != nil {
LogDebug(fmt.Sprintf("打开输出文件失败: %v", err)) LogDebug(GetText("output_open_file_failed", err))
return fmt.Errorf("打开输出文件失败: %v", err) return fmt.Errorf(GetText("output_open_file_failed", err))
} }
om.file = file om.file = file
switch om.outputFormat { switch om.outputFormat {
case "csv": case "csv":
LogDebug("初始化CSV写入器") LogDebug(GetText("output_init_csv"))
om.csvWriter = csv.NewWriter(file) om.csvWriter = csv.NewWriter(file)
headers := []string{"Time", "Type", "Target", "Status", "Details"} headers := []string{"Time", "Type", "Target", "Status", "Details"}
if err := om.csvWriter.Write(headers); err != nil { if err := om.csvWriter.Write(headers); err != nil {
LogDebug(fmt.Sprintf("写入CSV头失败: %v", err)) LogDebug(GetText("output_write_csv_header_failed", err))
file.Close() file.Close()
return fmt.Errorf("写入CSV头失败: %v", err) return fmt.Errorf(GetText("output_write_csv_header_failed", err))
} }
om.csvWriter.Flush() om.csvWriter.Flush()
case "json": case "json":
LogDebug("初始化JSON编码器") LogDebug(GetText("output_init_json"))
om.jsonEncoder = json.NewEncoder(file) om.jsonEncoder = json.NewEncoder(file)
om.jsonEncoder.SetIndent("", " ") om.jsonEncoder.SetIndent("", " ")
case "txt": case "txt":
LogDebug("初始化文本输出") LogDebug(GetText("output_init_txt"))
default: default:
LogDebug(fmt.Sprintf("不支持的输出格式: %s", om.outputFormat)) LogDebug(GetText("output_format_invalid", om.outputFormat))
} }
om.isInitialized = true om.isInitialized = true
LogDebug("输出管理器初始化完成") LogDebug(GetText("output_init_complete"))
return nil return nil
} }
// SaveResult 保存扫描结果 // SaveResult 保存扫描结果
func SaveResult(result *ScanResult) error { func SaveResult(result *ScanResult) error {
if ResultOutput == nil { if ResultOutput == nil {
LogDebug("输出系统未初始化") LogDebug(GetText("output_not_init"))
return fmt.Errorf("输出系统未初始化") return fmt.Errorf(GetText("output_not_init"))
} }
LogDebug(fmt.Sprintf("正在保存结果 - 类型: %s, 目标: %s", result.Type, result.Target)) LogDebug(GetText("output_saving_result", result.Type, result.Target))
return ResultOutput.saveResult(result) return ResultOutput.saveResult(result)
} }
@ -143,8 +141,8 @@ func (om *OutputManager) saveResult(result *ScanResult) error {
defer om.mu.Unlock() defer om.mu.Unlock()
if !om.isInitialized { if !om.isInitialized {
LogDebug("输出管理器未初始化") LogDebug(GetText("output_not_init"))
return fmt.Errorf("输出管理器未初始化") return fmt.Errorf(GetText("output_not_init"))
} }
var err error var err error
@ -156,14 +154,14 @@ func (om *OutputManager) saveResult(result *ScanResult) error {
case "csv": case "csv":
err = om.writeCsv(result) err = om.writeCsv(result)
default: default:
LogDebug(fmt.Sprintf("不支持的输出格式: %s", om.outputFormat)) LogDebug(GetText("output_format_invalid", om.outputFormat))
return fmt.Errorf("不支持的输出格式: %s", om.outputFormat) return fmt.Errorf(GetText("output_format_invalid", om.outputFormat))
} }
if err != nil { if err != nil {
LogDebug(fmt.Sprintf("保存结果失败: %v", err)) LogDebug(GetText("output_save_failed", err))
} else { } else {
LogDebug(fmt.Sprintf("成功保存结果 - 类型: %s, 目标: %s", result.Type, result.Target)) LogDebug(GetText("output_save_success", result.Type, result.Target))
} }
return err return err
} }
@ -179,13 +177,13 @@ func (om *OutputManager) writeTxt(result *ScanResult) error {
details = strings.Join(pairs, ", ") details = strings.Join(pairs, ", ")
} }
txt := fmt.Sprintf("[%s] [%s] Target: %s, Status: %s, Details: {%s}\n", txt := GetText("output_txt_format",
result.Time.Format("2006-01-02 15:04:05"), result.Time.Format("2006-01-02 15:04:05"),
result.Type, result.Type,
result.Target, result.Target,
result.Status, result.Status,
details, details,
) ) + "\n"
_, err := om.file.WriteString(txt) _, err := om.file.WriteString(txt)
return err return err
} }
@ -218,30 +216,30 @@ func (om *OutputManager) writeCsv(result *ScanResult) error {
// CloseOutput 关闭输出系统 // CloseOutput 关闭输出系统
func CloseOutput() error { func CloseOutput() error {
if ResultOutput == nil { if ResultOutput == nil {
LogDebug("输出系统未初始化,无需关闭") LogDebug(GetText("output_no_need_close"))
return nil return nil
} }
LogDebug("正在关闭输出系统") LogDebug(GetText("output_closing"))
ResultOutput.mu.Lock() ResultOutput.mu.Lock()
defer ResultOutput.mu.Unlock() defer ResultOutput.mu.Unlock()
if !ResultOutput.isInitialized { if !ResultOutput.isInitialized {
LogDebug("输出管理器未初始化,无需关闭") LogDebug(GetText("output_no_need_close"))
return nil return nil
} }
if ResultOutput.csvWriter != nil { if ResultOutput.csvWriter != nil {
LogDebug("刷新CSV写入器缓冲区") LogDebug(GetText("output_flush_csv"))
ResultOutput.csvWriter.Flush() ResultOutput.csvWriter.Flush()
} }
if err := ResultOutput.file.Close(); err != nil { if err := ResultOutput.file.Close(); err != nil {
LogDebug(fmt.Sprintf("关闭文件失败: %v", err)) LogDebug(GetText("output_close_failed", err))
return fmt.Errorf("关闭文件失败: %v", err) return fmt.Errorf(GetText("output_close_failed", err))
} }
ResultOutput.isInitialized = false ResultOutput.isInitialized = false
LogDebug("输出系统已关闭") LogDebug(GetText("output_closed"))
return nil return nil
} }

View File

@ -31,7 +31,7 @@ func ParseUser() error {
// 处理直接指定的用户名列表 // 处理直接指定的用户名列表
if Username != "" { if Username != "" {
usernames = strings.Split(Username, ",") usernames = strings.Split(Username, ",")
LogInfo(fmt.Sprintf("加载用户名: %d 个", len(usernames))) LogInfo(GetText("no_username_specified", len(usernames)))
} }
// 从文件加载用户名列表 // 从文件加载用户名列表
@ -47,12 +47,12 @@ func ParseUser() error {
usernames = append(usernames, user) usernames = append(usernames, user)
} }
} }
LogInfo(fmt.Sprintf("从文件加载用户名: %d 个", len(users))) LogInfo(GetText("load_usernames_from_file", len(users)))
} }
// 去重处理 // 去重处理
usernames = RemoveDuplicate(usernames) usernames = RemoveDuplicate(usernames)
LogInfo(fmt.Sprintf("用户名总数: %d 个", len(usernames))) LogInfo(GetText("total_usernames", len(usernames)))
// 更新用户字典 // 更新用户字典
for name := range Userdict { for name := range Userdict {
@ -74,7 +74,7 @@ func ParsePass(Info *HostInfo) error {
} }
} }
Passwords = pwdList Passwords = pwdList
LogInfo(fmt.Sprintf("加载密码: %d 个", len(pwdList))) LogInfo(GetText("load_passwords", len(pwdList)))
} }
// 从文件加载密码列表 // 从文件加载密码列表
@ -89,7 +89,7 @@ func ParsePass(Info *HostInfo) error {
} }
} }
Passwords = pwdList Passwords = pwdList
LogInfo(fmt.Sprintf("从文件加载密码: %d 个", len(passes))) LogInfo(GetText("load_passwords_from_file", len(passes)))
} }
// 处理哈希文件 // 处理哈希文件
@ -108,10 +108,10 @@ func ParsePass(Info *HostInfo) error {
HashValues = append(HashValues, line) HashValues = append(HashValues, line)
validCount++ validCount++
} else { } else {
LogError(fmt.Sprintf("无效的哈希值: %s (长度!=32)", line)) LogError(GetText("invalid_hash", line))
} }
} }
LogInfo(fmt.Sprintf("加载有效哈希值: %d 个", validCount)) LogInfo(GetText("load_valid_hashes", validCount))
} }
// 处理直接指定的URL列表 // 处理直接指定的URL列表
@ -126,7 +126,7 @@ func ParsePass(Info *HostInfo) error {
} }
} }
} }
LogInfo(fmt.Sprintf("加载URL: %d 个", len(URLs))) LogInfo(GetText("load_urls", len(URLs)))
} }
// 从文件加载URL列表 // 从文件加载URL列表
@ -145,7 +145,7 @@ func ParsePass(Info *HostInfo) error {
} }
} }
} }
LogInfo(fmt.Sprintf("从文件加载URL: %d 个", len(urls))) LogInfo(GetText("load_urls_from_file", len(urls)))
} }
// 从文件加载主机列表 // 从文件加载主机列表
@ -168,7 +168,7 @@ func ParsePass(Info *HostInfo) error {
} }
} }
} }
LogInfo(fmt.Sprintf("从文件加载主机: %d 个", len(hosts))) LogInfo(GetText("load_hosts_from_file", len(hosts)))
} }
// 从文件加载端口列表 // 从文件加载端口列表
@ -186,7 +186,7 @@ func ParsePass(Info *HostInfo) error {
} }
} }
Ports = newport.String() Ports = newport.String()
LogInfo("从文件加载端口配置") LogInfo(GetText("load_ports_from_file"))
} }
return nil return nil
@ -197,7 +197,7 @@ func Readfile(filename string) ([]string, error) {
// 打开文件 // 打开文件
file, err := os.Open(filename) file, err := os.Open(filename)
if err != nil { if err != nil {
LogError(fmt.Sprintf("打开文件失败 %s: %v", filename, err)) LogError(GetText("open_file_failed", filename, err))
return nil, err return nil, err
} }
defer file.Close() defer file.Close()
@ -218,11 +218,11 @@ func Readfile(filename string) ([]string, error) {
// 检查扫描过程中是否有错误 // 检查扫描过程中是否有错误
if err := scanner.Err(); err != nil { if err := scanner.Err(); err != nil {
LogError(fmt.Sprintf("读取文件错误 %s: %v", filename, err)) LogError(GetText("read_file_failed", filename, err))
return nil, err return nil, err
} }
LogInfo(fmt.Sprintf("读取文件成功 %s: %d 行", filename, lineCount)) LogInfo(GetText("read_file_success", filename, lineCount))
return content, nil return content, nil
} }
@ -243,22 +243,17 @@ func ParseInput(Info *HostInfo) error {
if modes == 0 { if modes == 0 {
// 无参数时显示帮助 // 无参数时显示帮助
flag.Usage() flag.Usage()
return fmt.Errorf("请指定扫描参数") return fmt.Errorf(GetText("specify_scan_params"))
} else if modes > 1 { } else if modes > 1 {
return fmt.Errorf("参数 -h、-u、-local 不能同时使用") return fmt.Errorf(GetText("params_conflict"))
} }
// 处理爆破线程配置 // 处理爆破线程配置
if BruteThreads <= 0 { if BruteThreads <= 0 {
BruteThreads = 1 BruteThreads = 1
LogInfo(fmt.Sprintf("暴力破解线程数: %d", BruteThreads)) LogInfo(GetText("brute_threads", BruteThreads))
} }
//if DisableSave {
// IsSave = false
// LogInfo("已启用临时保存模式")
//}
// 处理端口配置 // 处理端口配置
if Ports == MainPorts { if Ports == MainPorts {
Ports += "," + WebPorts Ports += "," + WebPorts
@ -270,7 +265,7 @@ func ParseInput(Info *HostInfo) error {
} else { } else {
Ports += "," + AddPorts Ports += "," + AddPorts
} }
LogInfo(fmt.Sprintf("额外端口: %s", AddPorts)) LogInfo(GetText("extra_ports", AddPorts))
} }
// 处理用户名配置 // 处理用户名配置
@ -280,7 +275,7 @@ func ParseInput(Info *HostInfo) error {
Userdict[dict] = append(Userdict[dict], users...) Userdict[dict] = append(Userdict[dict], users...)
Userdict[dict] = RemoveDuplicate(Userdict[dict]) Userdict[dict] = RemoveDuplicate(Userdict[dict])
} }
LogInfo(fmt.Sprintf("额外用户名: %s", AddUsers)) LogInfo(GetText("extra_usernames", AddUsers))
} }
// 处理密码配置 // 处理密码配置
@ -288,7 +283,7 @@ func ParseInput(Info *HostInfo) error {
passes := strings.Split(AddPasswords, ",") passes := strings.Split(AddPasswords, ",")
Passwords = append(Passwords, passes...) Passwords = append(Passwords, passes...)
Passwords = RemoveDuplicate(Passwords) Passwords = RemoveDuplicate(Passwords)
LogInfo(fmt.Sprintf("额外密码: %s", AddPasswords)) LogInfo(GetText("extra_passwords", AddPasswords))
} }
// 处理Socks5代理配置 // 处理Socks5代理配置
@ -303,10 +298,10 @@ func ParseInput(Info *HostInfo) error {
_, err := url.Parse(Socks5Proxy) _, err := url.Parse(Socks5Proxy)
if err != nil { if err != nil {
return fmt.Errorf("Socks5代理格式错误: %v", err) return fmt.Errorf(GetText("socks5_proxy_error", err))
} }
DisablePing = true DisablePing = true
LogInfo(fmt.Sprintf("Socks5代理: %s", Socks5Proxy)) LogInfo(GetText("socks5_proxy", Socks5Proxy))
} }
// 处理HTTP代理配置 // 处理HTTP代理配置
@ -323,20 +318,20 @@ func ParseInput(Info *HostInfo) error {
} }
if !strings.HasPrefix(HttpProxy, "socks") && !strings.HasPrefix(HttpProxy, "http") { if !strings.HasPrefix(HttpProxy, "socks") && !strings.HasPrefix(HttpProxy, "http") {
return fmt.Errorf("不支持的代理类型") return fmt.Errorf(GetText("unsupported_proxy"))
} }
_, err := url.Parse(HttpProxy) _, err := url.Parse(HttpProxy)
if err != nil { if err != nil {
return fmt.Errorf("代理格式错误: %v", err) return fmt.Errorf(GetText("proxy_format_error", err))
} }
LogInfo(fmt.Sprintf("HTTP代理: %s", HttpProxy)) LogInfo(GetText("http_proxy", HttpProxy))
} }
// 处理Hash配置 // 处理Hash配置
if HashValue != "" { if HashValue != "" {
if len(HashValue) != 32 { if len(HashValue) != 32 {
return fmt.Errorf("Hash长度必须为32位") return fmt.Errorf(GetText("hash_length_error"))
} }
HashValues = append(HashValues, HashValue) HashValues = append(HashValues, HashValue)
} }
@ -346,7 +341,7 @@ func ParseInput(Info *HostInfo) error {
for _, hash := range HashValues { for _, hash := range HashValues {
hashByte, err := hex.DecodeString(hash) hashByte, err := hex.DecodeString(hash)
if err != nil { if err != nil {
LogError(fmt.Sprintf("Hash解码失败: %s", hash)) LogError(GetText("hash_decode_failed", hash))
continue continue
} }
HashBytes = append(HashBytes, hashByte) HashBytes = append(HashBytes, hashByte)

View File

@ -13,15 +13,8 @@ import (
"strings" "strings"
) )
var ParseIPErr = errors.New("主机解析错误\n" + var ParseIPErr = errors.New(GetText("parse_ip_error"))
"支持的格式: \n" +
"192.168.1.1 (单个IP)\n" +
"192.168.1.1/8 (8位子网)\n" +
"192.168.1.1/16 (16位子网)\n" +
"192.168.1.1/24 (24位子网)\n" +
"192.168.1.1,192.168.1.2 (IP列表)\n" +
"192.168.1.1-192.168.255.255 (IP范围)\n" +
"192.168.1.1-255 (最后一位简写范围)")
// ParseIP 解析IP地址配置 // ParseIP 解析IP地址配置
func ParseIP(host string, filename string, nohosts ...string) (hosts []string, err error) { func ParseIP(host string, filename string, nohosts ...string) (hosts []string, err error) {
@ -32,7 +25,7 @@ func ParseIP(host string, filename string, nohosts ...string) (hosts []string, e
host = hostport[0] host = hostport[0]
hosts = ParseIPs(host) hosts = ParseIPs(host)
Ports = hostport[1] Ports = hostport[1]
LogInfo(fmt.Sprintf("已解析主机端口组合,端口设置为: %s", Ports)) LogInfo(GetText("host_port_parsed", Ports))
} }
} else { } else {
// 解析主机地址 // 解析主机地址
@ -42,10 +35,10 @@ func ParseIP(host string, filename string, nohosts ...string) (hosts []string, e
if filename != "" { if filename != "" {
fileHosts, err := Readipfile(filename) fileHosts, err := Readipfile(filename)
if err != nil { if err != nil {
LogError(fmt.Sprintf("读取主机文件失败: %v", err)) LogError(GetText("read_host_file_failed", err))
} else { } else {
hosts = append(hosts, fileHosts...) hosts = append(hosts, fileHosts...)
LogInfo(fmt.Sprintf("从文件加载额外主机: %d 个", len(fileHosts))) LogInfo(GetText("extra_hosts_loaded", len(fileHosts)))
} }
} }
} }
@ -72,13 +65,13 @@ func ParseIP(host string, filename string, nohosts ...string) (hosts []string, e
} }
hosts = newHosts hosts = newHosts
sort.Strings(hosts) sort.Strings(hosts)
LogInfo(fmt.Sprintf("已排除指定主机: %d 个", len(excludeHosts))) LogInfo(GetText("hosts_excluded", len(excludeHosts)))
} }
} }
// 去重处理 // 去重处理
hosts = RemoveDuplicate(hosts) hosts = RemoveDuplicate(hosts)
LogInfo(fmt.Sprintf("最终有效主机数量: %d", len(hosts))) LogInfo(GetText("final_valid_hosts", len(hosts)))
// 检查解析结果 // 检查解析结果
if len(hosts) == 0 && len(HostPort) == 0 && (host != "" || filename != "") { if len(hosts) == 0 && len(HostPort) == 0 && (host != "" || filename != "") {
@ -123,7 +116,7 @@ func parseIP(ip string) []string {
default: default:
testIP := net.ParseIP(ip) testIP := net.ParseIP(ip)
if testIP == nil { if testIP == nil {
LogError(fmt.Sprintf("无效的IP格式: %s", ip)) LogError(GetText("invalid_ip_format", ip))
return nil return nil
} }
return []string{ip} return []string{ip}
@ -134,13 +127,13 @@ func parseIP(ip string) []string {
func parseIP2(host string) []string { func parseIP2(host string) []string {
_, ipNet, err := net.ParseCIDR(host) _, ipNet, err := net.ParseCIDR(host)
if err != nil { if err != nil {
LogError(fmt.Sprintf("CIDR格式解析失败: %s, %v", host, err)) LogError(GetText("cidr_parse_failed", host, err))
return nil return nil
} }
ipRange := IPRange(ipNet) ipRange := IPRange(ipNet)
hosts := parseIP1(ipRange) hosts := parseIP1(ipRange)
LogInfo(fmt.Sprintf("解析CIDR %s -> IP范围 %s", host, ipRange)) LogInfo(GetText("parse_cidr_to_range", host, ipRange))
return hosts return hosts
} }
@ -154,7 +147,7 @@ func parseIP1(ip string) []string {
if len(ipRange[1]) < 4 { if len(ipRange[1]) < 4 {
endNum, err := strconv.Atoi(ipRange[1]) endNum, err := strconv.Atoi(ipRange[1])
if testIP == nil || endNum > 255 || err != nil { if testIP == nil || endNum > 255 || err != nil {
LogError(fmt.Sprintf("IP范围格式错误: %s", ip)) LogError(GetText("ip_range_format_error", ip))
return nil return nil
} }
@ -164,7 +157,7 @@ func parseIP1(ip string) []string {
prefixIP := strings.Join(splitIP[0:3], ".") prefixIP := strings.Join(splitIP[0:3], ".")
if startNum > endNum || err1 != nil || err2 != nil { if startNum > endNum || err1 != nil || err2 != nil {
LogError(fmt.Sprintf("IP范围无效: %d-%d", startNum, endNum)) LogError(GetText("invalid_ip_range", startNum, endNum))
return nil return nil
} }
@ -172,14 +165,14 @@ func parseIP1(ip string) []string {
allIP = append(allIP, prefixIP+"."+strconv.Itoa(i)) allIP = append(allIP, prefixIP+"."+strconv.Itoa(i))
} }
LogInfo(fmt.Sprintf("生成IP范围: %s.%d - %s.%d", prefixIP, startNum, prefixIP, endNum)) LogInfo(GetText("generate_ip_range", prefixIP, startNum, prefixIP, endNum))
} else { } else {
// 处理完整IP范围格式 // 处理完整IP范围格式
splitIP1 := strings.Split(ipRange[0], ".") splitIP1 := strings.Split(ipRange[0], ".")
splitIP2 := strings.Split(ipRange[1], ".") splitIP2 := strings.Split(ipRange[1], ".")
if len(splitIP1) != 4 || len(splitIP2) != 4 { if len(splitIP1) != 4 || len(splitIP2) != 4 {
LogError(fmt.Sprintf("IP格式错误: %s", ip)) LogError(GetText("ip_format_error", ip))
return nil return nil
} }
@ -188,7 +181,7 @@ func parseIP1(ip string) []string {
ip1, err1 := strconv.Atoi(splitIP1[i]) ip1, err1 := strconv.Atoi(splitIP1[i])
ip2, err2 := strconv.Atoi(splitIP2[i]) ip2, err2 := strconv.Atoi(splitIP2[i])
if ip1 > ip2 || err1 != nil || err2 != nil { if ip1 > ip2 || err1 != nil || err2 != nil {
LogError(fmt.Sprintf("IP范围无效: %s-%s", ipRange[0], ipRange[1])) LogError(GetText("invalid_ip_range", ipRange[0], ipRange[1]))
return nil return nil
} }
start[i], end[i] = ip1, ip2 start[i], end[i] = ip1, ip2
@ -205,7 +198,7 @@ func parseIP1(ip string) []string {
allIP = append(allIP, ip) allIP = append(allIP, ip)
} }
LogInfo(fmt.Sprintf("生成IP范围: %s - %s", ipRange[0], ipRange[1])) LogInfo(GetText("generate_ip_range", ipRange[0], ipRange[1]))
} }
return allIP return allIP
@ -225,7 +218,7 @@ func IPRange(c *net.IPNet) string {
end := bcst.String() end := bcst.String()
result := fmt.Sprintf("%s-%s", start, end) result := fmt.Sprintf("%s-%s", start, end)
LogInfo(fmt.Sprintf("CIDR范围: %s", result)) LogInfo(GetText("cidr_range", result))
return result return result
} }
@ -233,7 +226,7 @@ func IPRange(c *net.IPNet) string {
func Readipfile(filename string) ([]string, error) { func Readipfile(filename string) ([]string, error) {
file, err := os.Open(filename) file, err := os.Open(filename)
if err != nil { if err != nil {
LogError(fmt.Sprintf("打开文件失败 %s: %v", filename, err)) LogError(GetText("open_file_failed", filename, err))
return nil, err return nil, err
} }
defer file.Close() defer file.Close()
@ -253,7 +246,7 @@ func Readipfile(filename string) ([]string, error) {
port := strings.Split(text[1], " ")[0] port := strings.Split(text[1], " ")[0]
num, err := strconv.Atoi(port) num, err := strconv.Atoi(port)
if err != nil || num < 1 || num > 65535 { if err != nil || num < 1 || num > 65535 {
LogError(fmt.Sprintf("忽略无效端口: %s", line)) LogError(GetText("invalid_port", line))
continue continue
} }
@ -261,20 +254,20 @@ func Readipfile(filename string) ([]string, error) {
for _, host := range hosts { for _, host := range hosts {
HostPort = append(HostPort, fmt.Sprintf("%s:%s", host, port)) HostPort = append(HostPort, fmt.Sprintf("%s:%s", host, port))
} }
LogInfo(fmt.Sprintf("解析IP端口组合: %s", line)) LogInfo(GetText("parse_ip_port", line))
} else { } else {
hosts := ParseIPs(line) hosts := ParseIPs(line)
content = append(content, hosts...) content = append(content, hosts...)
LogInfo(fmt.Sprintf("解析IP地址: %s", line)) LogInfo(GetText("parse_ip_address", line))
} }
} }
if err := scanner.Err(); err != nil { if err := scanner.Err(); err != nil {
LogError(fmt.Sprintf("读取文件错误: %v", err)) LogError(GetText("read_file_error", err))
return content, err return content, err
} }
LogInfo(fmt.Sprintf("从文件解析完成: %d 个IP地址", len(content))) LogInfo(GetText("file_parse_complete", len(content)))
return content, nil return content, nil
} }
@ -300,7 +293,7 @@ func parseIP8(ip string) []string {
testIP := net.ParseIP(realIP) testIP := net.ParseIP(realIP)
if testIP == nil { if testIP == nil {
LogError(fmt.Sprintf("无效的IP格式: %s", realIP)) LogError(GetText("invalid_ip_format", realIP))
return nil return nil
} }
@ -308,7 +301,7 @@ func parseIP8(ip string) []string {
ipRange := strings.Split(ip, ".")[0] ipRange := strings.Split(ip, ".")[0]
var allIP []string var allIP []string
LogInfo(fmt.Sprintf("解析网段: %s.0.0.0/8", ipRange)) LogInfo(GetText("parse_subnet", ipRange))
// 遍历所有可能的第二、三段 // 遍历所有可能的第二、三段
for a := 0; a <= 255; a++ { for a := 0; a <= 255; a++ {
@ -329,7 +322,7 @@ func parseIP8(ip string) []string {
} }
} }
LogInfo(fmt.Sprintf("生成采样IP: %d 个", len(allIP))) LogInfo(GetText("sample_ip_generated", len(allIP)))
return allIP return allIP
} }

View File

@ -1,10 +1,9 @@
package Common package Common
import ( import (
"fmt"
"sort"
"strconv" "strconv"
"strings" "strings"
"sort"
) )
// ParsePort 解析端口配置字符串为端口号列表 // ParsePort 解析端口配置字符串为端口号列表
@ -42,7 +41,7 @@ func ParsePort(ports string) []int {
if strings.Contains(port, "-") { if strings.Contains(port, "-") {
ranges := strings.Split(port, "-") ranges := strings.Split(port, "-")
if len(ranges) < 2 { if len(ranges) < 2 {
LogError(fmt.Sprintf("端口范围格式错误: %s", port)) LogError(GetText("port_range_format_error", port))
continue continue
} }
@ -63,7 +62,7 @@ func ParsePort(ports string) []int {
end, _ := strconv.Atoi(upper) end, _ := strconv.Atoi(upper)
for i := start; i <= end; i++ { for i := start; i <= end; i++ {
if i > 65535 || i < 1 { if i > 65535 || i < 1 {
LogError(fmt.Sprintf("忽略无效端口: %d", i)) LogError(GetText("ignore_invalid_port", i))
continue continue
} }
scanPorts = append(scanPorts, i) scanPorts = append(scanPorts, i)
@ -74,7 +73,7 @@ func ParsePort(ports string) []int {
scanPorts = removeDuplicate(scanPorts) scanPorts = removeDuplicate(scanPorts)
sort.Ints(scanPorts) sort.Ints(scanPorts)
LogInfo(fmt.Sprintf("有效端口数量: %d", len(scanPorts))) LogInfo(GetText("valid_port_count", len(scanPorts)))
return scanPorts return scanPorts
} }

View File

@ -1,7 +1,5 @@
package Common package Common
import "fmt"
// 扫描模式常量 - 使用大写开头表示这是一个预设的扫描模式 // 扫描模式常量 - 使用大写开头表示这是一个预设的扫描模式
const ( const (
ModeAll = "All" // 全量扫描 ModeAll = "All" // 全量扫描
@ -48,7 +46,7 @@ var PluginGroups = map[string][]string{
// ParseScanMode 解析扫描模式 // ParseScanMode 解析扫描模式
func ParseScanMode(mode string) { func ParseScanMode(mode string) {
LogInfo(fmt.Sprintf("解析扫描模式: %s", mode)) LogInfo(GetText("parse_scan_mode", mode))
// 检查是否是预设模式 // 检查是否是预设模式
presetModes := []string{ presetModes := []string{
@ -60,9 +58,9 @@ func ParseScanMode(mode string) {
if mode == presetMode { if mode == presetMode {
ScanMode = mode ScanMode = mode
if plugins := GetPluginsForMode(mode); plugins != nil { if plugins := GetPluginsForMode(mode); plugins != nil {
LogInfo(fmt.Sprintf("使用预设模式: %s, 包含插件: %v", mode, plugins)) LogInfo(GetText("using_preset_mode_plugins", mode, plugins))
} else { } else {
LogInfo(fmt.Sprintf("使用预设模式: %s", mode)) LogInfo(GetText("using_preset_mode", mode))
} }
return return
} }
@ -71,14 +69,14 @@ func ParseScanMode(mode string) {
// 检查是否是有效的插件名 // 检查是否是有效的插件名
if _, exists := PluginManager[mode]; exists { if _, exists := PluginManager[mode]; exists {
ScanMode = mode ScanMode = mode
LogInfo(fmt.Sprintf("使用单个插件: %s", mode)) LogInfo(GetText("using_single_plugin", mode))
return return
} }
// 默认使用All模式 // 默认使用All模式
ScanMode = ModeAll ScanMode = ModeAll
LogInfo(fmt.Sprintf("未识别的模式,使用默认模式: %s", ModeAll)) LogInfo(GetText("using_default_mode", ModeAll))
LogInfo(fmt.Sprintf("包含插件: %v", PluginGroups[ModeAll])) LogInfo(GetText("included_plugins", PluginGroups[ModeAll]))
} }
// GetPluginsForMode 获取指定模式下的插件列表 // GetPluginsForMode 获取指定模式下的插件列表

View File

@ -22,7 +22,7 @@ func WrapperTCP(network, address string, forward *net.Dialer) (net.Conn, error)
if Socks5Proxy == "" { if Socks5Proxy == "" {
conn, err := forward.Dial(network, address) conn, err := forward.Dial(network, address)
if err != nil { if err != nil {
return nil, fmt.Errorf("建立TCP连接失败: %v", err) return nil, fmt.Errorf(GetText("tcp_conn_failed"), err)
} }
return conn, nil return conn, nil
} }
@ -30,12 +30,12 @@ func WrapperTCP(network, address string, forward *net.Dialer) (net.Conn, error)
// Socks5代理模式 // Socks5代理模式
dialer, err := Socks5Dialer(forward) dialer, err := Socks5Dialer(forward)
if err != nil { if err != nil {
return nil, fmt.Errorf("创建Socks5代理失败: %v", err) return nil, fmt.Errorf(GetText("socks5_create_failed"), err)
} }
conn, err := dialer.Dial(network, address) conn, err := dialer.Dial(network, address)
if err != nil { if err != nil {
return nil, fmt.Errorf("通过Socks5建立连接失败: %v", err) return nil, fmt.Errorf(GetText("socks5_conn_failed"), err)
} }
return conn, nil return conn, nil
@ -46,12 +46,12 @@ func Socks5Dialer(forward *net.Dialer) (proxy.Dialer, error) {
// 解析代理URL // 解析代理URL
u, err := url.Parse(Socks5Proxy) u, err := url.Parse(Socks5Proxy)
if err != nil { if err != nil {
return nil, fmt.Errorf("解析Socks5代理地址失败: %v", err) return nil, fmt.Errorf(GetText("socks5_parse_failed"), err)
} }
// 验证代理类型 // 验证代理类型
if strings.ToLower(u.Scheme) != "socks5" { if strings.ToLower(u.Scheme) != "socks5" {
return nil, errors.New("仅支持socks5代理") return nil, errors.New(GetText("socks5_only"))
} }
address := u.Host address := u.Host
@ -71,7 +71,7 @@ func Socks5Dialer(forward *net.Dialer) (proxy.Dialer, error) {
} }
if err != nil { if err != nil {
return nil, fmt.Errorf("创建Socks5代理失败: %v", err) return nil, fmt.Errorf(GetText("socks5_create_failed"), err)
} }
return dialer, nil return dialer, nil

1126
Common/i18n.go Normal file

File diff suppressed because it is too large Load Diff

View File

@ -80,7 +80,7 @@ func handleAliveHosts(chanHosts chan string, hostslist []string, isPing bool) {
// 保留原有的控制台输出 // 保留原有的控制台输出
if !Common.Silent { if !Common.Silent {
Common.LogSuccess(fmt.Sprintf("目标 %-15s 存活 (%s)", ip, protocol)) Common.LogSuccess(Common.GetText("target_alive", ip, protocol))
} }
} }
livewg.Done() livewg.Done()
@ -96,8 +96,8 @@ func probeWithICMP(hostslist []string, chanHosts chan string) {
return return
} }
Common.LogError(fmt.Sprintf("ICMP监听失败: %v", err)) Common.LogError(Common.GetText("icmp_listen_failed", err))
Common.LogInfo("正在尝试无监听ICMP探测...") Common.LogInfo(Common.GetText("trying_no_listen_icmp"))
// 尝试无监听ICMP探测 // 尝试无监听ICMP探测
conn2, err := net.DialTimeout("ip4:icmp", "127.0.0.1", 3*time.Second) conn2, err := net.DialTimeout("ip4:icmp", "127.0.0.1", 3*time.Second)
@ -107,9 +107,9 @@ func probeWithICMP(hostslist []string, chanHosts chan string) {
return return
} }
Common.LogError(fmt.Sprintf("ICMP连接失败: %v", err)) Common.LogError(Common.GetText("icmp_connect_failed", err))
Common.LogInfo("当前用户权限不足,无法发送ICMP包") Common.LogInfo(Common.GetText("insufficient_privileges"))
Common.LogInfo("切换为PING方式探测...") Common.LogInfo(Common.GetText("switching_to_ping"))
// 降级使用ping探测 // 降级使用ping探测
RunPing(hostslist, chanHosts) RunPing(hostslist, chanHosts)
@ -121,7 +121,7 @@ func printAliveStats(hostslist []string) {
if len(hostslist) > 1000 { if len(hostslist) > 1000 {
arrTop, arrLen := ArrayCountValueTop(AliveHosts, Common.LiveTop, true) arrTop, arrLen := ArrayCountValueTop(AliveHosts, Common.LiveTop, true)
for i := 0; i < len(arrTop); i++ { for i := 0; i < len(arrTop); i++ {
Common.LogSuccess(fmt.Sprintf("%s.0.0/16 存活主机数: %d", arrTop[i], arrLen[i])) Common.LogSuccess(Common.GetText("subnet_16_alive", arrTop[i], arrLen[i]))
} }
} }
@ -129,7 +129,7 @@ func printAliveStats(hostslist []string) {
if len(hostslist) > 256 { if len(hostslist) > 256 {
arrTop, arrLen := ArrayCountValueTop(AliveHosts, Common.LiveTop, false) arrTop, arrLen := ArrayCountValueTop(AliveHosts, Common.LiveTop, false)
for i := 0; i < len(arrTop); i++ { for i := 0; i < len(arrTop); i++ {
Common.LogSuccess(fmt.Sprintf("%s.0/24 存活主机数: %d", arrTop[i], arrLen[i])) Common.LogSuccess(Common.GetText("subnet_24_alive", arrTop[i], arrLen[i]))
} }
} }
} }