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) }