package local import ( _ "embed" "context" "encoding/json" "fmt" "os/exec" "runtime" "strings" "github.com/shadow1ng/fscan/common" "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/EDR检测插件 - Linus式简化版本 // // 设计哲学:"做一件事并做好" - 专注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(fmt.Sprintf("加载AV数据库失败: %v", err)) } else { common.LogInfo(fmt.Sprintf("加载了 %d 个AV产品信息", len(plugin.avProducts))) } return plugin } // Scan 执行AV/EDR检测 - 直接、有效 func (p *AVDetectPlugin) Scan(ctx context.Context, info *common.HostInfo) *ScanResult { var output strings.Builder var detectedAVs []string output.WriteString("=== AV/EDR检测 ===\n") // 获取运行进程 processes := p.getRunningProcesses() if len(processes) == 0 { return &ScanResult{ Success: false, Output: "无法获取进程列表", Error: fmt.Errorf("进程列表获取失败"), } } output.WriteString(fmt.Sprintf("扫描进程数: %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 { // 简单字符串匹配,忽略大小写 if strings.Contains(strings.ToLower(runningProcess), strings.ToLower(avProcess)) { foundProcesses = append(foundProcesses, runningProcess) } } } if len(foundProcesses) > 0 { detectedAVs = append(detectedAVs, avName) output.WriteString(fmt.Sprintf("✓ 检测到 %s:\n", avName)) for _, proc := range foundProcesses { output.WriteString(fmt.Sprintf(" - %s\n", proc)) } common.LogSuccess(fmt.Sprintf("检测到AV: %s (%d个进程)", avName, len(foundProcesses))) output.WriteString("\n") } } // 统计结果 output.WriteString("=== 检测结果 ===\n") output.WriteString(fmt.Sprintf("检测到的AV产品: %d个\n", len(detectedAVs))) if len(detectedAVs) > 0 { output.WriteString("检测到的产品: " + strings.Join(detectedAVs, ", ") + "\n") } else { output.WriteString("未检测到已知的AV/EDR产品\n") } return &ScanResult{ 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进程 - 简化实现 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格式:进程名在第一列 if strings.HasPrefix(line, "\"") { parts := strings.Split(line, "\",\"") if len(parts) > 0 { processName := strings.Trim(parts[0], "\"") if processName != "" { processes = append(processes, processName) } } } } 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() }) }