Skip to content

Commit 78d8b87

Browse files
committed
feat(filter): Add evt.is_direct_syscall and evt.is_indirect_syscall fields
1 parent 0ea43fd commit 78d8b87

File tree

9 files changed

+65
-25
lines changed

9 files changed

+65
-25
lines changed

internal/evasion/direct_syscall.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,7 @@ func (d *directSyscall) Eval(e *event.Event) (bool, error) {
6868
}
6969

7070
func (*directSyscall) Type() Type { return DirectSyscall }
71+
72+
func (*directSyscall) SetMask(e *event.Event) {
73+
e.Evasions |= uint32(DirectSyscall)
74+
}

internal/evasion/indirect_syscall.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,3 +160,7 @@ func (i *indirectSyscall) Eval(e *event.Event) (bool, error) {
160160
}
161161

162162
func (*indirectSyscall) Type() Type { return IndirectSyscall }
163+
164+
func (*indirectSyscall) SetMask(e *event.Event) {
165+
e.Evasions |= uint32(IndirectSyscall)
166+
}

internal/evasion/scanner.go

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,19 +35,21 @@ var evasionsCount expvar.Map
3535
// that yields the evasion techniques, such as direct syscall.
3636
type Scanner struct {
3737
evasions []Evasion
38+
config Config
3839
}
3940

