feat: 实现老版本插件适配器架构,无缝接入新插件系统

核心改进:
- 创建LegacyPlugin适配器基础框架,支持老版本插件接入新架构
- 实现适配器模式,保持老版本插件代码完全不变
- 支持不同类型插件的能力配置(漏洞检测、信息收集、服务检测)

已适配插件:
- MS17010: SMB远程代码执行漏洞检测 (EternalBlue)
- SmbGhost: CVE-2020-0796 远程代码执行漏洞检测
- SMB/SMB2: SMB服务弱密码检测和共享枚举
- RDP: 远程桌面服务弱密码检测
- NetBIOS: 信息收集和主机名解析
- Elasticsearch: 弱密码检测和未授权访问检测

技术特点:
- 零代码修改:老版本插件完全不需要修改
- 完整接口实现:适配Plugin、Scanner、Exploiter接口
- 灵活配置:支持暴力破解标志检查、插件类型配置
- 统一管理:通过新的插件注册表统一管理所有插件

测试验证:✓ 所有适配器插件正常工作,与新架构完美集成
This commit is contained in:
ZacharyZcR 2025-08-09 16:15:55 +08:00
parent 6fda09f183
commit d57e5d519d
8 changed files with 559 additions and 0 deletions

View File

@ -0,0 +1,181 @@
package adapter
import (
"context"
"fmt"
"github.com/shadow1ng/fscan/common"
"github.com/shadow1ng/fscan/plugins/base"
)
// LegacyPluginFunc 老版本插件的函数签名
type LegacyPluginFunc func(*common.HostInfo) error
// LegacyPlugin 老版本插件适配器
type LegacyPlugin struct {
metadata *base.PluginMetadata
legacyFunc LegacyPluginFunc
options *LegacyPluginOptions
}
// LegacyPluginOptions 老版本插件选项
type LegacyPluginOptions struct {
// 是否需要检查暴力破解开关
CheckBruteFlag bool
// 是否为漏洞检测类插件
IsVulnPlugin bool
// 是否为信息收集类插件
IsInfoPlugin bool
// 自定义端口如果不使用metadata中的端口
CustomPorts []int
}
// NewLegacyPlugin 创建老版本插件适配器
func NewLegacyPlugin(metadata *base.PluginMetadata, legacyFunc LegacyPluginFunc, options *LegacyPluginOptions) *LegacyPlugin {
if options == nil {
options = &LegacyPluginOptions{
CheckBruteFlag: true,
IsVulnPlugin: true,
}
}
return &LegacyPlugin{
metadata: metadata,
legacyFunc: legacyFunc,
options: options,
}
}
// GetMetadata 实现Plugin接口
func (p *LegacyPlugin) GetMetadata() *base.PluginMetadata {
return p.metadata
}
// GetName 实现Scanner接口
func (p *LegacyPlugin) GetName() string {
return p.metadata.Name
}
// Initialize 实现Plugin接口
func (p *LegacyPlugin) Initialize() error {
return nil
}
// Scan 实现Plugin接口 - 适配老版本插件调用
func (p *LegacyPlugin) Scan(ctx context.Context, info *common.HostInfo) (*base.ScanResult, error) {
// 检查上下文是否取消
select {
case <-ctx.Done():
return nil, ctx.Err()
default:
}
// 如果需要检查暴力破解标志且已禁用暴力破解
if p.options.CheckBruteFlag && common.DisableBrute {
if p.options.IsVulnPlugin {
// 漏洞检测类插件在禁用暴力破解时仍然运行
// 这里不返回,继续执行
} else {
// 非漏洞检测类插件在禁用暴力破解时跳过
return &base.ScanResult{
Success: false,
Service: p.metadata.Name,
Error: fmt.Errorf("brute force disabled"),
}, nil
}
}
// 调用老版本插件函数
err := p.legacyFunc(info)
if err != nil {
// 插件执行失败
return &base.ScanResult{
Success: false,
Service: p.metadata.Name,
Error: err,
}, nil
}
// 插件执行成功
// 老版本插件通常自己处理日志和结果输出,所以这里返回基本成功信息
return &base.ScanResult{
Success: true,
Service: p.metadata.Name,
Banner: fmt.Sprintf("%s scan completed", p.metadata.Name),
Extra: map[string]interface{}{
"plugin_type": "legacy",
"category": p.metadata.Category,
},
}, nil
}
// ScanCredential 实现Plugin接口 - 老版本插件不支持单独的凭据测试
func (p *LegacyPlugin) ScanCredential(ctx context.Context, info *common.HostInfo, cred *base.Credential) (*base.ScanResult, error) {
// 老版本插件通常内部处理凭据所以这里直接调用Scan
return p.Scan(ctx, info)
}
// =============================================================================
// Exploiter接口实现 - 老版本插件通常不支持独立的利用功能
// =============================================================================
// Exploit 实现Exploiter接口 - 老版本插件通常不支持单独利用
func (p *LegacyPlugin) Exploit(ctx context.Context, info *common.HostInfo, creds *base.Credential) (*base.ExploitResult, error) {
// 老版本插件通常在Scan中完成所有操作不支持独立利用
return nil, fmt.Errorf("legacy plugin does not support separate exploitation")
}
// GetExploitMethods 实现Exploiter接口 - 返回空的利用方法列表
func (p *LegacyPlugin) GetExploitMethods() []base.ExploitMethod {
// 老版本插件不支持独立的利用方法
return []base.ExploitMethod{}
}
// IsExploitSupported 实现Exploiter接口 - 老版本插件不支持独立利用
func (p *LegacyPlugin) IsExploitSupported(method base.ExploitType) bool {
// 老版本插件不支持独立的利用方法
return false
}
// GetCapabilities 实现Plugin接口
func (p *LegacyPlugin) GetCapabilities() []base.Capability {
capabilities := []base.Capability{}
// 根据插件类型分配合适的能力
if p.options.IsVulnPlugin {
// 漏洞检测插件通常涉及信息泄露检测
capabilities = append(capabilities, base.CapInformationLeak)
}
if p.options.IsInfoPlugin {
// 信息收集插件
capabilities = append(capabilities, base.CapInformationLeak)
}
// 大多数老版本插件都支持弱密码检测
if p.options.CheckBruteFlag {
capabilities = append(capabilities, base.CapWeakPassword)
}
return capabilities
}
// SetCapabilities 实现Plugin接口 - 老版本插件不支持动态设置能力
func (p *LegacyPlugin) SetCapabilities(capabilities []base.Capability) {
// 老版本插件的能力是固定的,这里不做任何操作
}
// GetDefaultPorts 获取默认端口
func (p *LegacyPlugin) GetDefaultPorts() []int {
if len(p.options.CustomPorts) > 0 {
return p.options.CustomPorts
}
return p.metadata.Ports
}
// Cleanup 清理资源
func (p *LegacyPlugin) Cleanup() error {
// 老版本插件通常没有需要清理的资源
return nil
}

