Skip to content

Commit 8df7d4f

Browse files
authored
fuzzy matching operator (#73)
1 parent 024efc4 commit 8df7d4f

File tree

5 files changed

+83
-7
lines changed

5 files changed

+83
-7
lines changed

go.mod

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ require (
99
github.com/hillu/go-yara/v4 v4.0.6
1010
github.com/inconshreveable/mousetrap v1.0.0 // indirect
1111
github.com/jedib0t/go-pretty/v6 v6.2.1
12+
github.com/lithammer/fuzzysearch v1.1.2
1213
github.com/magiconair/properties v1.8.1
1314
github.com/mitchellh/mapstructure v1.4.1
1415
github.com/olivere/elastic/v7 v7.0.20
@@ -26,7 +27,7 @@ require (
2627
github.com/valyala/gozstd v1.6.4
2728
github.com/xeipuuv/gojsonschema v1.2.0
2829
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b
29-
golang.org/x/text v0.3.2
30+
golang.org/x/text v0.3.5
3031
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
3132
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
3233
gopkg.in/natefinch/lumberjack.v2 v2.0.0

go.sum

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
9797
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
9898
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
9999
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
100+
github.com/lithammer/fuzzysearch v1.1.2 h1:ePUtm14xKxbpCxozcFbIDRtvANxnVnE+RKpJUqkr2gA=
101+
github.com/lithammer/fuzzysearch v1.1.2/go.mod h1:v6tYW/9kpfV6LNcweXdSjQsfCku/1M/oObmSox1fzP8=
100102
github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
101103
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
102104
github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA=
@@ -238,8 +240,9 @@ golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7w
238240
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b h1:ag/x1USPSsqHud38I9BAC88qdNLDHHtQ4mlgQIZPPNA=
239241
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
240242
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
241-
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
242243
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
244+
golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ=
245+
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
243246
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
244247
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
245248
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=

pkg/filter/filter_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,11 @@ func TestFilterRunFileKevent(t *testing.T) {
192192
{`file.name iendswith ('.EXE', 'KERNEL32.dll', 'user32.dll')`, true},
193193
{`file.name istartswith ('C:\\WINDOWS', 'KERNEL32.dll', 'user32.dll')`, true},
194194
{`file.name iin ('C:\\WINDOWS\\system32\\user32.dll')`, true},
195+
{`file.name fuzzy 'C:\\Windows\\system32\\ser3ll'`, true},
196+
{`file.name ifuzzy 'C:\\WINDOWS\\sYS\\ser3ll'`, true},
197+
{`file.name ifuzzy 'C:\\WINDOWS\\sYS\\32dll'`, true},
198+
{`file.name fuzzy ('C:\\Windows\\system32\\kernel', 'C:\\Windows\\system32\\ser3ll')`, true},
199+
{`file.name ifuzzynorm 'C:\\WINDOWS\\sÝS\\32dll'`, true},
195200
}
196201

197202
for i, tt := range tests {

pkg/filter/ql/ast.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
package ql
2222

2323
import (
24+
fuzzysearch "github.com/lithammer/fuzzysearch/fuzzy"
2425
"github.com/rabbitstack/fibratus/pkg/util/wildcard"
2526
"net"
2627
"strconv"
@@ -803,6 +804,62 @@ func (v *ValuerEval) evalBinaryExpr(expr *BinaryExpr) interface{} {
803804
default:
804805
return false
805806
}
807+
case fuzzy:
808+
switch rhs := rhs.(type) {
809+
case string:
810+
return fuzzysearch.Match(rhs, lhs)
811+
case []string:
812+
for _, s := range rhs {
813+
if fuzzysearch.Match(s, lhs) {
814+
return true
815+
}
816+
}
817+
return false
818+
default:
819+
return false
820+
}
821+
case ifuzzy:
822+
switch rhs := rhs.(type) {
823+
case string:
824+
return fuzzysearch.MatchFold(rhs, lhs)
825+
case []string:
826+
for _, s := range rhs {
827+
if fuzzysearch.MatchFold(s, lhs) {
828+
return true
829+
}
830+
}
831+
return false
832+
default:
833+
return false
834+
}
835+
case fuzzynorm:
836+
switch rhs := rhs.(type) {
837+
case string:
838+
return fuzzysearch.MatchNormalized(rhs, lhs)
839+
case []string:
840+
for _, s := range rhs {
841+
if fuzzysearch.MatchNormalized(s, lhs) {
842+
return true
843+
}
844+
}
845+
return false
846+
default:
847+
return false
848+
}
849+
case ifuzzynorm:
850+
switch rhs := rhs.(type) {
851+
case string:
852+
return fuzzysearch.MatchNormalizedFold(rhs, lhs)
853+
case []string:
854+
for _, s := range rhs {
855+
if fuzzysearch.MatchNormalizedFold(s, lhs) {
856+
return true
857+
}
858+
}
859+
return false
860+
default:
861+
return false
862+
}
806863
}
807864
case net.IP:
808865
switch expr.Op {

pkg/filter/ql/token.go

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,16 @@ const (
5252
not // not
5353
contains // contains
5454
icontains // icontains
55-
startswith // startswith
5655
istartswith // istartswith
57-
iendswith // iendswith
56+
startswith // startswith
5857
endswith // endswith
58+
iendswith // iendswith
5959
matches // matches
6060
imatches // imatches
61+
fuzzy // fuzzy
62+
ifuzzy // ifuzzy
63+
fuzzynorm // fuzzynorm
64+
ifuzzynorm // ifuzzynorm
6165
eq // =
6266
neq // !=
6367
lt // <
@@ -76,7 +80,9 @@ var keywords map[string]token
7680

7781
func init() {
7882
keywords = make(map[string]token)
79-
for _, tok := range []token{and, or, contains, icontains, in, iin, not, startswith, istartswith, endswith, iendswith, matches, imatches} {
83+
for _, tok := range []token{and, or, contains, icontains, in,
84+
iin, not, startswith, istartswith, endswith, iendswith,
85+
matches, imatches, fuzzy, ifuzzy, fuzzynorm, ifuzzynorm} {
8086
keywords[strings.ToLower(tokens[tok])] = tok
8187
}
8288
keywords["true"] = truet
@@ -114,6 +120,10 @@ var tokens = [...]string{
114120
iendswith: "IENDSWITH",
115121
matches: "MATCHES",
116122
imatches: "IMATCHES",
123+
fuzzy: "FUZZY",
124+
ifuzzy: "IFUZZY",
125+
fuzzynorm: "FUZZYNORM",
126+
ifuzzynorm: "IFUZZYNORM",
117127

118128
eq: "=",
119129
neq: "!=",
@@ -150,8 +160,8 @@ func (tok token) precedence() int {
150160
return 3
151161
case eq, neq, lt, lte, gt, gte:
152162
return 4
153-
case in, iin, contains, icontains, startswith, istartswith,
154-
endswith, iendswith, matches, imatches:
163+
case in, iin, contains, icontains, startswith, istartswith, endswith, iendswith,
164+
matches, imatches, fuzzy, ifuzzy, fuzzynorm, ifuzzynorm:
155165
return 5
156166
}
157167
return 0

0 commit comments

Comments
 (0)