fscan/plugins/local/avdetect.go
ZacharyZcR be1188d82b refactor: v2.1.0 核心重构和功能增强
**核心架构重构**
- 重构目录结构:Common/ -> common/, Core/ -> core/, Plugins/ -> plugins/, WebScan/ -> webscan/
- 模块化设计:拆分common/为parsers/, logging/, i18n/, output/, proxy/等子模块
- 统一插件系统:消除Plugin/Scanner/LocalPlugin等重复接口
- 配置解析器重写:新增parsers包处理所有配置解析逻辑
- 国际化支持:完整的中英文i18n系统

**服务插件重构** (59个插件)
- 所有服务插件采用统一接口设计
- 新增服务插件:ActiveMQ, Cassandra, Kafka, Neo4j, RabbitMQ, Rsync等
- 增强现有插件:SSH, MySQL, Redis, SMB, FTP, PostgreSQL等
- 本地功能插件:AVDetect, Cleaner, CronTask, KeyLogger, SystemInfo等26个
- 智能错误分类和重试机制
- 并发暴力破解优化

**核心扫描引擎**
- 端口扫描重构:支持SYN/Connect/ICMP多种模式
- 服务识别增强:集成nmap-service-probes指纹库
- Web扫描优化:title抓取、POC检测、指纹识别
- 进度条系统:实时显示扫描进度、发包统计、内存使用
- 发包频率控制:支持-rate和-maxpkts限制

**新增功能**
- user:pass格式字典支持 (-upf参数) #179
- fscan-lite C语言版本:轻量级无依赖版本
- 本地扫描模式:26个本地安全检测插件
- API模式:支持远程调用
- Docker测试环境:13个服务的docker-compose配置

**Bug修复**
- 修复并发输出混乱问题
- 修复包计数双重统计
- 修复进度条显示不准确
- 修复-no参数被忽略
- 修复SMB/SSH认证问题
- 修复Oracle TNS服务识别错误
- 修复SafeDialTimeout缺失TCP计数

**性能优化**
- 删除大量死代码和冗余函数
- 简化过度工程设计
- 优化端口扫描性能
- 减少内存占用
- 清理重复代码

**测试和CI/CD**
- 新增核心模块单元测试 (2000+ loc)
- GitHub Actions优化:统一构建发布流程
- 支持fscan和fscan-lite统一发布
- 中文化工作流配置

**文档**
- 更新README文档
- 新增插件开发文档
- 完善国际化文档

**依赖更新**
- 更新go.mod依赖
- 清理无用依赖
- 升级核心库版本

统计:
- 删除文件:61个旧架构文件
- 新增文件:500+个模块化文件
- 代码行数:~50000 lines
- Commits压缩:289 -> 1
2025-10-02 00:50:10 +08:00

206 lines
5.1 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"
"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 {
// 提取进程名部分进行匹配去除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)
output.WriteString(fmt.Sprintf("✓ 检测到 %s:\n", avName))
common.LogSuccess(fmt.Sprintf("检测到AV: %s (%d个进程)", avName, len(foundProcesses)))
// 输出详细进程信息到控制台
for _, proc := range foundProcesses {
output.WriteString(fmt.Sprintf(" - %s\n", proc))
common.LogInfo(fmt.Sprintf(" - %s", proc))
}
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进程 - 包含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()
})
}