View File

@ -0,0 +1,54 @@
package elasticsearch
import (
"github.com/shadow1ng/fscan/plugins/adapter"
"github.com/shadow1ng/fscan/plugins/base"
Plugins "github.com/shadow1ng/fscan/plugins"
)
// NewElasticsearchPlugin 创建Elasticsearch弱密码检测插件
func NewElasticsearchPlugin() base.Plugin {
// 插件元数据
metadata := &base.PluginMetadata{
Name: "elasticsearch",
Version: "1.0.0",
Author: "fscan-team",
Description: "Elasticsearch搜索引擎弱密码检测和未授权访问检测",
Category: "service",
Ports: []int{9200, 9300}, // Elasticsearch端口
Protocols: []string{"tcp"},
Tags: []string{"elasticsearch", "weak-password", "unauthorized", "service"},
}
// 适配器选项
options := &adapter.LegacyPluginOptions{
CheckBruteFlag: true, // Elasticsearch依赖暴力破解标志
IsVulnPlugin: false, // 这是服务检测插件,虽然包含安全检查
IsInfoPlugin: true, // 包含信息收集功能
CustomPorts: []int{9200, 9300}, // Elasticsearch端口
}
// 创建适配器直接使用老版本的ElasticScan函数
return adapter.NewLegacyPlugin(metadata, Plugins.ElasticScan, options)
}
// init 自动注册Elasticsearch插件
func init() {
// 创建插件工厂
metadata := &base.PluginMetadata{
Name: "elasticsearch",
Version: "1.0.0",
Author: "fscan-team",
Description: "Elasticsearch搜索引擎弱密码检测和未授权访问检测",
Category: "service",
Ports: []int{9200, 9300},
Protocols: []string{"tcp"},
Tags: []string{"elasticsearch", "weak-password", "unauthorized", "service"},
}
factory := base.NewSimplePluginFactory(metadata, func() base.Plugin {
return NewElasticsearchPlugin()
})
base.GlobalPluginRegistry.Register("elasticsearch", factory)
}

