Skip to content

Commit e7f3867

Browse files
committed
feat(filter): Add evt.is_direct_syscall and evt.is_indirect_syscall fields
1 parent 396bf3d commit e7f3867

File tree

9 files changed

+63
-23
lines changed

9 files changed

+63
-23
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
@@ -159,3 +159,7 @@ func (i *indirectSyscall) Eval(e *event.Event) (bool, error) {
159159
}
160160

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

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: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,12 @@ package filter
2020

2121
import (
2222
"errors"
23+
"reflect"
24+
25+
"github.com/rabbitstack/fibratus/internal/evasion"
2326
"github.com/rabbitstack/fibratus/pkg/event"
2427
"github.com/rabbitstack/fibratus/pkg/event/params"
2528
"github.com/rabbitstack/fibratus/pkg/filter/fields"
26-
"reflect"
2729
)
2830

2931
var (
@@ -134,6 +136,10 @@ func (k *evtAccessor) Get(f Field, evt *event.Event) (params.Value, error) {
134136
default:
135137
return evt.GetParamAsString(name), nil
136138
}
139+
case fields.EvtIsDirectSyscall:
140+
return evt.Evasions&uint32(evasion.DirectSyscall) != 0, nil
141+
case fields.EvtIsIndirectSyscall:
142+
return evt.Evasions&uint32(evasion.IndirectSyscall) != 0, nil
137143
}
138144

139145
return nil, nil

pkg/filter/fields/fields_windows.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,12 @@ const (
344344
EvtNparams Field = "evt.nparams"
345345
// EvtArg represents the field sequence for generic argument access
346346
EvtArg Field = "evt.arg"
347+
// EvtIsDirectSyscall represents the field that designates if this event is
348+
// performing a direct syscall.
349+
EvtIsDirectSyscall Field = "evt.is_direct_syscall"
350+
// EvtIsIndirectSyscall represents the field that designates if this event is
351+
// performing an indirect syscall.
352+
EvtIsIndirectSyscall Field = "evt.is_indirect_syscall"
347353

348354
// KevtSeq is the event sequence number
349355
KevtSeq Field = "kevt.seq"
@@ -812,6 +818,9 @@ var fields = map[Field]FieldInfo{
812818
}
813819
return true
814820
}}},
821+
EvtIsDirectSyscall: {EvtIsDirectSyscall, "indicates if the event is performing a direct syscall", params.Bool, []string{"evt.is_direct_syscall = true"}, nil, nil},
822+
EvtIsIndirectSyscall: {EvtIsIndirectSyscall, "indicates if the event is performing an indirect syscall", params.Bool, []string{"evt.is_indirect_syscall = true"}, nil, nil},
823+
815824
KevtSeq: {KevtSeq, "event sequence number", params.Uint64, []string{"kevt.seq > 666"}, &Deprecation{Since: "3.0.0", Fields: []Field{EvtSeq}}, nil},
816825
KevtPID: {KevtPID, "process identifier generating the event", params.Uint32, []string{"kevt.pid = 6"}, &Deprecation{Since: "3.0.0", Fields: []Field{EvtPID}}, nil},
817826
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{
@@ -701,6 +703,7 @@ func TestEventFilter(t *testing.T) {
701703
Category: event.File,
702704
Host: "archrabbit",
703705
Description: "Creates or opens a new file, directory, I/O device, pipe, console",
706+
Evasions: uint32(evasion.IndirectSyscall),
704707
Params: event.Params{
705708
params.ProcessID: {Name: params.ProcessID, Type: params.PID, Value: uint32(3434)},
706709
params.FileObject: {Name: params.FileObject, Type: params.Uint64, Value: uint64(12456738026482168384)},
@@ -729,6 +732,8 @@ func TestEventFilter(t *testing.T) {
729732
{`evt.arg[file_path] = '\\Device\\HarddiskVolume2\\Windows\\system32\\user32.dll'`, true},
730733
{`evt.arg[type] = 'file'`, true},
731734
{`evt.arg[pid] = 3434`, true},
735+
{`evt.is_direct_syscall = false`, true},
736+
{`evt.is_indirect_syscall`, true},
732737

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

0 commit comments

Comments
 (0)