Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions internal/etw/source_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1089,6 +1089,27 @@ func testCallstackEnrichment(t *testing.T, hsnap handle.Snapshotter, psnap ps.Sn
},
false,
},
{
"virtual alloc callstack",
func() error {
_, err := windows.VirtualAlloc(0, 1024, windows.MEM_COMMIT|windows.MEM_RESERVE, windows.PAGE_EXECUTE_READ)
if err != nil {
return err
}
return nil
},
func(e *kevent.Kevent) bool {
if e.CurrentPid() && e.Type == ktypes.VirtualAlloc &&
e.GetParamAsString(kparams.MemAllocType) == "COMMIT|RESERVE" {
callstack := e.Callstack.String()
log.Infof("virtual alloc event %s: %s", e.String(), callstack)
return callstackContainsTestExe(callstack) &&
strings.Contains(strings.ToLower(callstack), strings.ToLower("\\Windows\\System32\\KernelBase.dll!VirtualAlloc"))
}
return false
},
false,
},
//{
// "copy file callstack",
// func() error {
Expand Down Expand Up @@ -1196,6 +1217,7 @@ func testCallstackEnrichment(t *testing.T, hsnap handle.Snapshotter, psnap ps.Sn
time.Sleep(time.Second * 5)

log.Infof("current process id is [%d]", os.Getpid())

for _, tt := range tests {
gen := tt.gen
log.Infof("executing [%s] test generator", tt.name)
Expand Down
20 changes: 14 additions & 6 deletions internal/etw/stackext.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,12 @@ func (s *StackExtensions) AddStackTracingWith(guid windows.GUID, hookID uint16)
// EventIds returns all event types eligible for stack tracing.
func (s *StackExtensions) EventIds() []etw.ClassicEventID { return s.ids }

// EnableProcessStackTracing populates the stack identifiers
// EnableProcessCallstack populates the stack identifiers
// with event types eligible for emitting stack walk events
// related to process telemetry, such as creating a process,
// creating/terminating a thread or loading an image into
// process address space.
func (s *StackExtensions) EnableProcessStackTracing() {
func (s *StackExtensions) EnableProcessCallstack() {
s.AddStackTracing(ktypes.CreateProcess)
if s.config.EnableThreadKevents {
s.AddStackTracing(ktypes.CreateThread)
Expand All @@ -70,25 +70,33 @@ func (s *StackExtensions) EnableProcessStackTracing() {
}
}

// EnableFileStackTracing populates the stack identifiers
// EnableFileCallstack populates the stack identifiers
// with event types eligible for publishing call stack
// return addresses for file system activity.
func (s *StackExtensions) EnableFileStackTracing() {
func (s *StackExtensions) EnableFileCallstack() {
if s.config.EnableFileIOKevents {
s.AddStackTracing(ktypes.CreateFile)
s.AddStackTracing(ktypes.DeleteFile)
s.AddStackTracing(ktypes.RenameFile)
}
}

// EnableRegistryStackTracing populates the stack identifiers
// EnableRegistryCallstack populates the stack identifiers
// with event types eligible for publishing call stack
// return addresses for registry operations.
func (s *StackExtensions) EnableRegistryStackTracing() {
func (s *StackExtensions) EnableRegistryCallstack() {
if s.config.EnableRegistryKevents {
s.AddStackTracing(ktypes.RegCreateKey)
s.AddStackTracing(ktypes.RegDeleteKey)
s.AddStackTracing(ktypes.RegSetValue)
s.AddStackTracing(ktypes.RegDeleteValue)
}
}

// EnableMemoryCallstack enables stack tracing for the memory
// events such as memory allocations.
func (s *StackExtensions) EnableMemoryCallstack() {
if s.config.EnableMemKevents {
s.AddStackTracing(ktypes.VirtualAlloc)
}
}
11 changes: 7 additions & 4 deletions internal/etw/stackext_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,22 +33,25 @@ func TestStackExtensions(t *testing.T) {
EnableThreadKevents: true,
EnableNetKevents: true,
EnableFileIOKevents: true,
EnableMemKevents: true,
BufferSize: 1024,
FlushTimer: time.Millisecond * 2300,
},
}
exts := NewStackExtensions(cfg.Kstream)
assert.Len(t, exts.EventIds(), 0)

exts.EnableProcessStackTracing()
exts.EnableRegistryStackTracing()
exts.EnableFileStackTracing()
exts.EnableProcessCallstack()
exts.EnableRegistryCallstack()
exts.EnableFileCallstack()
exts.EnableMemoryCallstack()

assert.Len(t, exts.EventIds(), 6)
assert.Len(t, exts.EventIds(), 7)
assert.Contains(t, exts.EventIds(), etw.ClassicEventID{GUID: ktypes.ProcessEventGUID, Type: uint8(ktypes.CreateProcess.HookID())})
assert.Contains(t, exts.EventIds(), etw.ClassicEventID{GUID: ktypes.ThreadEventGUID, Type: uint8(ktypes.CreateThread.HookID())})
assert.Contains(t, exts.EventIds(), etw.ClassicEventID{GUID: ktypes.ThreadEventGUID, Type: uint8(ktypes.TerminateThread.HookID())})
assert.Contains(t, exts.EventIds(), etw.ClassicEventID{GUID: ktypes.FileEventGUID, Type: uint8(ktypes.CreateFile.HookID())})
assert.Contains(t, exts.EventIds(), etw.ClassicEventID{GUID: ktypes.FileEventGUID, Type: uint8(ktypes.RenameFile.HookID())})
assert.Contains(t, exts.EventIds(), etw.ClassicEventID{GUID: ktypes.FileEventGUID, Type: uint8(ktypes.DeleteFile.HookID())})
assert.Contains(t, exts.EventIds(), etw.ClassicEventID{GUID: ktypes.MemEventGUID, Type: uint8(ktypes.VirtualAlloc.HookID())})
}
22 changes: 14 additions & 8 deletions internal/etw/trace.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,24 +125,30 @@ type Trace struct {
// NewTrace creates a new trace with specified name, provider GUID, and keywords.
func NewTrace(name string, guid windows.GUID, keywords uint64, config *config.Config) *Trace {
t := &Trace{Name: name, GUID: guid, Keywords: keywords, stackExtensions: NewStackExtensions(config.Kstream), config: config}
t.prepareStackTracing()
t.enableCallstacks()
return t
}

func (t *Trace) prepareStackTracing() {
func (t *Trace) enableCallstacks() {
if t.IsKernelTrace() {
t.stackExtensions.EnableProcessCallstack()

// Enabling stack tracing for kernel trace
// with granular system providers support.
// In this situation, only stack tracing for
// file system events is enabled
t.stackExtensions.EnableProcessStackTracing()
// In this situation, registry event callstacks
// are enabled if system provider support is not
// detected
if !SupportsSystemProviders() {
t.stackExtensions.EnableRegistryStackTracing()
t.stackExtensions.EnableRegistryCallstack()
}
t.stackExtensions.EnableFileStackTracing()

t.stackExtensions.EnableFileCallstack()

t.stackExtensions.EnableMemoryCallstack()
}

if t.IsSystemRegistryTrace() {
t.stackExtensions.EnableRegistryStackTracing()
t.stackExtensions.EnableRegistryCallstack()
}
}

Expand Down
5 changes: 4 additions & 1 deletion pkg/kevent/kevent_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,10 @@ func (e *Kevent) adjustPID() {
e.PID, _ = e.Kparams.GetPid()
}
case ktypes.File:
e.Tid, _ = e.Kparams.GetTid()
if !e.IsMapViewFile() && !e.IsUnmapViewFile() {
// take thread id from the event parameters
e.Tid, _ = e.Kparams.GetTid()
}
switch {
case e.InvalidPid() && e.Type == ktypes.MapFileRundown:
// a valid pid for map rundown events
Expand Down
3 changes: 2 additions & 1 deletion pkg/kevent/ktypes/ktypes_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -504,7 +504,8 @@ func (k Ktype) CanEnrichStack() bool {
RegSetValue,
RegDeleteValue,
DeleteFile,
RenameFile:
RenameFile,
VirtualAlloc:
return true
default:
return false
Expand Down
10 changes: 9 additions & 1 deletion pkg/symbolize/symbolizer.go
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,15 @@ func (s *Symbolizer) syncModules(e *kevent.Kevent) error {
func (s *Symbolizer) processCallstack(e *kevent.Kevent) error {
addrs := e.Kparams.MustGetSliceAddrs(kparams.Callstack)
e.Callstack.Init(len(addrs))
if (e.IsCreateFile() && e.IsOpenDisposition()) || (e.IsSystemPid() && !e.IsLoadImage()) {

// skip stack enrichment for the events generated by the System process
// except the LoadImage event which may prove to be useful when the driver
// is loaded and the kernel address symbolization is enabled
if e.IsSystemPid() && !e.IsLoadImage() {
return nil
}

if e.IsCreateFile() && e.IsOpenDisposition() {
// for high-volume events decorating
// the frames with symbol information
// is not viable. For this reason, the
Expand Down
Loading