Skip to content

Commit 3302398

Browse files
committed
fix(ps): Make executable path assignation more robust
Introduce a new metadata attribute in the process state to distinguish how the initial process state is created - either from internal event or system logger. This attribute is utilized in the state machine to set the correct executable path.
1 parent 11ab687 commit 3302398

File tree

3 files changed

+28
-16
lines changed

3 files changed

+28
-16
lines changed

pkg/ps/snapshotter_windows.go

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,16 @@ package ps
2020

2121
import (
2222
"expvar"
23-
"github.com/rabbitstack/fibratus/pkg/sys"
24-
"github.com/rabbitstack/fibratus/pkg/util/va"
25-
"golang.org/x/sys/windows"
2623
"path/filepath"
2724
"strconv"
2825
"strings"
2926
"sync"
3027
"time"
3128

29+
"github.com/rabbitstack/fibratus/pkg/sys"
30+
"github.com/rabbitstack/fibratus/pkg/util/va"
31+
"golang.org/x/sys/windows"
32+
3233
"github.com/rabbitstack/fibratus/pkg/config"
3334
"github.com/rabbitstack/fibratus/pkg/event"
3435
"github.com/rabbitstack/fibratus/pkg/event/params"
@@ -161,25 +162,25 @@ func (s *snapshotter) Write(e *event.Event) error {
161162
if ps := s.procs[pid]; ps == nil && (e.IsCreateProcessInternal() || e.IsProcessRundownInternal()) {
162163
// only modify the state if there is no process derived from the NT kernel logger process events
163164
s.procs[pid] = proc
164-
} else if ps, ok := s.procs[pid]; ok && (e.IsCreateProcessInternal() || e.IsProcessRundownInternal()) {
165+
} else if ps, ok := s.procs[pid]; ok && (e.IsCreateProcessInternal() || e.IsProcessRundownInternal()) && ps.IsCreatedFromSystemLogger {
165166
// process state derived from the core kernel events exists - enrich it
166167
ps.TokenIntegrityLevel = proc.TokenIntegrityLevel
167168
ps.TokenElevationType = proc.TokenElevationType
168169
ps.IsTokenElevated = proc.IsTokenElevated
169-
if len(proc.Exe) > len(ps.Exe) {
170+
if strings.EqualFold(ps.Name, filepath.Base(proc.Exe)) && len(proc.Exe) > len(ps.Exe) {
170171
// prefer full executable path
171172
ps.Exe = proc.Exe
172173
}
173174
s.procs[pid] = ps
174-
} else if ps, ok := s.procs[pid]; ok && (e.IsCreateProcess() || e.IsProcessRundown()) && ps.TokenIntegrityLevel != "" {
175+
} else if ps, ok := s.procs[pid]; ok && (e.IsCreateProcess() || e.IsProcessRundown()) && !ps.IsCreatedFromSystemLogger {
175176
// enrich the existing process state with the newly arrived NT kernel logger process events
176177
// but obtain the integrity level and executable path from the previous proc state
177178
processEnrichments.Add(1)
178179
proc.TokenIntegrityLevel = ps.TokenIntegrityLevel
179180
proc.TokenElevationType = ps.TokenElevationType
180181
proc.IsTokenElevated = ps.IsTokenElevated
181182

182-
if len(ps.Exe) > len(proc.Exe) {
183+
if strings.EqualFold(proc.Name, filepath.Base(ps.Exe)) && len(ps.Exe) > len(proc.Exe) {
183184
// prefer full executable path
184185
proc.Exe = ps.Exe
185186
e.AppendParam(params.Exe, params.Path, ps.Exe)
@@ -397,6 +398,7 @@ func (s *snapshotter) newProcState(pid, ppid uint32, e *event.Event) (*pstypes.P
397398
proc.IsWOW64 = (e.Params.MustGetUint32(params.ProcessFlags) & event.PsWOW64) != 0
398399
proc.IsPackaged = (e.Params.MustGetUint32(params.ProcessFlags) & event.PsPackaged) != 0
399400
proc.IsProtected = (e.Params.MustGetUint32(params.ProcessFlags) & event.PsProtected) != 0
401+
proc.IsCreatedFromSystemLogger = true
400402

401403
if !s.capture {
402404
if proc.Username != "" {

pkg/ps/snapshotter_windows_test.go

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@
1919
package ps
2020

2121
import (
22+
"os"
23+
"path/filepath"
24+
"strings"
25+
"testing"
26+
"time"
27+
2228
"github.com/rabbitstack/fibratus/pkg/config"
2329
"github.com/rabbitstack/fibratus/pkg/event"
2430
"github.com/rabbitstack/fibratus/pkg/event/params"
@@ -31,11 +37,6 @@ import (
3137
"github.com/stretchr/testify/mock"
3238
"github.com/stretchr/testify/require"
3339
"golang.org/x/sys/windows"
34-
"os"
35-
"path/filepath"
36-
"strings"
37-
"testing"
38-
"time"
3940
)
4041

4142
func TestWrite(t *testing.T) {
@@ -227,6 +228,7 @@ func TestWriteInternalEventsEnrichment(t *testing.T) {
227228
params.ProcessID: {Name: params.ProcessID, Type: params.PID, Value: uint32(1024)},
228229
params.ProcessParentID: {Name: params.ProcessParentID, Type: params.PID, Value: uint32(444)},
229230
params.Exe: {Name: params.Exe, Type: params.UnicodeString, Value: `svchost.exe`},
231+
params.ProcessName: {Name: params.ProcessName, Type: params.UnicodeString, Value: `svchost.exe`},
230232
params.Cmdline: {Name: params.Cmdline, Type: params.UnicodeString, Value: `svchost.exe -k LocalSystemNetworkRestricted -p -s NcbService`},
231233
params.UserSID: {Name: params.UserSID, Type: params.WbemSID, Value: []byte{224, 8, 226, 31, 15, 167, 255, 255, 0, 0, 0, 0, 15, 167, 255, 255, 1, 1, 0, 0, 0, 0, 0, 5, 18, 0, 0, 0}},
232234
params.SessionID: {Name: params.SessionID, Type: params.Uint32, Value: uint32(1)},
@@ -265,6 +267,7 @@ func TestWriteInternalEventsEnrichment(t *testing.T) {
265267
params.ProcessID: {Name: params.ProcessID, Type: params.PID, Value: uint32(1024)},
266268
params.ProcessParentID: {Name: params.ProcessParentID, Type: params.PID, Value: uint32(444)},
267269
params.Exe: {Name: params.Exe, Type: params.UnicodeString, Value: `C:\Windows\System32\svchost.exe`},
270+
params.ProcessName: {Name: params.ProcessName, Type: params.UnicodeString, Value: `svchost.exe`},
268271
params.ProcessTokenIntegrityLevel: {Name: params.ProcessTokenIntegrityLevel, Type: params.AnsiString, Value: "HIGH"},
269272
params.ProcessTokenIsElevated: {Name: params.ProcessTokenIsElevated, Type: params.Bool, Value: true},
270273
params.ProcessTokenElevationType: {Name: params.ProcessTokenElevationType, Type: params.AnsiString, Value: "FULL"},
@@ -275,6 +278,7 @@ func TestWriteInternalEventsEnrichment(t *testing.T) {
275278
Params: event.Params{
276279
params.ProcessID: {Name: params.ProcessID, Type: params.PID, Value: uint32(1024)},
277280
params.ProcessParentID: {Name: params.ProcessParentID, Type: params.PID, Value: uint32(444)},
281+
params.ProcessName: {Name: params.ProcessName, Type: params.UnicodeString, Value: `svchost.exe`},
278282
params.Exe: {Name: params.Exe, Type: params.UnicodeString, Value: `svchost.exe`},
279283
params.Cmdline: {Name: params.Cmdline, Type: params.UnicodeString, Value: `svchost.exe -k LocalSystemNetworkRestricted -p -s NcbService`},
280284
params.UserSID: {Name: params.UserSID, Type: params.WbemSID, Value: []byte{224, 8, 226, 31, 15, 167, 255, 255, 0, 0, 0, 0, 15, 167, 255, 255, 1, 1, 0, 0, 0, 0, 0, 5, 18, 0, 0, 0}},
@@ -303,6 +307,7 @@ func TestWriteInternalEventsEnrichment(t *testing.T) {
303307
params.ProcessID: {Name: params.ProcessID, Type: params.PID, Value: uint32(os.Getpid())},
304308
params.ProcessParentID: {Name: params.ProcessParentID, Type: params.PID, Value: uint32(444)},
305309
params.Exe: {Name: params.Exe, Type: params.UnicodeString, Value: `svchost.exe`},
310+
params.ProcessName: {Name: params.ProcessName, Type: params.UnicodeString, Value: `svchost.exe`},
306311
params.Cmdline: {Name: params.Cmdline, Type: params.UnicodeString, Value: `svchost.exe -k LocalSystemNetworkRestricted -p -s NcbService`},
307312
params.UserSID: {Name: params.UserSID, Type: params.WbemSID, Value: []byte{224, 8, 226, 31, 15, 167, 255, 255, 0, 0, 0, 0, 15, 167, 255, 255, 1, 1, 0, 0, 0, 0, 0, 5, 18, 0, 0, 0}},
308313
params.SessionID: {Name: params.SessionID, Type: params.Uint32, Value: uint32(1)},

pkg/ps/types/types_windows.go

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,20 +21,22 @@ package types
2121
import (
2222
"encoding/binary"
2323
"fmt"
24+
"path/filepath"
25+
"strings"
26+
"sync"
27+
2428
"github.com/rabbitstack/fibratus/pkg/sys"
2529
"github.com/rabbitstack/fibratus/pkg/util/cmdline"
2630
"github.com/rabbitstack/fibratus/pkg/util/va"
2731
"golang.org/x/sys/windows"
28-
"path/filepath"
29-
"strings"
30-
"sync"
3132

3233
"github.com/rabbitstack/fibratus/pkg/cap/section"
3334
htypes "github.com/rabbitstack/fibratus/pkg/handle/types"
3435
"github.com/rabbitstack/fibratus/pkg/pe"
3536

36-
"github.com/rabbitstack/fibratus/pkg/util/bootid"
3737
"time"
38+
39+
"github.com/rabbitstack/fibratus/pkg/util/bootid"
3840
)
3941

4042
// PS encapsulates process' state such as allocated resources and other metadata.
@@ -98,6 +100,9 @@ type PS struct {
98100
TokenElevationType string `json:"token_elevation_type"`
99101
// IsTokenElevated indicates if the process token is elevated.
100102
IsTokenElevated bool `json:"is_token_elevated"`
103+
// IsCreatedFromSystemLogger is the metadata attribute that indicates if the
104+
// process state is created from the event published by the NT kernel logger.
105+
IsCreatedFromSystemLogger bool `json:"-"`
101106
}
102107

103108
// UUID is meant to offer a more robust version of process ID that

0 commit comments

Comments
 (0)