package portfinger import ( "fmt" "strconv" "strings" "github.com/shadow1ng/fscan/common" ) // 解析指令语法,返回指令结构 func (p *Probe) getDirectiveSyntax(data string) (directive Directive) { common.LogDebug("开始解析指令语法,输入数据: " + data) directive = Directive{} // 查找第一个空格的位置 blankIndex := strings.Index(data, " ") if blankIndex == -1 { common.LogDebug("未找到空格分隔符") return directive } // 解析各个字段 directiveName := data[:blankIndex] Flag := data[blankIndex+1 : blankIndex+2] delimiter := data[blankIndex+2 : blankIndex+3] directiveStr := data[blankIndex+3:] directive.DirectiveName = directiveName directive.Flag = Flag directive.Delimiter = delimiter directive.DirectiveStr = directiveStr common.LogDebug(fmt.Sprintf("指令解析结果: 名称=%s, 标志=%s, 分隔符=%s, 内容=%s", directiveName, Flag, delimiter, directiveStr)) return directive } // 解析探测器信息 func (p *Probe) parseProbeInfo(probeStr string) { common.LogDebug("开始解析探测器信息,输入字符串: " + probeStr) // 提取协议和其他信息 proto := probeStr[:4] other := probeStr[4:] // 验证协议类型 if !(proto == "TCP " || proto == "UDP ") { errMsg := "探测器协议必须是 TCP 或 UDP" common.LogDebug("错误: " + errMsg) panic(errMsg) } // 验证其他信息不为空 if len(other) == 0 { errMsg := "nmap-service-probes - 探测器名称无效" common.LogDebug("错误: " + errMsg) panic(errMsg) } // 解析指令 directive := p.getDirectiveSyntax(other) // 设置探测器属性 p.Name = directive.DirectiveName p.Data = strings.Split(directive.DirectiveStr, directive.Delimiter)[0] p.Protocol = strings.ToLower(strings.TrimSpace(proto)) common.LogDebug(fmt.Sprintf("探测器解析完成: 名称=%s, 数据=%s, 协议=%s", p.Name, p.Data, p.Protocol)) } // 从字符串解析探测器信息 func (p *Probe) fromString(data string) error { common.LogDebug("开始解析探测器字符串数据") var err error // 预处理数据 data = strings.TrimSpace(data) lines := strings.Split(data, "\n") if len(lines) == 0 { return fmt.Errorf("输入数据为空") } probeStr := lines[0] p.parseProbeInfo(probeStr) // 解析匹配规则和其他配置 var matchs []Match for _, line := range lines { common.LogDebug("处理行: " + line) switch { case strings.HasPrefix(line, "match "): match, err := p.getMatch(line) if err != nil { common.LogDebug("解析match失败: " + err.Error()) continue } matchs = append(matchs, match) case strings.HasPrefix(line, "softmatch "): softMatch, err := p.getSoftMatch(line) if err != nil { common.LogDebug("解析softmatch失败: " + err.Error()) continue } matchs = append(matchs, softMatch) case strings.HasPrefix(line, "ports "): p.parsePorts(line) case strings.HasPrefix(line, "sslports "): p.parseSSLPorts(line) case strings.HasPrefix(line, "totalwaitms "): p.parseTotalWaitMS(line) case strings.HasPrefix(line, "tcpwrappedms "): p.parseTCPWrappedMS(line) case strings.HasPrefix(line, "rarity "): p.parseRarity(line) case strings.HasPrefix(line, "fallback "): p.parseFallback(line) } } p.Matchs = &matchs common.LogDebug(fmt.Sprintf("解析完成,共有 %d 个匹配规则", len(matchs))) return err } // 解析端口配置 func (p *Probe) parsePorts(data string) { p.Ports = data[len("ports")+1:] common.LogDebug("解析端口: " + p.Ports) } // 解析SSL端口配置 func (p *Probe) parseSSLPorts(data string) { p.SSLPorts = data[len("sslports")+1:] common.LogDebug("解析SSL端口: " + p.SSLPorts) } // 解析总等待时间 func (p *Probe) parseTotalWaitMS(data string) { waitMS, err := strconv.Atoi(strings.TrimSpace(data[len("totalwaitms")+1:])) if err != nil { common.LogDebug("解析总等待时间失败: " + err.Error()) return } p.TotalWaitMS = waitMS common.LogDebug(fmt.Sprintf("总等待时间: %d ms", waitMS)) } // 解析TCP包装等待时间 func (p *Probe) parseTCPWrappedMS(data string) { wrappedMS, err := strconv.Atoi(strings.TrimSpace(data[len("tcpwrappedms")+1:])) if err != nil { common.LogDebug("解析TCP包装等待时间失败: " + err.Error()) return } p.TCPWrappedMS = wrappedMS common.LogDebug(fmt.Sprintf("TCP包装等待时间: %d ms", wrappedMS)) } // 解析稀有度 func (p *Probe) parseRarity(data string) { rarity, err := strconv.Atoi(strings.TrimSpace(data[len("rarity")+1:])) if err != nil { common.LogDebug("解析稀有度失败: " + err.Error()) return } p.Rarity = rarity common.LogDebug(fmt.Sprintf("稀有度: %d", rarity)) } // 解析回退配置 func (p *Probe) parseFallback(data string) { p.Fallback = data[len("fallback")+1:] common.LogDebug("回退配置: " + p.Fallback) } // 从内容解析探测器规则 func (v *VScan) parseProbesFromContent(content string) { common.LogDebug("开始解析探测器规则文件内容") var probes []Probe var lines []string // 过滤注释和空行 linesTemp := strings.Split(content, "\n") for _, lineTemp := range linesTemp { lineTemp = strings.TrimSpace(lineTemp) if lineTemp == "" || strings.HasPrefix(lineTemp, "#") { continue } lines = append(lines, lineTemp) } // 验证文件内容 if len(lines) == 0 { errMsg := "读取nmap-service-probes文件失败: 内容为空" common.LogDebug("错误: " + errMsg) panic(errMsg) } // 检查Exclude指令 excludeCount := 0 for _, line := range lines { if strings.HasPrefix(line, "Exclude ") { excludeCount++ } if excludeCount > 1 { errMsg := "nmap-service-probes文件中只允许有一个Exclude指令" common.LogDebug("错误: " + errMsg) panic(errMsg) } } // 验证第一行格式 firstLine := lines[0] if !(strings.HasPrefix(firstLine, "Exclude ") || strings.HasPrefix(firstLine, "Probe ")) { errMsg := "解析错误: 首行必须以\"Probe \"或\"Exclude \"开头" common.LogDebug("错误: " + errMsg) panic(errMsg) } // 处理Exclude指令 if excludeCount == 1 { v.Exclude = firstLine[len("Exclude")+1:] lines = lines[1:] common.LogDebug("解析到Exclude规则: " + v.Exclude) } // 合并内容并分割探测器 content = "\n" + strings.Join(lines, "\n") probeParts := strings.Split(content, "\nProbe")[1:] // 解析每个探测器 for _, probePart := range probeParts { probe := Probe{} if err := probe.fromString(probePart); err != nil { common.LogDebug(fmt.Sprintf("解析探测器失败: %v", err)) continue } probes = append(probes, probe) } v.AllProbes = probes common.LogDebug(fmt.Sprintf("成功解析 %d 个探测器规则", len(probes))) } // 将探测器转换为名称映射 func (v *VScan) parseProbesToMapKName() { common.LogDebug("开始构建探测器名称映射") v.ProbesMapKName = map[string]Probe{} for _, probe := range v.AllProbes { v.ProbesMapKName[probe.Name] = probe common.LogDebug("添加探测器映射: " + probe.Name) } } // 设置使用的探测器 func (v *VScan) SetusedProbes() { common.LogDebug("开始设置要使用的探测器") for _, probe := range v.AllProbes { if strings.ToLower(probe.Protocol) == "tcp" { if probe.Name == "SSLSessionReq" { common.LogDebug("跳过 SSLSessionReq 探测器") continue } v.Probes = append(v.Probes, probe) common.LogDebug("添加TCP探测器: " + probe.Name) // 特殊处理TLS会话请求 if probe.Name == "TLSSessionReq" { sslProbe := v.ProbesMapKName["SSLSessionReq"] v.Probes = append(v.Probes, sslProbe) common.LogDebug("为TLSSessionReq添加SSL探测器") } } else { v.UdpProbes = append(v.UdpProbes, probe) common.LogDebug("添加UDP探测器: " + probe.Name) } } common.LogDebug(fmt.Sprintf("探测器设置完成,TCP: %d个, UDP: %d个", len(v.Probes), len(v.UdpProbes))) }