Skip to content

Commit 01de00b

Browse files
committed
refactor(accessor): Lazy file information filter fields
1 parent 32a659c commit 01de00b

4 files changed

Lines changed: 139 additions & 14 deletions

File tree

pkg/filter/accessor_windows.go

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -716,12 +716,11 @@ func (l *fileAccessor) Get(f Field, e *event.Event) (params.Value, error) {
716716
return isLOLDriver(f.Name, e)
717717
}
718718
return false, nil
719-
case fields.FileIsDLL:
720-
return e.Params.GetBool(params.FileIsDLL)
721-
case fields.FileIsDriver:
722-
return e.Params.GetBool(params.FileIsDriver)
723-
case fields.FileIsExecutable:
724-
return e.Params.GetBool(params.FileIsExecutable)
719+
case fields.FileIsDLL, fields.FileIsDriver, fields.FileIsExecutable:
720+
if e.IsCreateDisposition() && e.IsSuccess() {
721+
return getFileInfo(f.Name, e)
722+
}
723+
return false, nil
725724
case fields.FilePID:
726725
return e.Params.GetPid()
727726
case fields.FileKey:
@@ -873,14 +872,13 @@ func (*moduleAccessor) Get(f Field, e *event.Event) (params.Value, error) {
873872
return isLOLDriver(f.Name, e)
874873
}
875874
return false, nil
876-
case fields.ImageIsDLL, fields.ModuleIsDLL:
877-
return e.Params.GetBool(params.FileIsDLL)
878-
case fields.ImageIsDriver, fields.ModuleIsDriver:
879-
return e.Params.GetBool(params.FileIsDriver)
880-
case fields.ImageIsExecutable, fields.ModuleIsExecutable:
881-
return e.Params.GetBool(params.FileIsExecutable)
882-
case fields.ImageIsDotnet, fields.ModuleIsDotnet, fields.DllIsDotnet:
883-
return e.Params.GetBool(params.FileIsDotnet)
875+
case fields.ImageIsDLL, fields.ModuleIsDLL, fields.ImageIsDriver,
876+
fields.ModuleIsDriver, fields.ImageIsExecutable, fields.ModuleIsExecutable,
877+
fields.ImageIsDotnet, fields.ModuleIsDotnet, fields.DllIsDotnet:
878+
if e.IsLoadImage() {
879+
return getFileInfo(f.Name, e)
880+
}
881+
return false, nil
884882
}
885883

886884
return nil, nil

