mirror of
https://github.com/shadow1ng/fscan.git
synced 2025-09-14 05:56:46 +08:00

将原有的878行单一文件重构为多个专门化模块: - 类型定义模块:集中管理所有数据结构 - 扫描器核心:初始化和全局状态管理 - 编码工具:处理各种编码格式转换 - 探测器解析:解析nmap-service-probes格式 - 匹配引擎:模式匹配和服务识别 - 版本解析:服务版本信息提取 通过向后兼容层保持原有API接口不变,确保现有代码无需修改即可使用新架构
174 lines
5.0 KiB
Go
174 lines
5.0 KiB
Go
package portfinger
|
||
|
||
import (
|
||
"fmt"
|
||
"regexp"
|
||
"strconv"
|
||
"strings"
|
||
|
||
"github.com/shadow1ng/fscan/common"
|
||
)
|
||
|
||
// 解析match指令获取匹配规则
|
||
func (p *Probe) getMatch(data string) (match Match, err error) {
|
||
common.LogDebug("开始解析match指令:" + data)
|
||
match = Match{}
|
||
|
||
// 提取match文本并解析指令语法
|
||
matchText := data[len("match")+1:]
|
||
directive := p.getDirectiveSyntax(matchText)
|
||
|
||
// 分割文本获取pattern和版本信息
|
||
textSplited := strings.Split(directive.DirectiveStr, directive.Delimiter)
|
||
if len(textSplited) == 0 {
|
||
return match, fmt.Errorf("无效的match指令格式")
|
||
}
|
||
|
||
pattern := textSplited[0]
|
||
versionInfo := strings.Join(textSplited[1:], "")
|
||
|
||
// 解码并编译正则表达式
|
||
patternUnescaped, decodeErr := DecodePattern(pattern)
|
||
if decodeErr != nil {
|
||
common.LogDebug("解码pattern失败: " + decodeErr.Error())
|
||
return match, decodeErr
|
||
}
|
||
|
||
patternUnescapedStr := string([]rune(string(patternUnescaped)))
|
||
patternCompiled, compileErr := regexp.Compile(patternUnescapedStr)
|
||
if compileErr != nil {
|
||
common.LogDebug("编译正则表达式失败: " + compileErr.Error())
|
||
return match, compileErr
|
||
}
|
||
|
||
// 设置match对象属性
|
||
match.Service = directive.DirectiveName
|
||
match.Pattern = pattern
|
||
match.PatternCompiled = patternCompiled
|
||
match.VersionInfo = versionInfo
|
||
|
||
common.LogDebug(fmt.Sprintf("解析match成功: 服务=%s, Pattern=%s",
|
||
match.Service, match.Pattern))
|
||
return match, nil
|
||
}
|
||
|
||
// 解析softmatch指令获取软匹配规则
|
||
func (p *Probe) getSoftMatch(data string) (softMatch Match, err error) {
|
||
common.LogDebug("开始解析softmatch指令:" + data)
|
||
softMatch = Match{IsSoft: true}
|
||
|
||
// 提取softmatch文本并解析指令语法
|
||
matchText := data[len("softmatch")+1:]
|
||
directive := p.getDirectiveSyntax(matchText)
|
||
|
||
// 分割文本获取pattern和版本信息
|
||
textSplited := strings.Split(directive.DirectiveStr, directive.Delimiter)
|
||
if len(textSplited) == 0 {
|
||
return softMatch, fmt.Errorf("无效的softmatch指令格式")
|
||
}
|
||
|
||
pattern := textSplited[0]
|
||
versionInfo := strings.Join(textSplited[1:], "")
|
||
|
||
// 解码并编译正则表达式
|
||
patternUnescaped, decodeErr := DecodePattern(pattern)
|
||
if decodeErr != nil {
|
||
common.LogDebug("解码pattern失败: " + decodeErr.Error())
|
||
return softMatch, decodeErr
|
||
}
|
||
|
||
patternUnescapedStr := string([]rune(string(patternUnescaped)))
|
||
patternCompiled, compileErr := regexp.Compile(patternUnescapedStr)
|
||
if compileErr != nil {
|
||
common.LogDebug("编译正则表达式失败: " + compileErr.Error())
|
||
return softMatch, compileErr
|
||
}
|
||
|
||
// 设置softMatch对象属性
|
||
softMatch.Service = directive.DirectiveName
|
||
softMatch.Pattern = pattern
|
||
softMatch.PatternCompiled = patternCompiled
|
||
softMatch.VersionInfo = versionInfo
|
||
|
||
common.LogDebug(fmt.Sprintf("解析softmatch成功: 服务=%s, Pattern=%s",
|
||
softMatch.Service, softMatch.Pattern))
|
||
return softMatch, nil
|
||
}
|
||
|
||
// containsPort 检查指定端口是否在探测器的端口范围内(私有方法)
|
||
func (p *Probe) containsPort(testPort int) bool {
|
||
common.LogDebug(fmt.Sprintf("检查端口 %d 是否在探测器端口范围内: %s", testPort, p.Ports))
|
||
|
||
// 检查单个端口
|
||
ports := strings.Split(p.Ports, ",")
|
||
for _, port := range ports {
|
||
port = strings.TrimSpace(port)
|
||
cmpPort, err := strconv.Atoi(port)
|
||
if err == nil && testPort == cmpPort {
|
||
common.LogDebug(fmt.Sprintf("端口 %d 匹配单个端口", testPort))
|
||
return true
|
||
}
|
||
}
|
||
|
||
// 检查端口范围
|
||
for _, port := range ports {
|
||
port = strings.TrimSpace(port)
|
||
if strings.Contains(port, "-") {
|
||
portRange := strings.Split(port, "-")
|
||
if len(portRange) != 2 {
|
||
common.LogDebug("无效的端口范围格式: " + port)
|
||
continue
|
||
}
|
||
|
||
start, err1 := strconv.Atoi(strings.TrimSpace(portRange[0]))
|
||
end, err2 := strconv.Atoi(strings.TrimSpace(portRange[1]))
|
||
|
||
if err1 != nil || err2 != nil {
|
||
common.LogDebug(fmt.Sprintf("解析端口范围失败: %s", port))
|
||
continue
|
||
}
|
||
|
||
if testPort >= start && testPort <= end {
|
||
common.LogDebug(fmt.Sprintf("端口 %d 在范围 %d-%d 内", testPort, start, end))
|
||
return true
|
||
}
|
||
}
|
||
}
|
||
|
||
common.LogDebug(fmt.Sprintf("端口 %d 不在探测器端口范围内", testPort))
|
||
return false
|
||
}
|
||
|
||
// MatchPattern 检查响应是否与匹配规则匹配
|
||
func (m *Match) MatchPattern(response []byte) bool {
|
||
if m.PatternCompiled == nil {
|
||
common.LogDebug("警告: 匹配规则的正则表达式未编译")
|
||
return false
|
||
}
|
||
|
||
matched := m.PatternCompiled.Match(response)
|
||
if matched {
|
||
// 提取匹配到的子组
|
||
submatches := m.PatternCompiled.FindStringSubmatch(string(response))
|
||
if len(submatches) > 1 {
|
||
m.FoundItems = submatches[1:] // 排除完整匹配,只保留分组
|
||
common.LogDebug(fmt.Sprintf("模式匹配成功,提取到 %d 个分组", len(m.FoundItems)))
|
||
} else {
|
||
common.LogDebug("模式匹配成功,但没有分组匹配")
|
||
}
|
||
}
|
||
|
||
return matched
|
||
}
|
||
|
||
// IsPortMatch 检查探测器是否适用于指定端口
|
||
func (p *Probe) IsPortMatch(port int) bool {
|
||
// 如果没有指定端口范围,认为适用于所有端口
|
||
if p.Ports == "" {
|
||
return true
|
||
}
|
||
|
||
return p.containsPort(port)
|
||
}
|
||
|