Skip to content

Commit ee4a3a3

Browse files
committed
feat(filter): Process token filter fields
Introduces the filter fields for the current, child, and parent process token integrity level, elevation type, and the elevation indicator (whether the process token was elevated or not).
1 parent 8d71b62 commit ee4a3a3

File tree

8 files changed

+241
-131
lines changed

8 files changed

+241
-131
lines changed

pkg/event/param_windows.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ func (p Param) String() string {
8282
if err != nil {
8383
return ""
8484
}
85-
if p.Name == params.ProcessIntegrityLevel {
85+
if p.Name == params.ProcessTokenIntegrityLevel {
8686
return sys.RidToString(sid)
8787
}
8888
return sid.String()
@@ -312,7 +312,7 @@ func (e *Event) produceParams(evt *etw.EventRecord) {
312312
e.AppendParam(params.ProcessFlags, params.Flags, flags, WithFlags(PsCreationFlags))
313313
e.AppendParam(params.ProcessTokenElevationType, params.Enum, tokenElevationType, WithEnum(PsTokenElevationTypes))
314314
e.AppendParam(params.ProcessTokenIsElevated, params.Bool, tokenIsElevated > 0)
315-
e.AppendParam(params.ProcessIntegrityLevel, params.SID, tokenMandatoryLabel)
315+
e.AppendParam(params.ProcessTokenIntegrityLevel, params.SID, tokenMandatoryLabel)
316316
e.AppendParam(params.Exe, params.DOSPath, exe)
317317
case OpenProcess:
318318
processID := evt.ReadUint32(0)

pkg/event/params/params_windows.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,8 @@ const (
5858
ExitStatus = "exit_status"
5959
// StartTime field denotes the process start time.
6060
StartTime = "start_time"
61-
// ProcessIntegrityLevel field denotes the process integrity level.
62-
ProcessIntegrityLevel = "integrity_level"
61+
// ProcessTokenIntegrityLevel field denotes the process integrity level.
62+
ProcessTokenIntegrityLevel = "token_integrity_level"
6363
// ProcessTokenElevationType field designates the process token elevation type.
6464
ProcessTokenElevationType = "token_elevation_type"
6565
// ProcessTokenIsElevated field designates if the process token is elevated.

pkg/filter/accessor_windows.go

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -430,11 +430,64 @@ func (ps *psAccessor) Get(f Field, e *event.Event) (params.Value, error) {
430430
return nil, ErrPsNil
431431
}
432432
return ps.IsProtected, nil
433+
case fields.PsChildTokenIntegrityLevel:
434+
if e.Category != event.Process {
435+
return nil, nil
436+
}
437+
return e.GetParamAsString(params.ProcessTokenIntegrityLevel), nil
438+
case fields.PsChildTokenIsElevated:
439+
if e.Category != event.Process {
440+
return nil, nil
441+
}
442+
return e.Params.GetBool(params.ProcessTokenIsElevated)
443+
case fields.PsChildTokenElevationType:
444+
if e.Category != event.Process {
445+
return nil, nil
446+
}
447+
return e.GetParamAsString(params.ProcessTokenElevationType), nil
448+
case fields.PsTokenIntegrityLevel:
449+
ps := e.PS
450+
if ps == nil {
451+
return nil, ErrPsNil
452+
}
453+
return ps.TokenIntegrityLevel, nil
454+
case fields.PsTokenElevationType:
455+
ps := e.PS
456+
if ps == nil {
457+
return nil, ErrPsNil
458+
}
459+
return ps.TokenElevationType, nil
460+
case fields.PsTokenIsElevated:
461+
ps := e.PS
462+
if ps == nil {
463+
return nil, ErrPsNil
464+
}
465+
return ps.IsTokenElevated, nil
466+
case fields.PsParentTokenIntegrityLevel:
467+
ps := getParentPs(e)
468+
if ps == nil {
469+
return nil, ErrPsNil
470+
}
471+
return ps.TokenIntegrityLevel, nil
472+
case fields.PsParentTokenElevationType:
473+
ps := getParentPs(e)
474+
if ps == nil {
475+
return nil, ErrPsNil
476+
}
477+
return ps.TokenElevationType, nil
478+
case fields.PsParentTokenIsElevated:
479+
ps := getParentPs(e)
480+
if ps == nil {
481+
return nil, ErrPsNil
482+
}
483+
return ps.IsTokenElevated, nil
433484
case fields.PsAncestors:
434485
if e.PS != nil {
435486
ancestors := make([]*pstypes.PS, 0)
436487
walk := func(proc *pstypes.PS) {
437-
ancestors = append(ancestors, proc)
488+
if proc != nil {
489+
ancestors = append(ancestors, proc)
490+
}
438491
}
439492
pstypes.Walk(walk, e.PS)
440493

@@ -474,7 +527,9 @@ func (ps *psAccessor) Get(f Field, e *event.Event) (params.Value, error) {
474527

475528
ancestors := make([]string, 0)
476529
walk := func(proc *pstypes.PS) {
477-
ancestors = append(ancestors, proc.Name)
530+
if proc != nil {
531+
ancestors = append(ancestors, proc.Name)
532+
}
478533
}
479534
pstypes.Walk(walk, e.PS)
480535

pkg/filter/fields/fields_windows.go

Lines changed: 110 additions & 77 deletions
Large diffs are not rendered by default.

pkg/filter/filter_test.go

Lines changed: 43 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -109,21 +109,6 @@ func TestStringFields(t *testing.T) {
109109
}
110110

111111
func TestProcFilter(t *testing.T) {
112-
pars := event.Params{
113-
params.Cmdline: {Name: params.Cmdline, Type: params.UnicodeString, Value: "C:\\Windows\\system32\\svchost-fake.exe -k RPCSS"},
114-
params.ProcessName: {Name: params.ProcessName, Type: params.AnsiString, Value: "svchost-fake.exe"},
115-
params.ProcessID: {Name: params.ProcessID, Type: params.PID, Value: uint32(1234)},
116-
params.ProcessParentID: {Name: params.ProcessParentID, Type: params.PID, Value: uint32(345)},
117-
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}},
118-
params.Username: {Name: params.Username, Type: params.UnicodeString, Value: "loki"},
119-
params.Domain: {Name: params.Domain, Type: params.UnicodeString, Value: "TITAN"},
120-
params.ProcessFlags: {Name: params.ProcessFlags, Type: params.Flags, Value: uint32(0x000000E)},
121-
}
122-
123-
pars1 := event.Params{
124-
params.DesiredAccess: {Name: params.DesiredAccess, Type: params.Flags, Value: uint32(0x1400), Flags: event.PsAccessRightFlags},
125-
}
126-
127112
ps1 := &pstypes.PS{
128113
Name: "wininit.exe",
129114
Username: "SYSTEM",
@@ -138,17 +123,32 @@ func TestProcFilter(t *testing.T) {
138123
Name: "System",
139124
},
140125
},
141-
IsWOW64: false,
142-
IsProtected: true,
143-
IsPackaged: false,
126+
IsWOW64: false,
127+
IsProtected: true,
128+
IsPackaged: false,
129+
TokenIntegrityLevel: "SYSTEM",
130+
IsTokenElevated: false,
131+
TokenElevationType: "DEFAULT",
144132
}
145133

146134
evt := &event.Event{
147135
Type: event.CreateProcess,
148136
Category: event.Process,
149-
Params: pars,
150-
Name: "CreateProcess",
151-
PID: 1023,
137+
Params: event.Params{
138+
params.Cmdline: {Name: params.Cmdline, Type: params.UnicodeString, Value: "C:\\Windows\\system32\\svchost-fake.exe -k RPCSS"},
139+
params.ProcessName: {Name: params.ProcessName, Type: params.AnsiString, Value: "svchost-fake.exe"},
140+
params.ProcessID: {Name: params.ProcessID, Type: params.PID, Value: uint32(1234)},
141+
params.ProcessParentID: {Name: params.ProcessParentID, Type: params.PID, Value: uint32(345)},
142+
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}},
143+
params.Username: {Name: params.Username, Type: params.UnicodeString, Value: "loki"},
144+
params.Domain: {Name: params.Domain, Type: params.UnicodeString, Value: "TITAN"},
145+
params.ProcessFlags: {Name: params.ProcessFlags, Type: params.Flags, Value: uint32(0x000000E)},
146+
params.ProcessTokenIntegrityLevel: {Name: params.ProcessTokenIntegrityLevel, Type: params.AnsiString, Value: "SYSTEM"},
147+
params.ProcessTokenIsElevated: {Name: params.ProcessTokenIsElevated, Type: params.Bool, Value: true},
148+
params.ProcessTokenElevationType: {Name: params.ProcessTokenElevationType, Type: params.AnsiString, Value: "FULL"},
149+
},
150+
Name: "CreateProcess",
151+
PID: 1023,
152152
PS: &pstypes.PS{
153153
Name: "svchost.exe",
154154
Cmdline: "C:\\Windows\\System32\\svchost.exe",
@@ -171,19 +171,24 @@ func TestProcFilter(t *testing.T) {
171171
{Size: 34545, BaseAddress: va.Address(144229524944769), Protection: 4653056, File: "C:\\Windows\\System32\\ucrtbase.dll", Type: "IMAGE"}, //EXECUTE_READWRITE|READONLY
172172
{Size: 4096, BaseAddress: va.Address(145229445447666), Protection: 12845056, Type: "PAGEFILE"}, // READWRITE 12845056
173173
},
174-
IsProtected: false,
175-
IsPackaged: true,
176-
IsWOW64: false,
174+
IsProtected: false,
175+
IsPackaged: true,
176+
IsWOW64: false,
177+
TokenIntegrityLevel: "SYSTEM",
178+
IsTokenElevated: false,
179+
TokenElevationType: "DEFAULT",
177180
},
178181
}
179182
evt.Timestamp, _ = time.Parse(time.RFC3339, "2011-05-03T15:04:05.323Z")
180183

181184
evt1 := &event.Event{
182185
Type: event.OpenProcess,
183186
Category: event.Process,
184-
Params: pars1,
185-
Name: "OpenProcess",
186-
PID: 1023,
187+
Params: event.Params{
188+
params.DesiredAccess: {Name: params.DesiredAccess, Type: params.Flags, Value: uint32(0x1400), Flags: event.PsAccessRightFlags},
189+
},
190+
Name: "OpenProcess",
191+
PID: 1023,
187192
PS: &pstypes.PS{
188193
Name: "svchost.exe",
189194
Parent: ps1,
@@ -240,6 +245,16 @@ func TestProcFilter(t *testing.T) {
240245
{`ps.parent.is_wow64`, false},
241246
{`ps.parent.is_packaged`, false},
242247
{`ps.parent.is_protected`, true},
248+
{`ps.token.integrity_level = 'SYSTEM'`, true},
249+
{`ps.token.is_elevated = false`, true},
250+
{`ps.token.elevation_type = 'DEFAULT'`, true},
251+
{`ps.child.token.integrity_level = 'SYSTEM'`, true},
252+
{`ps.child.token.is_elevated = true`, true},
253+
{`ps.child.token.elevation_type = 'FULL'`, true},
254+
{`ps.parent.token.integrity_level = 'SYSTEM'`, true},
255+
{`ps.parent.token.is_elevated = false`, true},
256+
{`ps.parent.token.elevation_type = 'DEFAULT'`, true},
257+
243258
{`evt.name = 'CreateProcess' and ps.name contains 'svchost'`, true},
244259

245260
{`ps.modules IN ('kernel32.dll')`, true},
@@ -262,6 +277,7 @@ func TestProcFilter(t *testing.T) {
262277
{`foreach(ps._ancestors, $proc, $proc.username = 'SYSTEM')`, true},
263278
{`foreach(ps._ancestors, $proc, $proc.domain = 'NT AUTHORITY')`, true},
264279
{`foreach(ps._ancestors, $proc, $proc.username = upper('system'))`, true},
280+
{`foreach(ps._ancestors, $proc, $proc.token.integrity_level = 'SYSTEM' and $proc.token.is_elevated = false and $proc.token.elevation_type = 'DEFAULT')`, true},
265281

266282
{`ps.args intersects ('-k', 'DcomLaunch')`, true},
267283
{`ps.args intersects ('-w', 'DcomLaunch')`, false},

pkg/filter/ql/function.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,12 @@ func (f *Foreach) procMapValuer(segments []*BoundSegmentLiteral, proc *pstypes.P
487487
valuer[key] = proc.Username
488488
case fields.DomainSegment:
489489
valuer[key] = proc.Domain
490+
case fields.TokenIntegrityLevelSegment:
491+
valuer[key] = proc.TokenIntegrityLevel
492+
case fields.TokenIsElevatedSegment:
493+
valuer[key] = proc.IsTokenElevated
494+
case fields.TokenElevationTypeSegment:
495+
valuer[key] = proc.TokenElevationType
490496
}
491497
}
492498
return valuer

pkg/ps/snapshotter_windows.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ func (s *snapshotter) Write(e *event.Event) error {
185185
e.AppendParam(params.Exe, params.Path, ps.Exe)
186186
}
187187

188-
e.AppendParam(params.ProcessIntegrityLevel, params.AnsiString, ps.TokenIntegrityLevel)
188+
e.AppendParam(params.ProcessTokenIntegrityLevel, params.AnsiString, ps.TokenIntegrityLevel)
189189
e.AppendParam(params.ProcessTokenElevationType, params.AnsiString, ps.TokenElevationType)
190190
e.AppendParam(params.ProcessTokenIsElevated, params.Bool, ps.IsTokenElevated)
191191

@@ -370,7 +370,7 @@ func (s *snapshotter) newProcState(pid, ppid uint32, e *event.Event) (*pstypes.P
370370
Ppid: ppid,
371371
Exe: e.GetParamAsString(params.Exe),
372372
Name: filepath.Base(e.GetParamAsString(params.Exe)),
373-
TokenIntegrityLevel: e.GetParamAsString(params.ProcessIntegrityLevel),
373+
TokenIntegrityLevel: e.GetParamAsString(params.ProcessTokenIntegrityLevel),
374374
TokenElevationType: e.GetParamAsString(params.ProcessTokenElevationType),
375375
IsTokenElevated: e.Params.TryGetBool(params.ProcessTokenIsElevated),
376376
Threads: make(map[uint32]pstypes.Thread),
@@ -460,7 +460,7 @@ func (s *snapshotter) newProcState(pid, ppid uint32, e *event.Event) (*pstypes.P
460460
proc.TokenIntegrityLevel = sys.RidToString(tokenMandatoryLabel.Label.Sid)
461461
proc.IsTokenElevated = token.IsElevated()
462462

463-
e.AppendParam(params.ProcessIntegrityLevel, params.AnsiString, proc.TokenIntegrityLevel)
463+
e.AppendParam(params.ProcessTokenIntegrityLevel, params.AnsiString, proc.TokenIntegrityLevel)
464464
e.AppendParam(params.ProcessTokenIsElevated, params.Bool, proc.IsTokenElevated)
465465
}
466466

pkg/ps/snapshotter_windows_test.go

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -200,12 +200,12 @@ func TestWriteInternalEventsEnrichment(t *testing.T) {
200200
{
201201
Type: event.CreateProcessInternal,
202202
Params: event.Params{
203-
params.ProcessID: {Name: params.ProcessID, Type: params.PID, Value: uint32(1024)},
204-
params.ProcessParentID: {Name: params.ProcessParentID, Type: params.PID, Value: uint32(444)},
205-
params.Exe: {Name: params.Exe, Type: params.UnicodeString, Value: `C:\Windows\System32\svchost.exe`},
206-
params.ProcessIntegrityLevel: {Name: params.ProcessIntegrityLevel, Type: params.AnsiString, Value: "HIGH"},
207-
params.ProcessTokenIsElevated: {Name: params.ProcessTokenIsElevated, Type: params.Bool, Value: true},
208-
params.ProcessTokenElevationType: {Name: params.ProcessTokenElevationType, Type: params.AnsiString, Value: "FULL"},
203+
params.ProcessID: {Name: params.ProcessID, Type: params.PID, Value: uint32(1024)},
204+
params.ProcessParentID: {Name: params.ProcessParentID, Type: params.PID, Value: uint32(444)},
205+
params.Exe: {Name: params.Exe, Type: params.UnicodeString, Value: `C:\Windows\System32\svchost.exe`},
206+
params.ProcessTokenIntegrityLevel: {Name: params.ProcessTokenIntegrityLevel, Type: params.AnsiString, Value: "HIGH"},
207+
params.ProcessTokenIsElevated: {Name: params.ProcessTokenIsElevated, Type: params.Bool, Value: true},
208+
params.ProcessTokenElevationType: {Name: params.ProcessTokenElevationType, Type: params.AnsiString, Value: "FULL"},
209209
},
210210
},
211211
},
@@ -236,12 +236,12 @@ func TestWriteInternalEventsEnrichment(t *testing.T) {
236236
{
237237
Type: event.CreateProcessInternal,
238238
Params: event.Params{
239-
params.ProcessID: {Name: params.ProcessID, Type: params.PID, Value: uint32(1024)},
240-
params.ProcessParentID: {Name: params.ProcessParentID, Type: params.PID, Value: uint32(444)},
241-
params.Exe: {Name: params.Exe, Type: params.UnicodeString, Value: `C:\Windows\System32\svchost.exe`},
242-
params.ProcessIntegrityLevel: {Name: params.ProcessIntegrityLevel, Type: params.AnsiString, Value: "HIGH"},
243-
params.ProcessTokenIsElevated: {Name: params.ProcessTokenIsElevated, Type: params.Bool, Value: true},
244-
params.ProcessTokenElevationType: {Name: params.ProcessTokenElevationType, Type: params.AnsiString, Value: "FULL"},
239+
params.ProcessID: {Name: params.ProcessID, Type: params.PID, Value: uint32(1024)},
240+
params.ProcessParentID: {Name: params.ProcessParentID, Type: params.PID, Value: uint32(444)},
241+
params.Exe: {Name: params.Exe, Type: params.UnicodeString, Value: `C:\Windows\System32\svchost.exe`},
242+
params.ProcessTokenIntegrityLevel: {Name: params.ProcessTokenIntegrityLevel, Type: params.AnsiString, Value: "HIGH"},
243+
params.ProcessTokenIsElevated: {Name: params.ProcessTokenIsElevated, Type: params.Bool, Value: true},
244+
params.ProcessTokenElevationType: {Name: params.ProcessTokenElevationType, Type: params.AnsiString, Value: "FULL"},
245245
},
246246
},
247247
},
@@ -262,12 +262,12 @@ func TestWriteInternalEventsEnrichment(t *testing.T) {
262262
{
263263
Type: event.CreateProcessInternal,
264264
Params: event.Params{
265-
params.ProcessID: {Name: params.ProcessID, Type: params.PID, Value: uint32(1024)},
266-
params.ProcessParentID: {Name: params.ProcessParentID, Type: params.PID, Value: uint32(444)},
267-
params.Exe: {Name: params.Exe, Type: params.UnicodeString, Value: `C:\Windows\System32\svchost.exe`},
268-
params.ProcessIntegrityLevel: {Name: params.ProcessIntegrityLevel, Type: params.AnsiString, Value: "HIGH"},
269-
params.ProcessTokenIsElevated: {Name: params.ProcessTokenIsElevated, Type: params.Bool, Value: true},
270-
params.ProcessTokenElevationType: {Name: params.ProcessTokenElevationType, Type: params.AnsiString, Value: "FULL"},
265+
params.ProcessID: {Name: params.ProcessID, Type: params.PID, Value: uint32(1024)},
266+
params.ProcessParentID: {Name: params.ProcessParentID, Type: params.PID, Value: uint32(444)},
267+
params.Exe: {Name: params.Exe, Type: params.UnicodeString, Value: `C:\Windows\System32\svchost.exe`},
268+
params.ProcessTokenIntegrityLevel: {Name: params.ProcessTokenIntegrityLevel, Type: params.AnsiString, Value: "HIGH"},
269+
params.ProcessTokenIsElevated: {Name: params.ProcessTokenIsElevated, Type: params.Bool, Value: true},
270+
params.ProcessTokenElevationType: {Name: params.ProcessTokenElevationType, Type: params.AnsiString, Value: "FULL"},
271271
},
272272
},
273273
{

0 commit comments

Comments
 (0)