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
4 changes: 1 addition & 3 deletions internal/etw/processors/registry_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,7 @@ func (r *registryProcessor) processEvent(e *kevent.Kevent) (*kevent.Kevent, erro
switch e.Type {
case ktypes.RegKCBRundown, ktypes.RegCreateKCB:
khandle := e.Kparams.MustGetUint64(kparams.RegKeyHandle)
if _, ok := r.keys[khandle]; !ok {
r.keys[khandle], _ = e.Kparams.GetString(kparams.RegPath)
}
r.keys[khandle] = e.Kparams.MustGetString(kparams.RegPath)
kcbCount.Add(1)
case ktypes.RegDeleteKCB:
khandle := e.Kparams.MustGetUint64(kparams.RegKeyHandle)
Expand Down
21 changes: 0 additions & 21 deletions internal/etw/source.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,16 +71,6 @@ var (
buffersRead = expvar.NewInt("kstream.kbuffers.read")
)

// SupportsSystemProviders determines if the support for granular
// system providers in present.
func SupportsSystemProviders() bool {
maj, _, patch := windows.RtlGetNtVersionNumbers()
if maj > 10 {
return true
}
return maj >= 10 && patch >= 20348
}

// EventSource is the core component responsible for
// starting ETW tracing sessions and setting up event
// consumers.
Expand Down Expand Up @@ -177,13 +167,6 @@ func (e *EventSource) Open(config *config.Config) error {

e.addTrace(etw.KernelLoggerSession, etw.KernelTraceControlGUID)

if SupportsSystemProviders() && !config.IsCaptureSet() {
log.Info("system providers support detected")
if config.Kstream.EnableRegistryKevents {
e.addTraceKeywords(etw.SystemRegistrySession, etw.SystemRegistryProviderID, etw.RegistryKeywordGeneral)
}
}

if config.Kstream.EnableDNSEvents {
e.addTrace(etw.DNSClientSession, etw.DNSClientGUID)
}
Expand Down Expand Up @@ -321,7 +304,3 @@ func (e *EventSource) RegisterEventListener(lis kevent.Listener) {
func (e *EventSource) addTrace(name string, guid windows.GUID) {
e.traces = append(e.traces, NewTrace(name, guid, 0x0, e.config))
}

func (e *EventSource) addTraceKeywords(name string, guid windows.GUID, keywords uint64) {
e.traces = append(e.traces, NewTrace(name, guid, keywords, e.config))
}
24 changes: 8 additions & 16 deletions internal/etw/source_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,21 +127,17 @@ func TestEventSourceStartTraces(t *testing.T) {
evs := NewEventSource(psnap, hsnap, tt.cfg, nil)
require.NoError(t, evs.Open(tt.cfg))
defer evs.Close()
if !SupportsSystemProviders() {
assert.Equal(t, tt.wantSessions, len(evs.(*EventSource).traces))
}
assert.Equal(t, tt.wantSessions, len(evs.(*EventSource).traces))

for _, trace := range evs.(*EventSource).traces {
require.True(t, trace.Handle().IsValid())
require.NoError(t, etw.ControlTrace(0, trace.Name, trace.GUID, etw.Query))
if !SupportsSystemProviders() {
if tt.wantFlags != nil && trace.IsKernelTrace() {
flags, err := etw.GetTraceSystemFlags(trace.Handle())
require.NoError(t, err)
// check enabled system event flags
require.Equal(t, tt.wantFlags[0], flags[0])
require.Equal(t, tt.wantFlags[1], flags[4])
}
if tt.wantFlags != nil && trace.IsKernelTrace() {
flags, err := etw.GetTraceSystemFlags(trace.Handle())
require.NoError(t, err)
// check enabled system event flags
require.Equal(t, tt.wantFlags[0], flags[0])
require.Equal(t, tt.wantFlags[1], flags[4])
}
}
})
Expand Down Expand Up @@ -204,11 +200,7 @@ func TestEventSourceEnableFlagsDynamically(t *testing.T) {

flags := evs.(*EventSource).traces[0].enableFlagsDynamically(cfg.Kstream)

if SupportsSystemProviders() {
require.Len(t, evs.(*EventSource).traces, 3)
} else {
require.Len(t, evs.(*EventSource).traces, 2)
}
require.Len(t, evs.(*EventSource).traces, 2)

require.True(t, flags&etw.FileIO != 0)
require.True(t, flags&etw.Process != 0)
Expand Down
56 changes: 5 additions & 51 deletions internal/etw/trace.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,7 @@ func initEventTraceProps(c config.KstreamConfig) etw.EventTraceProperties {
flushTimer = time.Second
}
mode := uint32(etw.ProcessTraceModeRealtime)
if SupportsSystemProviders() {
mode |= etw.EventTraceSystemLoggerMode
}

return etw.EventTraceProperties{
Wnode: etw.WnodeHeader{
BufferSize: uint32(unsafe.Sizeof(etw.EventTraceProperties{})) + maxTracePropsSize,
Expand Down Expand Up @@ -133,24 +131,13 @@ func (t *Trace) enableCallstacks() {
if t.IsKernelTrace() {
t.stackExtensions.EnableProcessCallstack()

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

t.stackExtensions.EnableFileCallstack()

t.stackExtensions.EnableMemoryCallstack()
}

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

if t.IsThreadpoolTrace() {
t.stackExtensions.EnableThreadpoolCallstack()
}
Expand Down Expand Up @@ -231,32 +218,14 @@ func (t *Trace) Start() error {
// enrichment is enabled, it is necessary to instruct the provider
// to emit stack addresses in the extended data item section when
// writing events to the session buffers
if cfg.StackEnrichment && !t.IsSystemProvider() && !t.IsThreadpoolTrace() {
if cfg.StackEnrichment && !t.IsThreadpoolTrace() {
return etw.EnableTraceWithOpts(t.GUID, t.startHandle, t.Keywords, etw.EnableTraceOpts{WithStacktrace: true})
} else if cfg.StackEnrichment && len(t.stackExtensions.EventIds()) > 0 {
if err := etw.EnableStackTracing(t.startHandle, t.stackExtensions.EventIds()); err != nil {
return fmt.Errorf("fail to enable system events callstack tracing: %v", err)
}
}

if t.IsSystemRegistryTrace() {
if err := etw.EnableTrace(t.GUID, t.startHandle, t.Keywords); err != nil {
return err
}
// when the registry provider is started
// in a separate session, we can trigger
// KCB rundown events by using a similar
// approach described previously
handle := t.startHandle
sysTraceFlags := make([]etw.EventTraceFlags, 8)
if err := etw.SetTraceSystemFlags(handle, sysTraceFlags); err != nil {
log.Warnf("unable to set empty system flags on registry provider: %v", err)
return nil
}
sysTraceFlags[0] = etw.Registry
return etw.SetTraceSystemFlags(handle, sysTraceFlags)
}

return etw.EnableTrace(t.GUID, t.startHandle, t.Keywords)
}

Expand Down Expand Up @@ -348,17 +317,9 @@ func (t *Trace) Close() error {
// IsKernelTrace determines if this is the system logger trace.
func (t *Trace) IsKernelTrace() bool { return t.GUID == etw.KernelTraceControlGUID }

// IsSystemRegistryTrace determines if this is the system registry logger trace.
func (t *Trace) IsSystemRegistryTrace() bool { return t.GUID == etw.SystemRegistryProviderID }

// IsThreadpoolTrace determines if this is the thread pool logger trace.
func (t *Trace) IsThreadpoolTrace() bool { return t.GUID == etw.ThreadpoolGUID }

// IsSystemProvider determines if this is one of the granular system provider traces.
func (t *Trace) IsSystemProvider() bool {
return t.GUID == etw.SystemIOProviderID || t.GUID == etw.SystemRegistryProviderID || t.GUID == etw.SystemProcessProviderID || t.GUID == etw.SystemMemoryProviderID
}

// enableFlagsDynamically crafts the system logger event mask
// depending on the compiled rules result or the config state.
// System logger flags is a bitmask that indicates which kernel events
Expand Down Expand Up @@ -398,15 +359,8 @@ func (t *Trace) enableFlagsDynamically(config config.KstreamConfig) etw.EventTra
if config.EnableMemKevents {
flags |= etw.VirtualAlloc
}

if !SupportsSystemProviders() || t.config.IsCaptureSet() {
// Registry is the only provider started
// in its own tracing session because it
// generates an overwhelming amount of
// events
if config.EnableRegistryKevents {
flags |= etw.Registry
}
if config.EnableRegistryKevents {
flags |= etw.Registry
}

return flags
Expand Down
2 changes: 1 addition & 1 deletion pkg/kevent/ktypes/ktypes_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -595,7 +595,7 @@ func (k Ktype) Source() EventSource {
// events, but it appears first on the consumer callback
// before other events published before it.
func (k Ktype) CanArriveOutOfOrder() bool {
return k.Category() == Registry || k.Category() == Threadpool || k.Subcategory() == DNS ||
return k.Category() == Threadpool || k.Subcategory() == DNS ||
k == OpenProcess || k == OpenThread || k == SetThreadContext || k == CreateSymbolicLinkObject
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/kevent/ktypes/ktypes_windows_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ func TestGUIDAndHookIDFromKtype(t *testing.T) {
}

func TestCanArriveOutOfOrder(t *testing.T) {
assert.True(t, RegSetValue.CanArriveOutOfOrder())
assert.False(t, RegSetValue.CanArriveOutOfOrder())
assert.False(t, VirtualAlloc.CanArriveOutOfOrder())
assert.True(t, OpenProcess.CanArriveOutOfOrder())
}
36 changes: 0 additions & 36 deletions pkg/sys/etw/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,48 +66,12 @@ const (
// ThreadpoolSession represents the session name for the thread pool logger
ThreadpoolSession = "Threadpool Logger"

// SystemRegistrySession represents system registry logger
SystemRegistrySession = "System Registry Logger"

// WnodeTraceFlagGUID indicates that the structure contains event tracing information
WnodeTraceFlagGUID = 0x00020000
// ProcessTraceModeRealtime denotes that there will be a real-time consumers for events forwarded from the providers
ProcessTraceModeRealtime = 0x00000100
// ProcessTraceModeEventRecord is the mode that enables the "event record" format for kernel events
ProcessTraceModeEventRecord = 0x10000000
// EventTraceSystemLoggerMode enables events from system loggers
EventTraceSystemLoggerMode = 0x02000000
)

var (
// SystemProcessProviderID provides events related to the process, including lifetime information, image load events, and thread related events.
SystemProcessProviderID = windows.GUID{Data1: 0x151f55dc, Data2: 0x467d, Data3: 0x471f, Data4: [8]byte{0x83, 0xb5, 0x5f, 0x88, 0x9d, 0x46, 0xff, 0x66}}
// SystemIOProviderID provides events related to multiple kinds of IO including disk, cache, and network.
SystemIOProviderID = windows.GUID{Data1: 0x3d5c43e3, Data2: 0x0f1c, Data3: 0x4202, Data4: [8]byte{0xb8, 0x17, 0x17, 0x4c, 0x00, 0x70, 0xdc, 0x79}}
// SystemRegistryProviderID provides events related to the registry.
SystemRegistryProviderID = windows.GUID{Data1: 0x16156bd9, Data2: 0xfab4, Data3: 0x4cfa, Data4: [8]byte{0xa2, 0x32, 0x89, 0xd1, 0x09, 0x90, 0x58, 0xe3}}
// SystemMemoryProviderID provides events related to the memory manager.
SystemMemoryProviderID = windows.GUID{Data1: 0x82958ca9, Data2: 0xb6cd, Data3: 0x47f8, Data4: [8]byte{0xa3, 0xa8, 0x03, 0xae, 0x85, 0xa4, 0xbc, 0x24}}
)

const (
// ProcessKeywordGeneral enables process events
ProcessKeywordGeneral = 0x1
// ProcessKeywordThread enables thread events
ProcessKeywordThread = 0x800
// ProcessKeywordLoader enables image load/unload events
ProcessKeywordLoader = 0x1000

// RegistryKeywordGeneral enables registry events
RegistryKeywordGeneral = 0x1

// IOKeywordNetwork enables network events
IOKeywordNetwork = 0x200

// MemoryVirtualAlloc enables memory alloc events
MemoryVirtualAlloc = 0x400
// MemoryVAMap enables section mapping/unmapping events
MemoryVAMap = 0x4000
)

const (
Expand Down
Loading