View File

@ -0,0 +1,54 @@
package ms17010
import (
"github.com/shadow1ng/fscan/plugins/adapter"
"github.com/shadow1ng/fscan/plugins/base"
Plugins "github.com/shadow1ng/fscan/plugins"
)
// NewMS17010Plugin 创建MS17010漏洞检测插件
func NewMS17010Plugin() base.Plugin {
// 插件元数据
metadata := &base.PluginMetadata{
Name: "ms17010",
Version: "1.0.0",
Author: "fscan-team",
Description: "MS17010 SMB远程代码执行漏洞检测 (EternalBlue)",
Category: "vulnerability",
Ports: []int{445}, // SMB端口
Protocols: []string{"tcp"},
Tags: []string{"smb", "ms17010", "eternalblue", "vulnerability"},
}
// 适配器选项
options := &adapter.LegacyPluginOptions{
CheckBruteFlag: false, // MS17010不依赖暴力破解标志
IsVulnPlugin: true, // 这是漏洞检测插件
IsInfoPlugin: false,
CustomPorts: []int{445}, // 固定使用SMB端口
}
// 创建适配器直接使用老版本的MS17010函数
return adapter.NewLegacyPlugin(metadata, Plugins.MS17010, options)
}
// init 自动注册MS17010插件
func init() {
// 创建插件工厂
metadata := &base.PluginMetadata{
Name: "ms17010",
Version: "1.0.0",
Author: "fscan-team",
Description: "MS17010 SMB远程代码执行漏洞检测 (EternalBlue)",
Category: "vulnerability",
Ports: []int{445},
Protocols: []string{"tcp"},
Tags: []string{"smb", "ms17010", "eternalblue", "vulnerability"},
}
factory := base.NewSimplePluginFactory(metadata, func() base.Plugin {
return NewMS17010Plugin()
})
base.GlobalPluginRegistry.Register("ms17010", factory)
}

View File

@ -0,0 +1,54 @@
package netbios
import (
"github.com/shadow1ng/fscan/plugins/adapter"
"github.com/shadow1ng/fscan/plugins/base"
Plugins "github.com/shadow1ng/fscan/plugins"
)
// NewNetBiosPlugin 创建NetBIOS信息收集插件
func NewNetBiosPlugin() base.Plugin {
// 插件元数据
metadata := &base.PluginMetadata{
Name: "netbios",
Version: "1.0.0",
Author: "fscan-team",
Description: "NetBIOS信息收集和主机名解析",
Category: "information",
Ports: []int{139, 445}, // NetBIOS端口
Protocols: []string{"tcp", "udp"},
Tags: []string{"netbios", "information-gathering", "hostname", "smb"},
}
// 适配器选项
options := &adapter.LegacyPluginOptions{
CheckBruteFlag: false, // NetBIOS信息收集不依赖暴力破解标志
IsVulnPlugin: false, // 这不是漏洞检测插件
IsInfoPlugin: true, // 这是信息收集插件
CustomPorts: []int{139, 445}, // NetBIOS/SMB端口
}
// 创建适配器直接使用老版本的NetBIOS函数
return adapter.NewLegacyPlugin(metadata, Plugins.NetBIOS, options)
}
// init 自动注册NetBIOS插件
func init() {
// 创建插件工厂
metadata := &base.PluginMetadata{
Name: "netbios",
Version: "1.0.0",
Author: "fscan-team",
Description: "NetBIOS信息收集和主机名解析",
Category: "information",
Ports: []int{139, 445},
Protocols: []string{"tcp", "udp"},
Tags: []string{"netbios", "information-gathering", "hostname", "smb"},
}
factory := base.NewSimplePluginFactory(metadata, func() base.Plugin {
return NewNetBiosPlugin()
})
base.GlobalPluginRegistry.Register("netbios", factory)
}

