fscan/plugins/local/avdetect.go
ZacharyZcR 95497da8ca refactor: 优化插件系统设计,消除代码重复
主要改进:
1. 修复Services插件端口数据重复问题
   - 删除插件结构体中的ports字段和GetPorts()方法
   - 系统统一使用注册时的端口信息

2. 引入BasePlugin基础结构体
   - 消除51个插件中重复的name字段和Name()方法
   - 统一插件基础功能,简化代码维护

3. 统一插件接口设计
   - 保持向后兼容,功能完全不变
   - 代码更简洁,符合工程最佳实践

影响范围:
- services插件:29个文件简化
- web插件:2个文件简化
- local插件:21个文件简化
- 总计删除约150行重复代码
2025-09-02 05:36:12 +08:00

193 lines
4.6 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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()
})
}