github.com/chainreactors/fingers@v1.2.1/goby/goby.go (about)

     1  package goby
     2  
     3  import (
     4  	"bytes"
     5  	"github.com/chainreactors/fingers/common"
     6  	"github.com/chainreactors/fingers/resources"
     7  	"github.com/chainreactors/words/logic"
     8  	"strings"
     9  )
    10  
    11  func NewGobyEngine(data []byte) (*GobyEngine, error) {
    12  	var fingers []*GobyFinger
    13  	err := resources.UnmarshalData(data, &fingers)
    14  	if err != nil {
    15  		return nil, err
    16  	}
    17  	engine := &GobyEngine{
    18  		Fingers: fingers,
    19  	}
    20  	err = engine.Compile()
    21  	if err != nil {
    22  		return nil, err
    23  	}
    24  	return engine, nil
    25  }
    26  
    27  type GobyEngine struct {
    28  	Fingers []*GobyFinger
    29  }
    30  
    31  func (engine *GobyEngine) Name() string {
    32  	return "goby"
    33  }
    34  
    35  func (engine *GobyEngine) Len() int {
    36  	return len(engine.Fingers)
    37  }
    38  
    39  func (engine *GobyEngine) Compile() error {
    40  	for _, finger := range engine.Fingers {
    41  		err := finger.Compile()
    42  		if err != nil {
    43  			return err
    44  		}
    45  	}
    46  	return nil
    47  }
    48  
    49  // WebMatch 实现Web指纹匹配
    50  func (engine *GobyEngine) WebMatch(content []byte) common.Frameworks {
    51  	return engine.MatchRaw(string(bytes.ToLower(content)))
    52  }
    53  
    54  // ServiceMatch 实现Service指纹匹配 - goby不支持Service指纹
    55  func (engine *GobyEngine) ServiceMatch(host string, portStr string, level int, sender common.ServiceSender, callback common.ServiceCallback) *common.ServiceResult {
    56  	// goby不支持Service指纹识别
    57  	return nil
    58  }
    59  
    60  func (engine *GobyEngine) Capability() common.EngineCapability {
    61  	return common.EngineCapability{
    62  		SupportWeb:     true,  // goby支持Web指纹
    63  		SupportService: false, // goby不支持Service指纹
    64  	}
    65  }
    66  
    67  func (engine *GobyEngine) MatchRaw(raw string) common.Frameworks {
    68  	frames := make(common.Frameworks)
    69  	for _, finger := range engine.Fingers {
    70  		frame := finger.Match(raw)
    71  		if frame != nil {
    72  			frames.Add(frame)
    73  		}
    74  	}
    75  	return frames
    76  }
    77  
    78  type gobyRule struct {
    79  	Label   string `json:"label"`
    80  	Feature string `json:"feature"`
    81  	IsEquel bool   `json:"is_equal"` //是则判断条件相等,否则判断不等
    82  }
    83  
    84  type GobyFinger struct {
    85  	Logic     string `json:"logic"`
    86  	logicExpr *logic.Program
    87  	Name      string     `json:"name"`
    88  	Rule      []gobyRule `json:"rule"`
    89  }
    90  
    91  func (finger *GobyFinger) Compile() error {
    92  	for i, r := range finger.Rule {
    93  		// Fix bug: golang 不支持直接使用 `r.Feature` 的方式修改循环内的值
    94  		//r.Feature = strings.ToLower(r.Feature)
    95  		finger.Rule[i].Feature = strings.ToLower(r.Feature)
    96  	}
    97  
    98  	finger.logicExpr = logic.Compile(finger.Logic)
    99  	return nil
   100  }
   101  
   102  func (finger *GobyFinger) Match(raw string) *common.Framework {
   103  	env := make(map[string]bool)
   104  	for _, r := range finger.Rule {
   105  		match := strings.Contains(raw, r.Feature)
   106  		env[r.Label] = match == r.IsEquel
   107  	}
   108  
   109  	matched := logic.EvalLogic(finger.logicExpr, env)
   110  
   111  	if matched {
   112  		return common.NewFramework(finger.Name, common.FrameFromGoby)
   113  	}
   114  	return nil
   115  }