fscan/plugins/local_backup/plugin.go
ZacharyZcR 678d750c8a refactor: 重构插件架构,实现单文件插件系统
将复杂的三文件插件架构(connector/exploiter/plugin)重构为简化的单文件插件架构,
大幅减少代码重复和维护成本,提升插件开发效率。

主要改进:
• 将每个服务插件从3个文件简化为1个文件
• 删除过度设计的工厂模式、适配器模式等抽象层
• 消除plugins/services/、plugins/adapters/、plugins/base/复杂目录结构
• 实现直接的插件注册机制,提升系统简洁性
• 保持完全向后兼容,所有扫描功能和输出格式不变

重构统计:
• 删除文件:100+个复杂架构文件
• 新增文件:20个简化的单文件插件
• 代码减少:每个插件减少60-80%代码量
• 功能增强:所有插件包含完整扫描和利用功能

已重构插件: MySQL, SSH, Redis, MongoDB, PostgreSQL, MSSQL, Oracle,
Neo4j, Memcached, RabbitMQ, ActiveMQ, Cassandra, FTP, Kafka, LDAP,
Rsync, SMTP, SNMP, Telnet, VNC

验证通过: 新系统编译运行正常,所有插件功能验证通过
2025-08-25 23:57:00 +08:00

165 lines
4.0 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 (
"context"
"errors"
"fmt"
"os"
"os/user"
"runtime"
"github.com/shadow1ng/fscan/common"
"github.com/shadow1ng/fscan/plugins/base"
)
// BaseLocalPlugin 本地插件基础实现 - 简化架构
type BaseLocalPlugin struct {
*base.BasePlugin
platforms []string
requiresPrivileges bool
}
// NewBaseLocalPlugin 创建基础本地插件
func NewBaseLocalPlugin(metadata *base.PluginMetadata) *BaseLocalPlugin {
basePlugin := base.NewBasePlugin(metadata)
return &BaseLocalPlugin{
BasePlugin: basePlugin,
platforms: []string{"windows", "linux", "darwin"}, // 默认支持所有平台
requiresPrivileges: false,
}
}
// Initialize 初始化插件
func (p *BaseLocalPlugin) Initialize() error {
// 检查平台支持
if !p.isPlatformSupported() {
return fmt.Errorf("当前平台 %s 不支持此插件", runtime.GOOS)
}
return p.BasePlugin.Initialize()
}
// Scan 执行扫描
func (p *BaseLocalPlugin) Scan(ctx context.Context, info *common.HostInfo) (*base.ScanResult, error) {
// 检查权限要求
if p.requiresPrivileges && !p.hasRequiredPrivileges() {
return &base.ScanResult{
Success: false,
Error: errors.New("需要管理员/root权限才能执行此扫描"),
}, nil
}
return p.ScanLocal(ctx, info)
}
// ScanLocal 默认本地扫描实现(子类应重写)
func (p *BaseLocalPlugin) ScanLocal(ctx context.Context, info *common.HostInfo) (*base.ScanResult, error) {
return &base.ScanResult{
Success: false,
Error: errors.New("ScanLocal方法需要在子类中实现"),
}, nil
}
// GetSystemInfo 获取系统信息 - 实用工具方法
func (p *BaseLocalPlugin) GetSystemInfo() map[string]string {
systemInfo := make(map[string]string)
systemInfo["os"] = runtime.GOOS
systemInfo["arch"] = runtime.GOARCH
if homeDir, err := os.UserHomeDir(); err == nil {
systemInfo["home_dir"] = homeDir
}
if workDir, err := os.Getwd(); err == nil {
systemInfo["working_dir"] = workDir
}
systemInfo["temp_dir"] = os.TempDir()
// 获取用户名
if currentUser, err := user.Current(); err == nil {
systemInfo["username"] = currentUser.Username
}
// 获取主机名
if hostname, err := os.Hostname(); err == nil {
systemInfo["hostname"] = hostname
}
return systemInfo
}
// GetPlatformSupport 获取支持的平台
func (p *BaseLocalPlugin) GetPlatformSupport() []string {
return p.platforms
}
// SetPlatformSupport 设置支持的平台
func (p *BaseLocalPlugin) SetPlatformSupport(platforms []string) {
p.platforms = platforms
}
// RequiresPrivileges 是否需要特殊权限
func (p *BaseLocalPlugin) RequiresPrivileges() bool {
return p.requiresPrivileges
}
// SetRequiresPrivileges 设置是否需要特殊权限
func (p *BaseLocalPlugin) SetRequiresPrivileges(required bool) {
p.requiresPrivileges = required
}
// isPlatformSupported 检查当前平台是否支持
func (p *BaseLocalPlugin) isPlatformSupported() bool {
currentOS := runtime.GOOS
for _, platform := range p.platforms {
if platform == currentOS {
return true
}
}
return false
}
// hasRequiredPrivileges 检查是否具有所需权限
func (p *BaseLocalPlugin) hasRequiredPrivileges() bool {
if !p.requiresPrivileges {
return true
}
// 这里可以根据平台实现权限检查
// Windows: 检查是否为管理员
// Linux/macOS: 检查是否为root或有sudo权限
switch runtime.GOOS {
case "windows":
return isWindowsAdmin()
case "linux", "darwin":
return isUnixRoot()
default:
return false
}
}
// 平台特定的权限检查函数 - 实际实现
func isWindowsAdmin() bool {
// Windows管理员权限检查尝试写入系统目录
testPath := `C:\Windows\Temp\fscan_admin_test`
file, err := os.Create(testPath)
if err != nil {
// 无法创建文件,可能没有管理员权限
return false
}
file.Close()
os.Remove(testPath)
return true
}
func isUnixRoot() bool {
// Unix/Linux root用户检查
currentUser, err := user.Current()
if err != nil {
return false
}
return currentUser.Uid == "0"
}