4041
// NewScanner instantiates the new evasion scanner.
4142
func NewScanner(config Config) *Scanner {
4243
s := &Scanner{
4344
evasions: make([]Evasion, 0),
45+
config: config,
4446
}
4547

4648
if config.EnableDirectSyscall {
47-
s.registerEvasion(NewDirectSyscall())
49+
s.addEvasion(NewDirectSyscall())
4850
}
4951
if config.EnableIndirectSyscall {
50-
s.registerEvasion(NewIndirectSyscall())
52+
s.addEvasion(NewIndirectSyscall())
5153
}
5254

5355
return s
@@ -71,8 +73,9 @@ func (s *Scanner) ProcessEvent(e *event.Event) (bool, error) {
7173
}
7274
if matches {
7375
enq = true
74-
e.AddSliceMetaOrAppend(event.EvasionsKey, evasion.Type().String())
76+
evasion.SetMask(e)
7577
evasionsCount.Add(evasion.Type().String(), 1)
78+
e.AddOrAppendMetaSlice(event.EvasionsKey, evasion.Type().String())
7679
log.Debugf("detected evasion %q on event [%s] and callstack [%s]", evasion.Type(), e, e.Callstack)
7780
}
7881
}
@@ -82,6 +85,8 @@ func (s *Scanner) ProcessEvent(e *event.Event) (bool, error) {
8285

8386
func (s *Scanner) CanEnqueue() bool { return false }
8487

85-
func (s *Scanner) registerEvasion(evasion Evasion) {
86-
s.evasions = append(s.evasions, evasion)
88+
func (s *Scanner) addEvasion(evasion Evasion) {
89+
if s.config.Enabled {
90+
s.evasions = append(s.evasions, evasion)
91+
}
8792
}

internal/evasion/scanner_test.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,15 @@
1919
package evasion
2020

2121
import (
22+
"strings"
23+
"testing"
24+
"time"
25+
2226
"github.com/rabbitstack/fibratus/pkg/callstack"
2327
"github.com/rabbitstack/fibratus/pkg/event"
2428
"github.com/rabbitstack/fibratus/pkg/event/params"
2529
"github.com/rabbitstack/fibratus/pkg/fs"
2630
"github.com/stretchr/testify/require"
27-
"strings"
28-
"testing"
29-
"time"
3031
)
3132

3233
func TestScannerProcessEvent(t *testing.T) {
@@ -66,6 +67,7 @@ func TestScannerProcessEvent(t *testing.T) {
6667
require.NoError(t, err)
6768
require.True(t, matches && len(tt.expectedEvasions) > 0)
6869
if len(tt.expectedEvasions) > 0 {
70+
require.True(t, tt.evt.Evasions&uint32(DirectSyscall) != 0)
6971
require.True(t, tt.evt.ContainsMeta(event.EvasionsKey))
7072
require.Equal(t, tt.expectedEvasions, tt.evt.GetMeta(event.EvasionsKey).([]string))
7173
}

internal/evasion/types.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@ package evasion
2121
import "github.com/rabbitstack/fibratus/pkg/event"
2222

2323
// Type is the alias for the evasion technique type.
24-
type Type uint8
24+
type Type uint32
2525

2626
const (
2727
// DirectSyscall represents the direct syscall evasion.
28-
DirectSyscall Type = iota
28+
DirectSyscall Type = 1 << iota
2929
// IndirectSyscall represents the indirect syscall evasion.
3030
IndirectSyscall
3131
)
@@ -47,8 +47,10 @@ type Evasion interface {
4747
// Eval executes the evasion logic. The evasion detector usually accesses
4848
// the callstack from the given event to determine if any evasions are
4949
// performed on behalf of the process. If the evasion is recognized, this
50-
// method return true, or false otherwise.
50+
// method returns true, or false otherwise.
5151
Eval(*event.Event) (bool, error)
5252
// Type returns the type of the evasion technique.
5353
Type() Type
54+
// SetMask sets the type in the event evasions bitmask.
55+
SetMask(*event.Event)
5456
}

pkg/event/event.go

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,14 @@ package event
2020

2121
import (
2222
"fmt"
23+
"strings"
24+
"sync"
25+
"time"
26+
2327
"github.com/rabbitstack/fibratus/pkg/callstack"
2428
capver "github.com/rabbitstack/fibratus/pkg/cap/version"
2529
"github.com/rabbitstack/fibratus/pkg/event/params"
2630
pstypes "github.com/rabbitstack/fibratus/pkg/ps/types"
27-
"strings"
28-
"sync"
29-
"time"
3031
)
3132

3233
// TimestampFormat is the Go valid format for the event timestamp
@@ -73,6 +74,8 @@ type Event struct {
7374
PID uint32 `json:"pid"`
7475
// Tid is the thread identifier of the thread that generated the event.
7576
Tid uint32 `json:"tid"`
77+
// Evasions is the bitmask that stores detected evasion types on this event.
78+
Evasions uint32 `json:"-"`
7679
// Type is the internal representation of the event. This field should be ignored by serializers.
7780
Type Type `json:"-"`
7881
// CPU designates the processor logical core where the event was originated.
@@ -245,9 +248,9 @@ func (e *Event) AddMeta(k MetadataKey, v any) {
245248
e.Metadata[k] = v
246249
}
247250

248-
// AddSliceMetaOrAppend puts the provided string into the slice if the key
251+
// AddOrAppendMetaSlice puts the provided string into the slice if the key
249252
// doesn't exist or appends the string to the slice.
250-
func (e *Event) AddSliceMetaOrAppend(k MetadataKey, s string) {
253+
func (e *Event) AddOrAppendMetaSlice(k MetadataKey, s string) {
251254
if e.ContainsMeta(k) {
252255
v := append(e.GetMeta(k).([]string), s)
253256
e.AddMeta(k, v)

pkg/filter/accessor.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,14 @@ package filter
2020

2121
import (
2222
"errors"
23-
"github.com/rabbitstack/fibratus/pkg/event"
24-
"github.com/rabbitstack/fibratus/pkg/event/params"
25-
"github.com/rabbitstack/fibratus/pkg/filter/fields"
2623
"net"
2724
"reflect"
2825
"time"
26+
27+
"github.com/rabbitstack/fibratus/internal/evasion"
28+
"github.com/rabbitstack/fibratus/pkg/event"
29+
"github.com/rabbitstack/fibratus/pkg/event/params"
30+
"github.com/rabbitstack/fibratus/pkg/filter/fields"
2931
)
3032

3133
var (
@@ -136,6 +138,10 @@ func (*evtAccessor) Get(f Field, evt *event.Event) (params.Value, error) {
136138
default:
137139
return evt.GetParamAsString(name), nil
138140
}
141+
case fields.EvtIsDirectSyscall:
142+
return evt.Evasions&uint32(evasion.DirectSyscall) != 0, nil
143+
case fields.EvtIsIndirectSyscall:
144+
return evt.Evasions&uint32(evasion.IndirectSyscall) != 0, nil
139145
}
140146

141147
return nil, nil

pkg/filter/fields/fields_windows.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,12 @@ const (
362362
EvtNparams Field = "evt.nparams"
363363
// EvtArg represents the field sequence for generic argument access
364364
EvtArg Field = "evt.arg"
365+
// EvtIsDirectSyscall represents the field that designates if this event is
366+
// performing a direct syscall.
367+
EvtIsDirectSyscall Field = "evt.is_direct_syscall"
368+
// EvtIsIndirectSyscall represents the field that designates if this event is
369+
// performing an indirect syscall.
370+
EvtIsIndirectSyscall Field = "evt.is_indirect_syscall"
365371

366372
// KevtSeq is the event sequence number
367373
KevtSeq Field = "kevt.seq"
@@ -839,6 +845,9 @@ var fields = map[Field]FieldInfo{
839845
}
840846
return true
841847
}}},
848+
EvtIsDirectSyscall: {EvtIsDirectSyscall, "indicates if the event is performing a direct syscall", params.Bool, []string{"evt.is_direct_syscall = true"}, nil, nil},
849+
EvtIsIndirectSyscall: {EvtIsIndirectSyscall, "indicates if the event is performing an indirect syscall", params.Bool, []string{"evt.is_indirect_syscall = true"}, nil, nil},
850+
842851
KevtSeq: {KevtSeq, "event sequence number", params.Uint64, []string{"kevt.seq > 666"}, &Deprecation{Since: "3.0.0", Fields: []Field{EvtSeq}}, nil},
843852
KevtPID: {KevtPID, "process identifier generating the event", params.Uint32, []string{"kevt.pid = 6"}, &Deprecation{Since: "3.0.0", Fields: []Field{EvtPID}}, nil},
844853
KevtTID: {KevtTID, "thread identifier generating the event", params.Uint32, []string{"kevt.tid = 1024"}, &Deprecation{Since: "3.0.0", Fields: []Field{EvtTID}}, nil},

pkg/filter/filter_test.go

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,15 @@
1919
package filter
2020

2121
import (
22+
"net"
23+
"os"
24+
"path/filepath"
25+
"testing"
26+
"time"
27+
"unsafe"
28+
2229
"github.com/rabbitstack/fibratus/internal/etw/processors"
30+
"github.com/rabbitstack/fibratus/internal/evasion"
2331
"github.com/rabbitstack/fibratus/pkg/callstack"
2432
"github.com/rabbitstack/fibratus/pkg/config"
2533
"github.com/rabbitstack/fibratus/pkg/event"
@@ -36,12 +44,6 @@ import (
3644
"github.com/stretchr/testify/assert"
3745
"github.com/stretchr/testify/require"
3846
"golang.org/x/sys/windows"
39-
"net"
40-
"os"
41-
"path/filepath"
42-
"testing"
43-
"time"
44-
"unsafe"
4547
)
4648

4749
var cfg = &config.Config{
@@ -747,6 +749,7 @@ func TestEventFilter(t *testing.T) {
747749
Category: event.File,
748750
Host: "archrabbit",
749751
Description: "Creates or opens a new file, directory, I/O device, pipe, console",
752+
Evasions: uint32(evasion.IndirectSyscall),
750753
Params: event.Params{
751754
params.ProcessID: {Name: params.ProcessID, Type: params.PID, Value: uint32(3434)},
752755
params.FileObject: {Name: params.FileObject, Type: params.Uint64, Value: uint64(12456738026482168384)},
@@ -775,6 +778,8 @@ func TestEventFilter(t *testing.T) {
775778
{`evt.arg[file_path] = '\\Device\\HarddiskVolume2\\Windows\\system32\\user32.dll'`, true},
776779
{`evt.arg[type] = 'file'`, true},
777780
{`evt.arg[pid] = 3434`, true},
781+
{`evt.is_direct_syscall = false`, true},
782+
{`evt.is_indirect_syscall`, true},
778783

779784
{`evt.desc contains 'Creates or opens a new file'`, true},
780785

0 commit comments

Comments
 (0)