fscan/plugins/local/avdetect.go
ZacharyZcR 4cd8ed5668 feat: 完成本地插件架构统一迁移
迁移所有本地插件到统一Plugin接口架构:
- socks5proxy/systemdservice: 网络代理和Linux服务持久化
- winregistry/winservice/winschtask/winstartup/winwmi: Windows持久化套件
- 所有插件消除BaseLocalPlugin继承,统一使用Plugin接口
- 保持原有功能完整性,支持跨平台编译标记
- 删除过度设计的继承体系,实现直接简洁实现
2025-08-26 14:39:53 +08:00

200 lines
4.7 KiB
Go
Raw 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"
)
//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 {
name string
avProducts map[string]AVProduct
}
// NewAVDetectPlugin 创建AV检测插件
func NewAVDetectPlugin() *AVDetectPlugin {
plugin := &AVDetectPlugin{
name: "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
}
// GetName 实现Plugin接口
func (p *AVDetectPlugin) GetName() string {
return p.name
}
// GetPorts 实现Plugin接口 - local插件不需要端口
func (p *AVDetectPlugin) GetPorts() []int {
return []int{}
}
// 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()
})
}