From 76a4331fae5bbce66ff909272946e90219bd134a Mon Sep 17 00:00:00 2001 From: ZacharyZcR Date: Fri, 15 May 2026 22:52:11 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E5=90=88=E5=B9=B6=20avdetect=20?= =?UTF-8?q?=E5=88=B0=20systeminfo=EF=BC=8C=E4=BF=AE=E5=A4=8D=E6=9D=80?= =?UTF-8?q?=E8=BD=AF=E6=A3=80=E6=B5=8B=E8=AF=AF=E6=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 avdetect 的进程匹配逻辑合并到 systeminfo 插件 - 修复进程匹配使用 Contains 导致大量误报,改为精确匹配 - 修正 auto.json 中 Microsoft Security Essentials 为 Microsoft Defender - 使用 map 索引优化进程匹配性能 - 清理废弃的 envinfo/avdetect i18n key --- common/flag.go | 2 +- common/i18n/locales/en.yaml | 15 +-- common/i18n/locales/zh.yaml | 16 +-- plugins/local/auto.json | 4 +- plugins/local/avdetect.go | 205 ------------------------------------ plugins/local/systeminfo.go | 111 ++++++++++++++++--- web/api/config.go | 1 - 7 files changed, 104 insertions(+), 250 deletions(-) delete mode 100644 plugins/local/avdetect.go diff --git a/common/flag.go b/common/flag.go index 9af9bf9..603f230 100644 --- a/common/flag.go +++ b/common/flag.go @@ -113,7 +113,7 @@ func Flag(Info *HostInfo) error { flag.Int64Var(&fv.GlobalTimeout, "gt", 180, i18n.GetText("flag_global_timeout")) flag.BoolVar(&fv.DisablePing, "np", false, i18n.GetText("flag_disable_ping")) flag.BoolVar(&fv.DisableTcpProbe, "ntp", false, i18n.GetText("flag_disable_tcp_probe")) - flag.StringVar(&fv.LocalPlugin, "local", "", "指定本地插件名称 (如: cleaner, avdetect, keylogger 等)") + flag.StringVar(&fv.LocalPlugin, "local", "", "指定本地插件名称 (如: cleaner, systeminfo, keylogger 等)") flag.BoolVar(&fv.AliveOnly, "ao", false, i18n.GetText("flag_alive_only")) // ═════════════════════════════════════════════════ diff --git a/common/i18n/locales/en.yaml b/common/i18n/locales/en.yaml index f985528..8cabbf0 100644 --- a/common/i18n/locales/en.yaml +++ b/common/i18n/locales/en.yaml @@ -564,9 +564,6 @@ keylogger_save_failed: keylogger_no_input: other: "No keyboard input captured" -# Environment info -envinfo_sensitive: - other: "Found sensitive environment variable: {{.Arg1}}" # Windows WMI winwmi_success: @@ -594,16 +591,6 @@ forwardshell_client_connected: forwardshell_read_failed: other: "Failed to read client command: {{.Arg1}}" -# AV detection -avdetect_load_failed: - other: "Failed to load AV database: {{.Arg1}}" -avdetect_loaded: - other: "Loaded {{.Arg1}} AV product info" -avdetect_found: - other: "Detected AV: {{.Arg1}} ({{.Arg2}} processes)" -avdetect_process: - other: " - {{.Arg1}}" - # Windows startup folder winstartup_success: other: "Windows startup folder persistence completed: {{.Arg1}} methods" @@ -709,6 +696,8 @@ systeminfo_patches: other: "Installed Patches: {{.Arg1}}" systeminfo_antivirus: other: "Antivirus Detected: {{.Arg1}}" +systeminfo_av_process: + other: " - {{.Arg1}}" systeminfo_sudo: other: "Sudo Privileges: {{.Arg1}}" systeminfo_macos_detail: diff --git a/common/i18n/locales/zh.yaml b/common/i18n/locales/zh.yaml index 5a923da..d524871 100644 --- a/common/i18n/locales/zh.yaml +++ b/common/i18n/locales/zh.yaml @@ -564,10 +564,6 @@ keylogger_save_failed: keylogger_no_input: other: "没有捕获到键盘输入" -# 环境变量信息 -envinfo_sensitive: - other: "发现敏感环境变量: {{.Arg1}}" - # Windows WMI winwmi_success: other: "Windows WMI事件订阅持久化完成: {{.Arg1}}个项目" @@ -594,16 +590,6 @@ forwardshell_client_connected: forwardshell_read_failed: other: "读取客户端命令失败: {{.Arg1}}" -# AV检测 -avdetect_load_failed: - other: "加载AV数据库失败: {{.Arg1}}" -avdetect_loaded: - other: "加载了 {{.Arg1}} 个AV产品信息" -avdetect_found: - other: "检测到AV: {{.Arg1}} ({{.Arg2}}个进程)" -avdetect_process: - other: " - {{.Arg1}}" - # Windows启动文件夹 winstartup_success: other: "Windows启动文件夹持久化完成: {{.Arg1}}个方法" @@ -709,6 +695,8 @@ systeminfo_patches: other: "已安装补丁: {{.Arg1}}个" systeminfo_antivirus: other: "检测到杀软: {{.Arg1}}" +systeminfo_av_process: + other: " - {{.Arg1}}" systeminfo_sudo: other: "sudo权限: {{.Arg1}}" systeminfo_macos_detail: diff --git a/plugins/local/auto.json b/plugins/local/auto.json index bcab7f8..4eb1ffc 100644 --- a/plugins/local/auto.json +++ b/plugins/local/auto.json @@ -406,7 +406,7 @@ ], "url": "https://www.mcafee.com/en-us" }, - "Microsoft Security Essentials": { + "Microsoft Defender(Windows Defender)": { "processes": [ "MsMpEng.exe", "msseces.exe", @@ -421,7 +421,7 @@ "MSASCuiL.exe", "SecurityHealthService.exe" ], - "url": "https://support.microsoft.com/en-us/help/17150/windows-7-what-is-microsoft-security-essentials" + "url": "https://www.microsoft.com/en-us/windows/comprehensive-security" }, "NANO-Antivirus": { "processes": [ diff --git a/plugins/local/avdetect.go b/plugins/local/avdetect.go deleted file mode 100644 index b1436db..0000000 --- a/plugins/local/avdetect.go +++ /dev/null @@ -1,205 +0,0 @@ -//go:build (plugin_avdetect || !plugin_selective) && !no_local - -package local - -import ( - "context" - _ "embed" - "encoding/json" - "fmt" - "os/exec" - "runtime" - "strings" - - "github.com/shadow1ng/fscan/common" - "github.com/shadow1ng/fscan/common/i18n" - "github.com/shadow1ng/fscan/plugins" -) - -//go:embed auto.json -var avDatabase []byte - -// AVProduct AV产品信息结构 -type AVProduct struct { - Processes []string `json:"processes"` - URL string `json:"url"` -} - -// AVDetectPlugin 杀软检测插件 -// 设计哲学:"做一件事并做好" - 专注AV检测 -// - 使用JSON数据库加载AV信息 -// - 删除复杂的结果结构体 -// - 跨平台支持,运行时适配 -type AVDetectPlugin struct { - plugins.BasePlugin - avProducts map[string]AVProduct -} - -// NewAVDetectPlugin 创建AV检测插件 -func NewAVDetectPlugin() *AVDetectPlugin { - plugin := &AVDetectPlugin{ - BasePlugin: plugins.NewBasePlugin("avdetect"), - avProducts: make(map[string]AVProduct), - } - - // 加载AV数据库 - if err := json.Unmarshal(avDatabase, &plugin.avProducts); err != nil { - common.LogError(i18n.Tr("avdetect_load_failed", err)) - } else { - common.LogInfo(i18n.Tr("avdetect_loaded", len(plugin.avProducts))) - } - - return plugin -} - -// Scan 执行AV/EDR检测 - 直接、有效 -func (p *AVDetectPlugin) Scan(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *plugins.Result { - var output strings.Builder - var detectedAVs []string - - output.WriteString("=== AV/EDR检测 ===\n") - - // 获取运行进程 - processes := p.getRunningProcesses() - if len(processes) == 0 { - return &plugins.Result{ - Success: false, - Output: "无法获取进程列表", - Error: fmt.Errorf("进程列表获取失败"), - } - } - - _, _ = fmt.Fprintf(&output, "扫描进程数: %d\n\n", len(processes)) - - // 检测AV产品 - 使用JSON数据库 - for avName, avProduct := range p.avProducts { - var foundProcesses []string - - for _, avProcess := range avProduct.Processes { - for _, runningProcess := range processes { - // 提取进程名部分进行匹配(去除PID信息) - processName := runningProcess - if strings.Contains(runningProcess, " (PID: ") { - processName = strings.Split(runningProcess, " (PID: ")[0] - } - - // 简单字符串匹配,忽略大小写 - if strings.Contains(strings.ToLower(processName), strings.ToLower(avProcess)) { - foundProcesses = append(foundProcesses, runningProcess) - } - } - } - - if len(foundProcesses) > 0 { - detectedAVs = append(detectedAVs, avName) - _, _ = fmt.Fprintf(&output, "✓ 检测到 %s:\n", avName) - - common.LogSuccess(i18n.Tr("avdetect_found", avName, len(foundProcesses))) - - // 输出详细进程信息到控制台 - for _, proc := range foundProcesses { - _, _ = fmt.Fprintf(&output, " - %s\n", proc) - common.LogInfo(i18n.Tr("avdetect_process", proc)) - } - output.WriteString("\n") - } - } - - // 统计结果 - output.WriteString("=== 检测结果 ===\n") - _, _ = fmt.Fprintf(&output, "检测到的AV产品: %d个\n", len(detectedAVs)) - - if len(detectedAVs) > 0 { - output.WriteString("检测到的产品: " + strings.Join(detectedAVs, ", ") + "\n") - } else { - output.WriteString("未检测到已知的AV/EDR产品\n") - } - - return &plugins.Result{ - Success: len(detectedAVs) > 0, - Output: output.String(), - Error: nil, - } -} - -// getRunningProcesses 获取运行进程列表 - 跨平台适配 -func (p *AVDetectPlugin) getRunningProcesses() []string { - var processes []string - - switch runtime.GOOS { - case "windows": - processes = p.getWindowsProcesses() - case "linux", "darwin": - processes = p.getUnixProcesses() - default: - // 不支持的平台,返回空列表 - return processes - } - - return processes -} - -// getWindowsProcesses 获取Windows进程 - 包含PID和进程名 -func (p *AVDetectPlugin) getWindowsProcesses() []string { - var processes []string - - // 使用tasklist命令 - cmd := exec.Command("tasklist", "/fo", "csv", "/nh") - output, err := cmd.Output() - if err != nil { - return processes - } - - lines := strings.Split(string(output), "\n") - for _, line := range lines { - line = strings.TrimSpace(line) - if line == "" { - continue - } - - // 解析CSV格式:进程名,PID,会话名,会话号,内存 - if strings.HasPrefix(line, "\"") { - parts := strings.Split(line, "\",\"") - if len(parts) >= 2 { - processName := strings.Trim(parts[0], "\"") - pid := strings.Trim(parts[1], "\"") - if processName != "" && pid != "" { - // 格式:进程名 (PID: xxxx) - processInfo := fmt.Sprintf("%s (PID: %s)", processName, pid) - processes = append(processes, processInfo) - } - } - } - } - - return processes -} - -// getUnixProcesses 获取Unix进程 - 简化实现 -func (p *AVDetectPlugin) getUnixProcesses() []string { - var processes []string - - // 使用ps命令 - cmd := exec.Command("ps", "-eo", "comm") - output, err := cmd.Output() - if err != nil { - return processes - } - - lines := strings.Split(string(output), "\n") - for _, line := range lines { - line = strings.TrimSpace(line) - if line != "" && line != "COMMAND" { - processes = append(processes, line) - } - } - - return processes -} - -// 注册插件 -func init() { - RegisterLocalPlugin("avdetect", func() Plugin { - return NewAVDetectPlugin() - }) -} diff --git a/plugins/local/systeminfo.go b/plugins/local/systeminfo.go index f86edfa..4baa856 100644 --- a/plugins/local/systeminfo.go +++ b/plugins/local/systeminfo.go @@ -4,6 +4,8 @@ package local import ( "context" + _ "embed" + "encoding/json" "fmt" "net" "os" @@ -17,6 +19,14 @@ import ( "github.com/shadow1ng/fscan/plugins" ) +//go:embed auto.json +var avDatabase []byte + +type avProduct struct { + Processes []string `json:"processes"` + URL string `json:"url"` +} + type SystemInfoPlugin struct { plugins.BasePlugin output strings.Builder @@ -47,6 +57,7 @@ func (p *SystemInfoPlugin) Scan(ctx context.Context, info *common.HostInfo, sess p.collectNetworkInfo() p.collectPrivilegeInfo() p.collectPlatformInfo() + p.collectAVInfo() p.collectSensitiveEnvVars() return &plugins.Result{ @@ -145,7 +156,6 @@ func (p *SystemInfoPlugin) collectWindowsInfo() { } } - // 防火墙状态 if out, err := p.runCommand("netsh", "advfirewall", "show", "allprofiles", "state"); err == nil { for _, line := range strings.Split(out, "\n") { line = strings.TrimSpace(line) @@ -155,7 +165,6 @@ func (p *SystemInfoPlugin) collectWindowsInfo() { } } - // 已安装补丁 if out, err := p.runCommand("wmic", "qfe", "get", "HotFixID,InstalledOn"); err == nil { lines := strings.Split(strings.TrimSpace(out), "\n") patches := 0 @@ -168,16 +177,6 @@ func (p *SystemInfoPlugin) collectWindowsInfo() { p.log("systeminfo_patches", patches) } } - - // 已安装的杀软 (WMI) - if out, err := p.runCommand("wmic", "/namespace:\\\\root\\SecurityCenter2", "path", "AntiVirusProduct", "get", "displayName"); err == nil { - for _, line := range strings.Split(out, "\n") { - line = strings.TrimSpace(line) - if line != "" && line != "displayName" { - p.logSuccess("systeminfo_antivirus", line) - } - } - } } func (p *SystemInfoPlugin) collectLinuxInfo() { @@ -194,7 +193,6 @@ func (p *SystemInfoPlugin) collectLinuxInfo() { } } - // 防火墙 if out, err := p.runCommand("iptables", "-L", "-n", "--line-numbers"); err == nil { ruleCount := 0 for _, line := range strings.Split(out, "\n") { @@ -205,7 +203,6 @@ func (p *SystemInfoPlugin) collectLinuxInfo() { p.log("systeminfo_firewall_rules", ruleCount) } - // sudo 权限 if out, err := p.runCommand("sudo", "-l", "-n"); err == nil { if strings.Contains(out, "ALL") { p.logSuccess("systeminfo_sudo", "ALL commands") @@ -229,6 +226,92 @@ func (p *SystemInfoPlugin) collectDarwinInfo() { } } +func (p *SystemInfoPlugin) collectAVInfo() { + var avProducts map[string]avProduct + if err := json.Unmarshal(avDatabase, &avProducts); err != nil { + return + } + + processes := p.getRunningProcesses() + if len(processes) == 0 { + return + } + + // 建立进程名索引,O(1) 查找 + processIndex := make(map[string][]string) + for _, proc := range processes { + name := proc + if idx := strings.Index(proc, " (PID: "); idx != -1 { + name = proc[:idx] + } + key := strings.ToLower(name) + processIndex[key] = append(processIndex[key], proc) + } + + for avName, av := range avProducts { + var matched []string + for _, avProc := range av.Processes { + if procs, ok := processIndex[strings.ToLower(avProc)]; ok { + matched = append(matched, procs...) + } + } + if len(matched) > 0 { + p.logSuccess("systeminfo_antivirus", fmt.Sprintf("%s (%d个进程)", avName, len(matched))) + for _, proc := range matched { + p.log("systeminfo_av_process", proc) + } + } + } +} + +func (p *SystemInfoPlugin) getRunningProcesses() []string { + switch runtime.GOOS { + case "windows": + return p.getWindowsProcesses() + case "linux", "darwin": + return p.getUnixProcesses() + } + return nil +} + +func (p *SystemInfoPlugin) getWindowsProcesses() []string { + out, err := p.runCommand("tasklist", "/fo", "csv", "/nh") + if err != nil { + return nil + } + var processes []string + for _, line := range strings.Split(string(out), "\n") { + line = strings.TrimSpace(line) + if !strings.HasPrefix(line, "\"") { + continue + } + parts := strings.Split(line, "\",\"") + if len(parts) >= 2 { + name := strings.Trim(parts[0], "\"") + pid := strings.Trim(parts[1], "\"") + if name != "" && pid != "" { + processes = append(processes, fmt.Sprintf("%s (PID: %s)", name, pid)) + } + } + } + return processes +} + +func (p *SystemInfoPlugin) getUnixProcesses() []string { + out, err := p.runCommand("ps", "-eo", "comm") + if err != nil { + return nil + } + var processes []string + for _, line := range strings.Split(string(out), "\n") { + line = strings.TrimSpace(line) + if line != "" && line != "COMMAND" { + processes = append(processes, line) + } + } + return processes +} + func (p *SystemInfoPlugin) collectSensitiveEnvVars() { keywords := []string{ "password", "passwd", "secret", "key", "token", diff --git a/web/api/config.go b/web/api/config.go index 0cba985..34b0ddf 100644 --- a/web/api/config.go +++ b/web/api/config.go @@ -114,7 +114,6 @@ var plugins = []PluginInfo{ {Name: "poc", Type: "web", Description: "POC漏洞检测", DescEn: "POC vulnerability detection", Enabled: true}, // 本地类 - {Name: "avdetect", Type: "local", Description: "杀软检测", DescEn: "Antivirus detection", Enabled: false}, {Name: "cleaner", Type: "local", Description: "痕迹清理", DescEn: "Trace cleaning", Enabled: false}, }