View File

@ -0,0 +1,54 @@
package rdp
import (
"github.com/shadow1ng/fscan/plugins/adapter"
"github.com/shadow1ng/fscan/plugins/base"
Plugins "github.com/shadow1ng/fscan/plugins"
)
// NewRdpPlugin 创建RDP弱密码检测插件
func NewRdpPlugin() base.Plugin {
// 插件元数据
metadata := &base.PluginMetadata{
Name: "rdp",
Version: "1.0.0",
Author: "fscan-team",
Description: "RDP远程桌面服务弱密码检测",
Category: "service",
Ports: []int{3389}, // RDP端口
Protocols: []string{"tcp"},
Tags: []string{"rdp", "remote-desktop", "weak-password", "service", "brute-force"},
}
// 适配器选项
options := &adapter.LegacyPluginOptions{
CheckBruteFlag: true, // RDP依赖暴力破解标志
IsVulnPlugin: false, // 这是服务检测插件,不是漏洞检测
IsInfoPlugin: false, // 主要是弱密码检测
CustomPorts: []int{3389}, // RDP端口
}
// 创建适配器直接使用老版本的RdpScan函数
return adapter.NewLegacyPlugin(metadata, Plugins.RdpScan, options)
}
// init 自动注册RDP插件
func init() {
// 创建插件工厂
metadata := &base.PluginMetadata{
Name: "rdp",
Version: "1.0.0",
Author: "fscan-team",
Description: "RDP远程桌面服务弱密码检测",
Category: "service",
Ports: []int{3389},
Protocols: []string{"tcp"},
Tags: []string{"rdp", "remote-desktop", "weak-password", "service", "brute-force"},
}
factory := base.NewSimplePluginFactory(metadata, func() base.Plugin {
return NewRdpPlugin()
})
base.GlobalPluginRegistry.Register("rdp", factory)
}

View File

@ -0,0 +1,54 @@
package smb
import (
"github.com/shadow1ng/fscan/plugins/adapter"
"github.com/shadow1ng/fscan/plugins/base"
Plugins "github.com/shadow1ng/fscan/plugins"
)
// NewSmbPlugin 创建SMB弱密码检测插件
func NewSmbPlugin() base.Plugin {
// 插件元数据
metadata := &base.PluginMetadata{
Name: "smb",
Version: "1.0.0",
Author: "fscan-team",
Description: "SMB服务弱密码检测和共享枚举",
Category: "service",
Ports: []int{445, 139}, // SMB端口
Protocols: []string{"tcp"},
Tags: []string{"smb", "weak-password", "service", "brute-force"},
}
// 适配器选项
options := &adapter.LegacyPluginOptions{
CheckBruteFlag: true, // SMB依赖暴力破解标志
IsVulnPlugin: false, // 这是服务检测插件,不是漏洞检测
IsInfoPlugin: true, // 包含信息收集功能
CustomPorts: []int{445, 139}, // SMB端口
}
// 创建适配器直接使用老版本的SmbScan函数
return adapter.NewLegacyPlugin(metadata, Plugins.SmbScan, options)
}
// init 自动注册SMB插件
func init() {
// 创建插件工厂
metadata := &base.PluginMetadata{
Name: "smb",
Version: "1.0.0",
Author: "fscan-team",
Description: "SMB服务弱密码检测和共享枚举",
Category: "service",
Ports: []int{445, 139},
Protocols: []string{"tcp"},
Tags: []string{"smb", "weak-password", "service", "brute-force"},
}
factory := base.NewSimplePluginFactory(metadata, func() base.Plugin {
return NewSmbPlugin()
})
base.GlobalPluginRegistry.Register("smb", factory)
}

