Skip to content

Commit 8e81077

Browse files
committed
feat(event): Append callstack for OpenProcess/OpenThread events
The callstack is included in the event parameters. For the sake of performance, we're deriving the callstack only for the interesting flag set.
1 parent 9df026f commit 8e81077

File tree

3 files changed

+55
-2
lines changed

3 files changed

+55
-2
lines changed

internal/etw/source_test.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1183,6 +1183,40 @@ func testCallstackEnrichment(t *testing.T, hsnap handle.Snapshotter, psnap ps.Sn
11831183
},
11841184
false,
11851185
},
1186+
{
1187+
"open process callstack",
1188+
func() error {
1189+
_, err := windows.OpenProcess(windows.PROCESS_VM_READ, false, uint32(os.Getpid()))
1190+
return err
1191+
},
1192+
func(e *kevent.Kevent) bool {
1193+
if e.CurrentPid() && e.Type == ktypes.OpenProcess {
1194+
callstack := e.Callstack.String()
1195+
log.Infof("open process event %s: %s", e.String(), callstack)
1196+
return callstackContainsTestExe(callstack) &&
1197+
strings.Contains(strings.ToLower(callstack), strings.ToLower("\\WINDOWS\\System32\\KERNELBASE.dll!OpenProcess"))
1198+
}
1199+
return false
1200+
},
1201+
false,
1202+
},
1203+
{
1204+
"open thread callstack",
1205+
func() error {
1206+
_, err := windows.OpenThread(windows.THREAD_IMPERSONATE, false, windows.GetCurrentThreadId())
1207+
return err
1208+
},
1209+
func(e *kevent.Kevent) bool {
1210+
if e.CurrentPid() && e.Type == ktypes.OpenThread {
1211+
callstack := e.Callstack.String()
1212+
log.Infof("open thread event %s: %s", e.String(), callstack)
1213+
return callstackContainsTestExe(callstack) &&
1214+
strings.Contains(strings.ToLower(callstack), strings.ToLower("\\WINDOWS\\System32\\KERNELBASE.dll!OpenThread"))
1215+
}
1216+
return false
1217+
},
1218+
false,
1219+
},
11861220
}
11871221

11881222
kstreamConfig := config.KstreamConfig{

pkg/kevent/flags.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,12 @@ var PsCreationFlags = []ParamFlag{
7676
{"PACKAGED", PsPackaged},
7777
}
7878

79+
// AllAccess represents the maximum process/thread access right
80+
const AllAccess = windows.STANDARD_RIGHTS_REQUIRED | windows.SYNCHRONIZE | 0xFFFF
81+
7982
// PsAccessRightFlags describes flags for the process access rights.
8083
var PsAccessRightFlags = []ParamFlag{
81-
{"ALL_ACCESS", windows.STANDARD_RIGHTS_REQUIRED | windows.SYNCHRONIZE | 0xFFFF},
84+
{"ALL_ACCESS", AllAccess},
8285
{"DELETE", windows.DELETE},
8386
{"READ_CONTROL", windows.READ_CONTROL},
8487
{"SYNCHRONIZE", windows.SYNCHRONIZE},
@@ -102,7 +105,7 @@ var PsAccessRightFlags = []ParamFlag{
102105

103106
// ThreadAccessRightFlags describes flags for the thread access rights.
104107
var ThreadAccessRightFlags = []ParamFlag{
105-
{"ALL_ACCESS", windows.STANDARD_RIGHTS_REQUIRED | windows.SYNCHRONIZE | 0xFFFF},
108+
{"ALL_ACCESS", AllAccess},
106109
{"DELETE", windows.DELETE},
107110
{"READ_CONTROL", windows.READ_CONTROL},
108111
{"SYNCHRONIZE", windows.SYNCHRONIZE},

pkg/kevent/kparam_windows.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,14 @@ func (e *Kevent) produceParams(evt *etw.EventRecord) {
269269
e.AppendParam(kparams.ProcessID, kparams.PID, processID)
270270
e.AppendParam(kparams.DesiredAccess, kparams.Flags, desiredAccess, WithFlags(PsAccessRightFlags))
271271
e.AppendParam(kparams.NTStatus, kparams.Status, status)
272+
273+
// append callstack for interested flags
274+
if desiredAccess == AllAccess || ((desiredAccess & windows.PROCESS_VM_READ) != 0) || ((desiredAccess & windows.PROCESS_VM_WRITE) != 0) ||
275+
((desiredAccess & windows.PROCESS_VM_OPERATION) != 0) || ((desiredAccess & windows.PROCESS_DUP_HANDLE) != 0) ||
276+
((desiredAccess & windows.PROCESS_TERMINATE) != 0) || ((desiredAccess & windows.PROCESS_CREATE_PROCESS) != 0) ||
277+
((desiredAccess & windows.PROCESS_CREATE_THREAD) != 0) || ((desiredAccess & windows.PROCESS_SET_INFORMATION) != 0) {
278+
e.AppendParam(kparams.Callstack, kparams.Slice, evt.Callstack())
279+
}
272280
case ktypes.CreateThread,
273281
ktypes.TerminateThread,
274282
ktypes.ThreadRundown:
@@ -323,6 +331,14 @@ func (e *Kevent) produceParams(evt *etw.EventRecord) {
323331
e.AppendParam(kparams.ThreadID, kparams.TID, threadID)
324332
e.AppendParam(kparams.DesiredAccess, kparams.Flags, desiredAccess, WithFlags(ThreadAccessRightFlags))
325333
e.AppendParam(kparams.NTStatus, kparams.Status, status)
334+
335+
// append callstack for interested flags
336+
if desiredAccess == AllAccess || ((desiredAccess & windows.THREAD_SET_CONTEXT) != 0) || ((desiredAccess & windows.THREAD_SET_THREAD_TOKEN) != 0) ||
337+
((desiredAccess & windows.THREAD_IMPERSONATE) != 0) || ((desiredAccess & windows.THREAD_DIRECT_IMPERSONATION) != 0) ||
338+
((desiredAccess & windows.THREAD_SUSPEND_RESUME) != 0) || ((desiredAccess & windows.THREAD_TERMINATE) != 0) ||
339+
((desiredAccess & windows.THREAD_SET_INFORMATION) != 0) {
340+
e.AppendParam(kparams.Callstack, kparams.Slice, evt.Callstack())
341+
}
326342
case ktypes.SetThreadContext:
327343
status := evt.ReadUint32(0)
328344
e.AppendParam(kparams.NTStatus, kparams.Status, status)

0 commit comments

Comments
 (0)