dddd/lib/gonmap/type-probe.go
SleepingBag945 01e7d0b159 dddd
2023-08-18 08:55:46 +02:00

181 lines
4.7 KiB
Go
Executable File
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 gonmap
import (
"errors"
"fmt"
"github.com/lcvvvv/gonmap/simplenet"
"regexp"
"strconv"
"strings"
"time"
)
type probe struct {
//探针级别
rarity int
//探针名称
name string
//探针适用默认端口号
ports PortList
//探针适用SSL端口号
sslports PortList
//totalwaitms time.Duration
//tcpwrappedms time.Duration
//探针对应指纹库
matchGroup []*match
//探针指纹库若匹配失败则会尝试使用fallback指定探针的指纹库
fallback string
//探针发送协议类型
protocol string
//探针发送数据
sendRaw string
}
func (p *probe) scan(host string, port int, tls bool, timeout time.Duration, size int) (string, bool, error) {
uri := fmt.Sprintf("%s:%d", host, port)
sendRaw := strings.Replace(p.sendRaw, "{Host}", fmt.Sprintf("%s:%d", host, port), -1)
text, err := simplenet.Send(p.protocol, tls, uri, sendRaw, timeout, size)
if err == nil {
return text, tls, nil
}
if strings.Contains(err.Error(), "STEP1") && tls == true {
text, err := simplenet.Send(p.protocol, false, uri, p.sendRaw, timeout, size)
return text, false, err
}
return text, tls, err
}
func (p *probe) match(s string) *FingerPrint {
var f = &FingerPrint{}
var softFilter string
for _, m := range p.matchGroup {
//实现软筛选
if softFilter != "" {
if m.service != softFilter {
continue
}
}
//logger.Println("开始匹配正则:", m.service, m.patternRegexp.String())
if m.patternRegexp.MatchString(s) {
//标记当前正则
f.MatchRegexString = m.patternRegexp.String()
if m.soft {
//如果为软捕获,这设置筛选器
f.Service = m.service
softFilter = m.service
continue
} else {
//如果为硬捕获则直接获取指纹信息
m.makeVersionInfo(s, f)
f.Service = m.service
return f
}
}
}
return f
}
var probeExprRegx = regexp.MustCompile("^(UDP|TCP) ([a-zA-Z0-9-_./]+) (?:q\\|([^|]*)\\|)$")
var probeIntRegx = regexp.MustCompile(`^(\d+)$`)
var probeStrRegx = regexp.MustCompile(`^([a-zA-Z0-9-_./]+)$`)
func parseProbe(lines []string) *probe {
var p = &probe{}
p.ports = emptyPortList
p.sslports = emptyPortList
for _, line := range lines {
p.loadLine(line)
}
return p
}
func (p *probe) loadLine(s string) {
//分解命令
i := strings.Index(s, " ")
commandName := s[:i]
commandArgs := s[i+1:]
//逐行处理
switch commandName {
case "Probe":
p.loadProbe(commandArgs)
case "match":
p.loadMatch(commandArgs, false)
case "softmatch":
p.loadMatch(commandArgs, true)
case "ports":
p.loadPorts(commandArgs, false)
case "sslports":
p.loadPorts(commandArgs, true)
case "totalwaitms":
//p.totalwaitms = time.Duration(p.getInt(commandArgs)) * time.Millisecond
case "tcpwrappedms":
//p.tcpwrappedms = time.Duration(p.getInt(commandArgs)) * time.Millisecond
case "rarity":
p.rarity = p.getInt(commandArgs)
case "fallback":
p.fallback = p.getString(commandArgs)
}
}
func (p *probe) loadProbe(s string) {
//Probe <protocol> <probename> <probestring>
if !probeExprRegx.MatchString(s) {
panic(errors.New("probe 语句格式不正确"))
}
args := probeExprRegx.FindStringSubmatch(s)
if args[1] == "" || args[2] == "" {
panic(errors.New("probe 参数格式不正确"))
}
p.protocol = args[1]
p.name = args[1] + "_" + args[2]
str := args[3]
str = strings.ReplaceAll(str, `\0`, `\x00`)
str = strings.ReplaceAll(str, `"`, `${double-quoted}`)
str = `"` + str + `"`
str, _ = strconv.Unquote(str)
str = strings.ReplaceAll(str, `${double-quoted}`, `"`)
p.sendRaw = str
}
func (p *probe) loadMatch(s string, soft bool) {
//"match": misc.MakeRegexpCompile("^([a-zA-Z0-9-_./]+) m\\|([^|]+)\\|([is]{0,2}) (.*)$"),
//match <Service> <pattern>|<patternopt> [<versioninfo>]
// "matchVersioninfoProductname": misc.MakeRegexpCompile("p/([^/]+)/"),
// "matchVersioninfoVersion": misc.MakeRegexpCompile("v/([^/]+)/"),
// "matchVersioninfoInfo": misc.MakeRegexpCompile("i/([^/]+)/"),
// "matchVersioninfoHostname": misc.MakeRegexpCompile("h/([^/]+)/"),
// "matchVersioninfoOS": misc.MakeRegexpCompile("o/([^/]+)/"),
// "matchVersioninfoDevice": misc.MakeRegexpCompile("d/([^/]+)/"),
p.matchGroup = append(p.matchGroup, parseMatch(s, soft))
}
func (p *probe) loadPorts(expr string, ssl bool) {
if ssl {
p.sslports = parsePortList(expr)
} else {
p.ports = parsePortList(expr)
}
}
func (p *probe) getInt(expr string) int {
if !probeIntRegx.MatchString(expr) {
panic(errors.New("totalwaitms or tcpwrappedms 语句参数不正确"))
}
i, _ := strconv.Atoi(probeIntRegx.FindStringSubmatch(expr)[1])
return i
}
func (p *probe) getString(expr string) string {
if !probeStrRegx.MatchString(expr) {
panic(errors.New("fallback 语句参数不正确"))
}
return probeStrRegx.FindStringSubmatch(expr)[1]
}