fscan/plugins/base/plugin.go
ZacharyZcR 4a3f281b6b refactor: 统一Plugins目录大小写为小写
- 将所有Plugins路径重命名为plugins
- 修复Git索引与实际文件系统大小写不一致问题
- 确保跨平台兼容性和路径一致性
2025-08-12 13:08:06 +08:00

259 lines
6.6 KiB
Go

package base
import (
"context"
"fmt"
"time"
"github.com/shadow1ng/fscan/common"
"github.com/shadow1ng/fscan/common/i18n"
)
// =============================================================================
// 完整插件基础实现
// =============================================================================
// BasePlugin 基础插件实现,组合扫描和利用功能
type BasePlugin struct {
*BaseScanner
*BaseExploiter
metadata *PluginMetadata
initialized bool
}
// NewBasePlugin 创建基础插件
func NewBasePlugin(metadata *PluginMetadata) *BasePlugin {
return &BasePlugin{
BaseScanner: NewBaseScanner(metadata.Name, metadata),
BaseExploiter: NewBaseExploiter(metadata.Name),
metadata: metadata,
initialized: false,
}
}
// Initialize 初始化插件
func (p *BasePlugin) Initialize() error {
if p.initialized {
return nil
}
// 执行插件特定的初始化逻辑
common.LogDebug(i18n.GetText("plugin_init", p.metadata.Name))
p.initialized = true
return nil
}
// GetMetadata 获取插件元数据
func (p *BasePlugin) GetMetadata() *PluginMetadata {
return p.metadata
}
// =============================================================================
// 通用插件实现模板
// =============================================================================
// ServicePlugin 服务插件模板 - 提供常见的服务扫描模式
type ServicePlugin struct {
*BasePlugin
credentialScanner CredentialScanner
serviceConnector ServiceConnector
}
// ServiceConnector 服务连接器接口
type ServiceConnector interface {
// Connect 连接到服务
Connect(ctx context.Context, info *common.HostInfo) (interface{}, error)
// Authenticate 认证
Authenticate(ctx context.Context, conn interface{}, cred *Credential) error
// Close 关闭连接
Close(conn interface{}) error
}
// NewServicePlugin 创建服务插件
func NewServicePlugin(metadata *PluginMetadata, connector ServiceConnector) *ServicePlugin {
plugin := &ServicePlugin{
BasePlugin: NewBasePlugin(metadata),
serviceConnector: connector,
}
// 设置自己为凭据扫描器
plugin.credentialScanner = plugin
return plugin
}
// Scan 服务扫描实现
func (p *ServicePlugin) Scan(ctx context.Context, info *common.HostInfo) (*ScanResult, error) {
// 检查是否禁用暴力破解
if common.DisableBrute {
return &ScanResult{
Success: false,
Error: fmt.Errorf(i18n.GetText("plugin_brute_disabled")),
}, nil
}
// 生成凭据列表
credentials := p.generateCredentials()
if len(credentials) == 0 {
return &ScanResult{
Success: false,
Error: fmt.Errorf(i18n.GetText("plugin_no_credentials")),
}, nil
}
// 执行并发扫描
config := &ConcurrentScanConfig{
MaxConcurrent: common.ModuleThreadNum,
Timeout: time.Duration(common.Timeout) * time.Second,
MaxRetries: common.MaxRetries,
}
return ConcurrentCredentialScan(ctx, p.credentialScanner, info, credentials, config)
}
// ScanCredential 实现CredentialScanner接口
func (p *ServicePlugin) ScanCredential(ctx context.Context, info *common.HostInfo, cred *Credential) (*ScanResult, error) {
// 连接到服务
conn, err := p.serviceConnector.Connect(ctx, info)
if err != nil {
return &ScanResult{
Success: false,
Error: fmt.Errorf("连接失败: %v", err),
}, nil
}
defer p.serviceConnector.Close(conn)
// 尝试认证
err = p.serviceConnector.Authenticate(ctx, conn, cred)
if err != nil {
return &ScanResult{
Success: false,
Error: fmt.Errorf("认证失败: %v", err),
}, nil
}
// 认证成功
result := &ScanResult{
Success: true,
Service: p.metadata.Name,
Credentials: []*Credential{cred},
Extra: make(map[string]interface{}),
}
return result, nil
}
// generateCredentials 生成凭据列表(需要子类重写)
func (p *ServicePlugin) generateCredentials() []*Credential {
// 默认实现:从通用字典生成
serviceName := p.metadata.Name
usernames := common.Userdict[serviceName]
if len(usernames) == 0 {
usernames = []string{"admin", "root", serviceName}
}
return GenerateCredentials(usernames, common.Passwords)
}
// GetServiceConnector 获取服务连接器(提供给子插件访问)
func (p *ServicePlugin) GetServiceConnector() ServiceConnector {
return p.serviceConnector
}
// =============================================================================
// 插件工厂
// =============================================================================
// PluginFactory 插件工厂接口
type PluginFactory interface {
CreatePlugin() Plugin
GetMetadata() *PluginMetadata
}
// SimplePluginFactory 简单插件工厂
type SimplePluginFactory struct {
metadata *PluginMetadata
creator func() Plugin
}
// NewSimplePluginFactory 创建简单插件工厂
func NewSimplePluginFactory(metadata *PluginMetadata, creator func() Plugin) *SimplePluginFactory {
return &SimplePluginFactory{
metadata: metadata,
creator: creator,
}
}
// CreatePlugin 创建插件实例
func (f *SimplePluginFactory) CreatePlugin() Plugin {
return f.creator()
}
// GetMetadata 获取插件元数据
func (f *SimplePluginFactory) GetMetadata() *PluginMetadata {
return f.metadata
}
// =============================================================================
// 插件注册管理器
// =============================================================================
// PluginRegistry 插件注册表
type PluginRegistry struct {
factories map[string]PluginFactory
}
// NewPluginRegistry 创建插件注册表
func NewPluginRegistry() *PluginRegistry {
return &PluginRegistry{
factories: make(map[string]PluginFactory),
}
}
// Register 注册插件工厂
func (r *PluginRegistry) Register(name string, factory PluginFactory) {
r.factories[name] = factory
}
// Create 创建插件实例
func (r *PluginRegistry) Create(name string) (Plugin, error) {
factory, exists := r.factories[name]
if !exists {
return nil, fmt.Errorf("插件 %s 未注册", name)
}
plugin := factory.CreatePlugin()
if err := plugin.Initialize(); err != nil {
return nil, fmt.Errorf("插件初始化失败: %v", err)
}
return plugin, nil
}
// GetAll 获取所有注册的插件名称
func (r *PluginRegistry) GetAll() []string {
names := make([]string, 0, len(r.factories))
for name := range r.factories {
names = append(names, name)
}
return names
}
// GetMetadata 获取插件元数据
func (r *PluginRegistry) GetMetadata(name string) *PluginMetadata {
factory, exists := r.factories[name]
if !exists {
return nil
}
return factory.GetMetadata()
}
// GetFactory 获取插件工厂
func (r *PluginRegistry) GetFactory(name string) PluginFactory {
return r.factories[name]
}
// 全局插件注册表
var GlobalPluginRegistry = NewPluginRegistry()