refactor: 合并 avdetect 到 systeminfo,修复杀软检测误报

- 将 avdetect 的进程匹配逻辑合并到 systeminfo 插件
- 修复进程匹配使用 Contains 导致大量误报,改为精确匹配
- 修正 auto.json 中 Microsoft Security Essentials 为 Microsoft Defender
- 使用 map 索引优化进程匹配性能
- 清理废弃的 envinfo/avdetect i18n key
This commit is contained in:
ZacharyZcR
2026-05-15 22:52:11 +08:00
parent ca4e1ffad3
commit 76a4331fae
7 changed files with 104 additions and 250 deletions
+97 -14
View File
@@ -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",