mirror of
https://github.com/shadow1ng/fscan.git
synced 2025-09-14 14:06:44 +08:00

主要改进: 1. 修复Services插件端口数据重复问题 - 删除插件结构体中的ports字段和GetPorts()方法 - 系统统一使用注册时的端口信息 2. 引入BasePlugin基础结构体 - 消除51个插件中重复的name字段和Name()方法 - 统一插件基础功能,简化代码维护 3. 统一插件接口设计 - 保持向后兼容,功能完全不变 - 代码更简洁,符合工程最佳实践 影响范围: - services插件:29个文件简化 - web插件:2个文件简化 - local插件:21个文件简化 - 总计删除约150行重复代码
168 lines
3.6 KiB
Go
168 lines
3.6 KiB
Go
package plugins
|
||
|
||
import (
|
||
"context"
|
||
"strings"
|
||
"sync"
|
||
|
||
"github.com/shadow1ng/fscan/common"
|
||
)
|
||
|
||
// Plugin 统一插件接口 - 消除过度设计
|
||
//
|
||
// 统一插件系统设计原则:
|
||
// 之前:3个不同的接口做同样的事情
|
||
// 现在:1个接口统治所有插件
|
||
type Plugin interface {
|
||
Name() string
|
||
Scan(ctx context.Context, info *common.HostInfo) *Result
|
||
}
|
||
|
||
// BasePlugin 基础插件结构 - 消除插件name字段重复
|
||
//
|
||
// 所有插件都需要name字段,通过基础结构体统一提供
|
||
type BasePlugin struct {
|
||
name string
|
||
}
|
||
|
||
// NewBasePlugin 创建基础插件
|
||
func NewBasePlugin(name string) BasePlugin {
|
||
return BasePlugin{name: name}
|
||
}
|
||
|
||
// Name 实现Plugin接口
|
||
func (b BasePlugin) Name() string {
|
||
return b.name
|
||
}
|
||
|
||
// Result 统一结果结构 - 合并所有类型
|
||
type Result struct {
|
||
Success bool
|
||
Service string
|
||
Username string
|
||
Password string
|
||
Banner string
|
||
Output string // web/local插件使用
|
||
Error error
|
||
|
||
// Web插件字段
|
||
Title string // 网页标题
|
||
Status int // HTTP状态码
|
||
Server string // 服务器信息
|
||
Length int // 响应长度
|
||
VulInfo string // 漏洞信息
|
||
}
|
||
|
||
// Exploiter 利用接口 - 保持向后兼容
|
||
type Exploiter interface {
|
||
Exploit(ctx context.Context, info *common.HostInfo, creds Credential) *ExploitResult
|
||
}
|
||
|
||
// ExploitResult 利用结果
|
||
type ExploitResult struct {
|
||
Success bool
|
||
Output string
|
||
Error error
|
||
}
|
||
|
||
// Credential 认证凭据
|
||
type Credential struct {
|
||
Username string
|
||
Password string
|
||
KeyData []byte
|
||
}
|
||
|
||
// PluginInfo 插件信息结构 - 合并工厂和端口信息
|
||
type PluginInfo struct {
|
||
factory func() Plugin
|
||
ports []int
|
||
}
|
||
|
||
// 全局插件注册表 - 一个数据结构解决所有问题
|
||
var (
|
||
plugins = make(map[string]*PluginInfo)
|
||
mutex sync.RWMutex
|
||
)
|
||
|
||
// Register 注册插件 - 一个函数统治所有注册
|
||
func Register(name string, factory func() Plugin) {
|
||
RegisterWithPorts(name, factory, []int{})
|
||
}
|
||
|
||
// RegisterWithPorts 注册带端口信息的插件
|
||
func RegisterWithPorts(name string, factory func() Plugin, ports []int) {
|
||
mutex.Lock()
|
||
defer mutex.Unlock()
|
||
plugins[name] = &PluginInfo{
|
||
factory: factory,
|
||
ports: ports,
|
||
}
|
||
}
|
||
|
||
// Get 获取插件实例
|
||
func Get(name string) Plugin {
|
||
mutex.RLock()
|
||
defer mutex.RUnlock()
|
||
|
||
if info, exists := plugins[name]; exists {
|
||
return info.factory()
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// All 获取所有插件名称
|
||
func All() []string {
|
||
mutex.RLock()
|
||
defer mutex.RUnlock()
|
||
|
||
names := make([]string, 0, len(plugins))
|
||
for name := range plugins {
|
||
names = append(names, name)
|
||
}
|
||
return names
|
||
}
|
||
|
||
// Exists 检查插件是否存在,不创建实例 - 解决性能问题
|
||
func Exists(name string) bool {
|
||
mutex.RLock()
|
||
defer mutex.RUnlock()
|
||
|
||
_, exists := plugins[name]
|
||
return exists
|
||
}
|
||
|
||
// GetPluginPorts 获取插件端口列表
|
||
func GetPluginPorts(name string) []int {
|
||
mutex.RLock()
|
||
defer mutex.RUnlock()
|
||
|
||
if info, exists := plugins[name]; exists {
|
||
return info.ports
|
||
}
|
||
return []int{} // 返回空列表表示适用于所有端口
|
||
}
|
||
|
||
// GenerateCredentials 生成测试凭据 - 从services包移到这里统一管理
|
||
func GenerateCredentials(service string) []Credential {
|
||
users := common.Userdict[service]
|
||
if len(users) == 0 {
|
||
users = []string{"admin", "root", "administrator", "user", "guest", ""}
|
||
}
|
||
|
||
passwords := common.Passwords
|
||
if len(passwords) == 0 {
|
||
passwords = []string{"", "admin", "root", "password", "123456"}
|
||
}
|
||
|
||
var credentials []Credential
|
||
for _, user := range users {
|
||
for _, pass := range passwords {
|
||
actualPass := strings.Replace(pass, "{user}", user, -1)
|
||
credentials = append(credentials, Credential{
|
||
Username: user,
|
||
Password: actualPass,
|
||
})
|
||
}
|
||
}
|
||
return credentials
|
||
} |