View File

@ -0,0 +1,54 @@
package smb2
import (
"github.com/shadow1ng/fscan/plugins/adapter"
"github.com/shadow1ng/fscan/plugins/base"
Plugins "github.com/shadow1ng/fscan/plugins"
)
// NewSmb2Plugin 创建SMB2弱密码检测插件
func NewSmb2Plugin() base.Plugin {
// 插件元数据
metadata := &base.PluginMetadata{
Name: "smb2",
Version: "1.0.0",
Author: "fscan-team",
Description: "SMB2服务弱密码检测和共享枚举 (支持NTLM哈希)",
Category: "service",
Ports: []int{445}, // SMB2端口
Protocols: []string{"tcp"},
Tags: []string{"smb2", "weak-password", "service", "brute-force", "ntlm"},
}
// 适配器选项
options := &adapter.LegacyPluginOptions{
CheckBruteFlag: true, // SMB2依赖暴力破解标志
IsVulnPlugin: false, // 这是服务检测插件,不是漏洞检测
IsInfoPlugin: true, // 包含信息收集功能
CustomPorts: []int{445}, // SMB2端口
}
// 创建适配器直接使用老版本的SmbScan2函数
return adapter.NewLegacyPlugin(metadata, Plugins.SmbScan2, options)
}
// init 自动注册SMB2插件
func init() {
// 创建插件工厂
metadata := &base.PluginMetadata{
Name: "smb2",
Version: "1.0.0",
Author: "fscan-team",
Description: "SMB2服务弱密码检测和共享枚举 (支持NTLM哈希)",
Category: "service",
Ports: []int{445},
Protocols: []string{"tcp"},
Tags: []string{"smb2", "weak-password", "service", "brute-force", "ntlm"},
}
factory := base.NewSimplePluginFactory(metadata, func() base.Plugin {
return NewSmb2Plugin()
})
base.GlobalPluginRegistry.Register("smb2", factory)
}

View File

@ -0,0 +1,54 @@
package smbghost
import (
"github.com/shadow1ng/fscan/plugins/adapter"
"github.com/shadow1ng/fscan/plugins/base"
Plugins "github.com/shadow1ng/fscan/plugins"
)
// NewSmbGhostPlugin 创建SMBGhost漏洞检测插件
func NewSmbGhostPlugin() base.Plugin {
// 插件元数据
metadata := &base.PluginMetadata{
Name: "smbghost",
Version: "1.0.0",
Author: "fscan-team",
Description: "SMBGhost (CVE-2020-0796) 远程代码执行漏洞检测",
Category: "vulnerability",
Ports: []int{445}, // SMB端口
Protocols: []string{"tcp"},
Tags: []string{"smb", "smbghost", "cve-2020-0796", "vulnerability"},
}
// 适配器选项
options := &adapter.LegacyPluginOptions{
CheckBruteFlag: false, // SMBGhost不依赖暴力破解标志
IsVulnPlugin: true, // 这是漏洞检测插件
IsInfoPlugin: false,
CustomPorts: []int{445}, // 固定使用SMB端口
}
// 创建适配器直接使用老版本的SmbGhost函数
return adapter.NewLegacyPlugin(metadata, Plugins.SmbGhost, options)
}
// init 自动注册SmbGhost插件
func init() {
// 创建插件工厂
metadata := &base.PluginMetadata{
Name: "smbghost",
Version: "1.0.0",
Author: "fscan-team",
Description: "SMBGhost (CVE-2020-0796) 远程代码执行漏洞检测",
Category: "vulnerability",
Ports: []int{445},
Protocols: []string{"tcp"},
Tags: []string{"smb", "smbghost", "cve-2020-0796", "vulnerability"},
}
factory := base.NewSimplePluginFactory(metadata, func() base.Plugin {
return NewSmbGhostPlugin()
})
base.GlobalPluginRegistry.Register("smbghost", factory)
}