pkg/filter/filter_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1016,6 +1016,7 @@ func TestModuleFilter(t *testing.T) {
10161016
{`module.signature.subject icontains 'Microsoft Corporation'`, true},
10171017
{`module.pe.is_dotnet`, false},
10181018
{`module.path.stem endswith 'System32\\kernel32'`, true},
1019+
{`module.is_dll`, true},
10191020
{`dll.path.stem endswith 'System32\\kernel32'`, true},
10201021
{`dll.signature.type = 'EMBEDDED'`, true},
10211022
{`dll.signature.level = 'AUTHENTICODE'`, true},

pkg/filter/util.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,15 @@ package filter
2020

2121
import (
2222
"encoding/hex"
23+
"fmt"
2324
"net"
2425
"path/filepath"
2526
"strings"
2627

2728
"github.com/rabbitstack/fibratus/pkg/event"
2829
"github.com/rabbitstack/fibratus/pkg/event/params"
2930
"github.com/rabbitstack/fibratus/pkg/filter/fields"
31+
"github.com/rabbitstack/fibratus/pkg/fs"
3032
"github.com/rabbitstack/fibratus/pkg/util/bytes"
3133
"github.com/rabbitstack/fibratus/pkg/util/loldrivers"
3234
"github.com/rabbitstack/fibratus/pkg/util/signature"
@@ -72,6 +74,53 @@ func initLOLDriversClient(flds []Field) {
7274
}
7375
}
7476

77+
// getFileInfo obtains the file information for created files and loaded modules.
78+
// Appends the file data to the event parameters, so subsequent field extractions
79+
// will already have the needed info.
80+
func getFileInfo(f fields.Field, e *event.Event) (params.Value, error) {
81+
switch f {
82+
case fields.FileIsDLL, fields.ImageIsDLL, fields.ModuleIsDLL:
83+
if e.Params.Contains(params.FileIsDLL) {
84+
return e.Params.GetBool(params.FileIsDLL)
85+
}
86+
case fields.FileIsDriver, fields.ModuleIsDriver, fields.ImageIsDriver:
87+
if e.Params.Contains(params.FileIsDriver) {
88+
return e.Params.GetBool(params.FileIsDriver)
89+
}
90+
case fields.FileIsExecutable, fields.ImageIsExecutable, fields.ModuleIsExecutable:
91+
if e.Params.Contains(params.FileIsExecutable) {
92+
return e.Params.GetBool(params.FileIsExecutable)
93+
}
94+
case fields.ImageIsDotnet, fields.ModuleIsDotnet, fields.DllIsDotnet:
95+
if e.Params.Contains(params.FileIsDotnet) {
96+
return e.Params.GetBool(params.FileIsDotnet)
97+
}
98+
}
99+
100+
fileinfo, err := fs.GetFileInfo(e.GetParamAsString(params.FilePath))
101+
if err != nil {
102+
return nil, err
103+
}
104+
105+
e.AppendParam(params.FileIsDLL, params.Bool, fileinfo.IsDLL)
106+
e.AppendParam(params.FileIsDriver, params.Bool, fileinfo.IsDriver)
107+
e.AppendParam(params.FileIsExecutable, params.Bool, fileinfo.IsExecutable)
108+
e.AppendParam(params.FileIsDotnet, params.Bool, fileinfo.IsDotnet)
109+
110+
switch f {
111+
case fields.FileIsDLL, fields.ImageIsDLL, fields.ModuleIsDLL:
112+
return fileinfo.IsDLL, nil
113+
case fields.FileIsDriver, fields.ModuleIsDriver, fields.ImageIsDriver:
114+
return fileinfo.IsDriver, nil
115+
case fields.FileIsExecutable, fields.ImageIsExecutable, fields.ModuleIsExecutable:
116+
return fileinfo.IsExecutable, nil
117+
case fields.ImageIsDotnet, fields.ModuleIsDotnet, fields.DllIsDotnet:
118+
return fileinfo.IsDotnet, nil
119+
}
120+
121+
return nil, fmt.Errorf("unexpected field: %s", f)
122+
}
123+
75124
// getSignature tries to find the module signature mapped to the given address.
76125
// If the signature is not found in the cache, then a fresh signature instance
77126
// is created and verified.

pkg/filter/util_test.go

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
* Copyright 2021-present by Nedim Sabic Sabic
3+
* https://www.fibratus.io
4+
* All Rights Reserved.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
package filter
20+
21+
import (
22+
"os"
23+
"path/filepath"
24+
"testing"
25+
26+
"github.com/rabbitstack/fibratus/pkg/event"
27+
"github.com/rabbitstack/fibratus/pkg/event/params"
28+
"github.com/rabbitstack/fibratus/pkg/filter/fields"
29+
"github.com/stretchr/testify/require"
30+
)
31+
32+
func TestGetFileInfo(t *testing.T) {
33+
path, err := os.Executable()
34+
require.NoError(t, err)
35+
36+
var tests = []struct {
37+
e *event.Event
38+
f func(*testing.T, *event.Event)
39+
fld fields.Field
40+
}{
41+
{
42+
e: &event.Event{
43+
Name: "CreateFile",
44+
Params: map[string]*event.Param{
45+
params.FilePath: {Name: params.FilePath, Type: params.UnicodeString, Value: path},
46+
},
47+
},
48+
f: func(t *testing.T, e *event.Event) {
49+
require.True(t, e.Params.MustGetBool(params.FileIsExecutable))
50+
},
51+
fld: fields.FileIsExecutable,
52+
},
53+
{
54+
e: &event.Event{
55+
Name: "CreateFile",
56+
Params: map[string]*event.Param{
57+
params.FilePath: {Name: params.FilePath, Type: params.UnicodeString, Value: filepath.Join(os.Getenv("SystemRoot"), "System32", "kernel32.dll")},
58+
},
59+
},
60+
f: func(t *testing.T, e *event.Event) {
61+
require.True(t, e.Params.MustGetBool(params.FileIsDLL))
62+
},
63+
fld: fields.ModuleIsDLL,
64+
},
65+
}
66+
67+
for _, tt := range tests {
68+
t.Run(tt.e.GetParamAsString(params.FilePath), func(t *testing.T) {
69+
v, err := getFileInfo(tt.fld, tt.e)
70+
require.NotNil(t, v)
71+
require.NoError(t, err)
72+
if tt.f != nil {
73+
tt.f(t, tt.e)
74+
}
75+
})
76+
}
77+
}

0 commit comments

Comments
 (0)