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

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

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

测试验证:✓ 所有适配器插件正常工作,与新架构完美集成
2025-08-09 16:15:55 +08:00

181 lines
5.2 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 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
}