diff --git a/libbeat/processors/decode_xml/schema.go b/libbeat/processors/decode_xml/schema.go index 10043ec3d0ba..d10e85a3a8fb 100644 --- a/libbeat/processors/decode_xml/schema.go +++ b/libbeat/processors/decode_xml/schema.go @@ -24,13 +24,15 @@ import ( "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/common/encoding/xml" "github.com/elastic/beats/v7/libbeat/logp" - "github.com/elastic/beats/v7/winlogbeat/sys/winevent" ) const wineventlogSchema = "wineventlog" type newDecoderFunc func(cfg decodeXMLConfig) decoder -type decoder func(p []byte) (common.MapStr, error) + +// a decoder will decode the raw XML into a set of fields, +// optionally will return additional ECS mappings when possible +type decoder func(p []byte) (decodedXML common.MapStr, err error) var ( registeredDecoders = map[string]newDecoderFunc{} @@ -83,13 +85,3 @@ func newSchemaLessDecoder(cfg decodeXMLConfig) decoder { return common.MapStr(out), nil } } - -func newWineventlogDecoder(decodeXMLConfig) decoder { - return func(p []byte) (common.MapStr, error) { - evt, err := winevent.UnmarshalXML(p) - if err != nil { - return nil, err - } - return evt.Fields(), nil - } -} diff --git a/libbeat/processors/decode_xml/schema_test.go b/libbeat/processors/decode_xml/schema_test.go index 655c5156fe23..dc566feb9047 100644 --- a/libbeat/processors/decode_xml/schema_test.go +++ b/libbeat/processors/decode_xml/schema_test.go @@ -40,9 +40,10 @@ func TestDecodeSchemas(t *testing.T) { { schema: wineventlogSchema, config: decodeXMLConfig{ - Field: "message", - Target: &testXMLTargetField, - Schema: wineventlogSchema, + Field: "message", + Target: &testXMLTargetField, + Schema: wineventlogSchema, + OverwriteKeys: true, }, Input: common.MapStr{ "message": "" + diff --git a/libbeat/processors/decode_xml/schema_wineventlog.go b/libbeat/processors/decode_xml/schema_wineventlog.go new file mode 100644 index 000000000000..64e42e043d1f --- /dev/null +++ b/libbeat/processors/decode_xml/schema_wineventlog.go @@ -0,0 +1,36 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you under +// the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +// +build !windows + +package decode_xml + +import ( + "github.com/elastic/beats/v7/libbeat/common" + "github.com/elastic/beats/v7/winlogbeat/sys/winevent" +) + +func newWineventlogDecoder(decodeXMLConfig) decoder { + return func(p []byte) (common.MapStr, error) { + evt, err := winevent.UnmarshalXML(p) + if err != nil { + return nil, err + } + winevent.EnrichRawValuesWithNames(nil, &evt) + return evt.Fields(), nil + } +} diff --git a/libbeat/processors/decode_xml/schema_wineventlog_windows.go b/libbeat/processors/decode_xml/schema_wineventlog_windows.go new file mode 100644 index 000000000000..0ce20f0814c9 --- /dev/null +++ b/libbeat/processors/decode_xml/schema_wineventlog_windows.go @@ -0,0 +1,84 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you under +// the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +// +build windows + +package decode_xml + +import ( + "sync" + + "github.com/elastic/beats/v7/libbeat/common" + "github.com/elastic/beats/v7/libbeat/logp" + "github.com/elastic/beats/v7/winlogbeat/sys/winevent" + "github.com/elastic/beats/v7/winlogbeat/sys/wineventlog" +) + +func newWineventlogDecoder(decodeXMLConfig) decoder { + cache := &metadataCache{ + store: map[string]*winevent.WinMeta{}, + } + return func(p []byte) (common.MapStr, error) { + evt, err := winevent.UnmarshalXML(p) + if err != nil { + return nil, err + } + md := cache.getPublisherMetadata(evt.Provider.Name) + winevent.EnrichRawValuesWithNames(md, &evt) + return evt.Fields(), nil + } +} + +type metadataCache struct { + store map[string]*winevent.WinMeta + mutex sync.RWMutex +} + +func (c *metadataCache) getPublisherMetadata(publisher string) *winevent.WinMeta { + // NOTE: This code uses double-check locking to elevate to a write-lock + // when a cache value needs initialized. + c.mutex.RLock() + + log := logp.L().Named(logName) + // Lookup cached value. + md, found := c.store[publisher] + if !found { + // Elevate to write lock. + c.mutex.RUnlock() + c.mutex.Lock() + defer c.mutex.Unlock() + + // Double-check if the condition changed while upgrading the lock. + md, found = c.store[publisher] + if found { + return md + } + + // Load metadata from the publisher. + md, err := wineventlog.NewPublisherMetadataStore(wineventlog.NilHandle, publisher, log) + if err != nil { + // Return an empty store on error (can happen in cases where the + // log was forwarded and the provider doesn't exist on collector). + md = wineventlog.NewEmptyPublisherMetadataStore(publisher, log) + } + c.store[publisher] = &md.WinMeta + } else { + c.mutex.RUnlock() + } + + return md +} diff --git a/winlogbeat/sys/winevent/event.go b/winlogbeat/sys/winevent/event.go index 53c6b49abd53..8af8d0c9a759 100644 --- a/winlogbeat/sys/winevent/event.go +++ b/winlogbeat/sys/winevent/event.go @@ -44,6 +44,11 @@ var ( const ( keywordAuditFailure = 0x10000000000000 keywordAuditSuccess = 0x20000000000000 + + // keywordClassic indicates the log was published with the "classic" event + // logging API. + // https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.eventing.reader.standardeventkeywords?view=netframework-4.8 + keywordClassic = 0x80000000000000 ) // UnmarshalXML unmarshals the given XML into a new Event. @@ -101,7 +106,6 @@ func (e Event) Fields() common.MapStr { AddOptional(win, "keywords", e.Keywords) AddOptional(win, "opcode", e.Opcode) AddOptional(win, "provider_guid", e.Provider.GUID) - AddOptional(win, "task", e.Task) AddOptional(win, "version", e.Version) AddOptional(win, "time_created", e.TimeCreated.SystemTime) @@ -330,3 +334,60 @@ func (v *HexInt64) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { *v = HexInt64(num) return nil } + +// EnrichRawValuesWithNames adds the names associated with the raw system +// property values. It enriches the event with keywords, opcode, level, and +// task. The search order is defined in the EvtFormatMessage documentation. +func EnrichRawValuesWithNames(publisherMeta *WinMeta, event *Event) { + // Keywords. Each bit in the value can represent a keyword. + rawKeyword := int64(event.KeywordsRaw) + isClassic := keywordClassic&rawKeyword > 0 + + if len(event.Keywords) == 0 { + for mask, keyword := range defaultWinMeta.Keywords { + if rawKeyword&mask > 0 { + event.Keywords = append(event.Keywords, keyword) + rawKeyword -= mask + } + } + if publisherMeta != nil { + for mask, keyword := range publisherMeta.Keywords { + if rawKeyword&mask > 0 { + event.Keywords = append(event.Keywords, keyword) + rawKeyword -= mask + } + } + } + } + + var found bool + if event.Opcode == "" { + // Opcode (search in defaultWinMeta first). + if !isClassic { + event.Opcode, found = defaultWinMeta.Opcodes[event.OpcodeRaw] + if !found && publisherMeta != nil { + event.Opcode = publisherMeta.Opcodes[event.OpcodeRaw] + } + } + } + + if event.Level == "" { + // Level (search in defaultWinMeta first). + event.Level, found = defaultWinMeta.Levels[event.LevelRaw] + if !found && publisherMeta != nil { + event.Level = publisherMeta.Levels[event.LevelRaw] + } + } + + if event.Task == "" { + if publisherMeta != nil { + // Task (fall-back to defaultWinMeta if not found). + event.Task, found = publisherMeta.Tasks[event.TaskRaw] + if !found { + event.Task = defaultWinMeta.Tasks[event.TaskRaw] + } + } else { + event.Task = defaultWinMeta.Tasks[event.TaskRaw] + } + } +} diff --git a/winlogbeat/sys/winevent/maputil.go b/winlogbeat/sys/winevent/maputil.go index 41fe694c88ed..45a265ae8c6b 100644 --- a/winlogbeat/sys/winevent/maputil.go +++ b/winlogbeat/sys/winevent/maputil.go @@ -80,6 +80,10 @@ func AddPairs(m common.MapStr, key string, pairs []KeyValue) common.MapStr { // isZero return true if the given value is the zero value for its type. func isZero(i interface{}) bool { + if i == nil { + return true + } + v := reflect.ValueOf(i) switch v.Kind() { case reflect.Array, reflect.String: @@ -95,5 +99,6 @@ func isZero(i interface{}) bool { case reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice: return v.IsNil() } + return false } diff --git a/winlogbeat/sys/wineventlog/winmeta.go b/winlogbeat/sys/winevent/winmeta.go similarity index 80% rename from winlogbeat/sys/wineventlog/winmeta.go rename to winlogbeat/sys/winevent/winmeta.go index 140b1c00066f..1d7ac8f5c689 100644 --- a/winlogbeat/sys/wineventlog/winmeta.go +++ b/winlogbeat/sys/winevent/winmeta.go @@ -15,13 +15,18 @@ // specific language governing permissions and limitations // under the License. -// +build windows +package winevent -package wineventlog +type WinMeta struct { + Keywords map[int64]string // Keyword bit mask to keyword name. + Opcodes map[uint8]string // Opcode value to name. + Levels map[uint8]string // Level value to name. + Tasks map[uint16]string // Task value to name. +} -// winMeta contains the static values that are a common across Windows. These +// defaultWinMeta contains the static values that are a common across Windows. These // values are from winmeta.xml inside the Windows SDK. -var winMeta = &publisherMetadataStore{ +var defaultWinMeta = &WinMeta{ Keywords: map[int64]string{ 0: "AnyKeyword", 0x1000000000000: "Response Time", diff --git a/winlogbeat/sys/wineventlog/metadata_store.go b/winlogbeat/sys/wineventlog/metadata_store.go index fe94c03e1681..a02da985b4fb 100644 --- a/winlogbeat/sys/wineventlog/metadata_store.go +++ b/winlogbeat/sys/wineventlog/metadata_store.go @@ -43,32 +43,30 @@ var ( } ) -// publisherMetadataStore stores metadata from a publisher. -type publisherMetadataStore struct { +// PublisherMetadataStore stores metadata from a publisher. +type PublisherMetadataStore struct { Metadata *PublisherMetadata // Handle to the publisher metadata. May be nil. - Keywords map[int64]string // Keyword bit mask to keyword name. - Opcodes map[uint8]string // Opcode value to name. - Levels map[uint8]string // Level value to name. - Tasks map[uint16]string // Task value to name. + + winevent.WinMeta // Event ID to event metadata (message and event data param names). - Events map[uint16]*eventMetadata + Events map[uint16]*EventMetadata // Event ID to map of fingerprints to event metadata. The fingerprint value // is hash of the event data parameters count and types. - EventFingerprints map[uint16]map[uint64]*eventMetadata + EventFingerprints map[uint16]map[uint64]*EventMetadata mutex sync.RWMutex log *logp.Logger } -func newPublisherMetadataStore(session EvtHandle, provider string, log *logp.Logger) (*publisherMetadataStore, error) { +func NewPublisherMetadataStore(session EvtHandle, provider string, log *logp.Logger) (*PublisherMetadataStore, error) { md, err := NewPublisherMetadata(session, provider) if err != nil { return nil, err } - store := &publisherMetadataStore{ + store := &PublisherMetadataStore{ Metadata: md, - EventFingerprints: map[uint16]map[uint64]*eventMetadata{}, + EventFingerprints: map[uint16]map[uint64]*EventMetadata{}, log: log.With("publisher", provider), } @@ -88,21 +86,23 @@ func newPublisherMetadataStore(session EvtHandle, provider string, log *logp.Log return store, nil } -// newEmptyPublisherMetadataStore creates an empty metadata store for cases +// NewEmptyPublisherMetadataStore creates an empty metadata store for cases // where no local publisher metadata exists. -func newEmptyPublisherMetadataStore(provider string, log *logp.Logger) *publisherMetadataStore { - return &publisherMetadataStore{ - Keywords: map[int64]string{}, - Opcodes: map[uint8]string{}, - Levels: map[uint8]string{}, - Tasks: map[uint16]string{}, - Events: map[uint16]*eventMetadata{}, - EventFingerprints: map[uint16]map[uint64]*eventMetadata{}, +func NewEmptyPublisherMetadataStore(provider string, log *logp.Logger) *PublisherMetadataStore { + return &PublisherMetadataStore{ + WinMeta: winevent.WinMeta{ + Keywords: map[int64]string{}, + Opcodes: map[uint8]string{}, + Levels: map[uint8]string{}, + Tasks: map[uint16]string{}, + }, + Events: map[uint16]*EventMetadata{}, + EventFingerprints: map[uint16]map[uint64]*EventMetadata{}, log: log.With("publisher", provider, "empty", true), } } -func (s *publisherMetadataStore) initKeywords() error { +func (s *PublisherMetadataStore) initKeywords() error { keywords, err := s.Metadata.Keywords() if err != nil { return err @@ -119,7 +119,7 @@ func (s *publisherMetadataStore) initKeywords() error { return nil } -func (s *publisherMetadataStore) initOpcodes() error { +func (s *PublisherMetadataStore) initOpcodes() error { opcodes, err := s.Metadata.Opcodes() if err != nil { return err @@ -135,7 +135,7 @@ func (s *publisherMetadataStore) initOpcodes() error { return nil } -func (s *publisherMetadataStore) initLevels() error { +func (s *PublisherMetadataStore) initLevels() error { levels, err := s.Metadata.Levels() if err != nil { return err @@ -152,7 +152,7 @@ func (s *publisherMetadataStore) initLevels() error { return nil } -func (s *publisherMetadataStore) initTasks() error { +func (s *PublisherMetadataStore) initTasks() error { tasks, err := s.Metadata.Tasks() if err != nil { return err @@ -168,14 +168,14 @@ func (s *publisherMetadataStore) initTasks() error { return nil } -func (s *publisherMetadataStore) initEvents() error { +func (s *PublisherMetadataStore) initEvents() error { itr, err := s.Metadata.EventMetadataIterator() if err != nil { return err } defer itr.Close() - s.Events = map[uint16]*eventMetadata{} + s.Events = map[uint16]*EventMetadata{} for itr.Next() { evt, err := newEventMetadataFromPublisherMetadata(itr, s.Metadata) if err != nil { @@ -188,7 +188,7 @@ func (s *publisherMetadataStore) initEvents() error { return itr.Err() } -func (s *publisherMetadataStore) getEventMetadata(eventID uint16, eventDataFingerprint uint64, eventHandle EvtHandle) *eventMetadata { +func (s *PublisherMetadataStore) getEventMetadata(eventID uint16, eventDataFingerprint uint64, eventHandle EvtHandle) *EventMetadata { // Use a read lock to get a cached value. s.mutex.RLock() fingerprints, found := s.EventFingerprints[eventID] @@ -207,7 +207,7 @@ func (s *publisherMetadataStore) getEventMetadata(eventID uint16, eventDataFinge fingerprints, found = s.EventFingerprints[eventID] if !found { - fingerprints = map[uint64]*eventMetadata{} + fingerprints = map[uint64]*EventMetadata{} s.EventFingerprints[eventID] = fingerprints } @@ -268,7 +268,7 @@ func (s *publisherMetadataStore) getEventMetadata(eventID uint16, eventDataFinge return em } -func (s *publisherMetadataStore) Close() error { +func (s *PublisherMetadataStore) Close() error { if s.Metadata != nil { s.mutex.Lock() defer s.mutex.Unlock() @@ -278,7 +278,7 @@ func (s *publisherMetadataStore) Close() error { return nil } -type eventMetadata struct { +type EventMetadata struct { EventID uint16 // Event ID. Version uint8 // Event format version. MsgStatic string // Used when the message has no parameters. @@ -288,7 +288,7 @@ type eventMetadata struct { // newEventMetadataFromEventHandle collects metadata about an event type using // the handle of an event. -func newEventMetadataFromEventHandle(publisher *PublisherMetadata, eventHandle EvtHandle) (*eventMetadata, error) { +func newEventMetadataFromEventHandle(publisher *PublisherMetadata, eventHandle EvtHandle) (*EventMetadata, error) { xml, err := getEventXML(publisher, eventHandle) if err != nil { return nil, err @@ -301,7 +301,7 @@ func newEventMetadataFromEventHandle(publisher *PublisherMetadata, eventHandle E return nil, errors.Wrap(err, "failed to unmarshal XML") } - em := &eventMetadata{ + em := &EventMetadata{ EventID: uint16(event.EventIdentifier.ID), Version: uint8(event.Version), } @@ -335,8 +335,8 @@ func newEventMetadataFromEventHandle(publisher *PublisherMetadata, eventHandle E // newEventMetadataFromPublisherMetadata collects metadata about an event type // using the publisher metadata. -func newEventMetadataFromPublisherMetadata(itr *EventMetadataIterator, publisher *PublisherMetadata) (*eventMetadata, error) { - em := &eventMetadata{} +func newEventMetadataFromPublisherMetadata(itr *EventMetadataIterator, publisher *PublisherMetadata) (*EventMetadata, error) { + em := &EventMetadata{} err := multierr.Combine( em.initEventID(itr), em.initVersion(itr), @@ -349,7 +349,7 @@ func newEventMetadataFromPublisherMetadata(itr *EventMetadataIterator, publisher return em, nil } -func (em *eventMetadata) initEventID(itr *EventMetadataIterator) error { +func (em *EventMetadata) initEventID(itr *EventMetadataIterator) error { id, err := itr.EventID() if err != nil { return err @@ -359,7 +359,7 @@ func (em *eventMetadata) initEventID(itr *EventMetadataIterator) error { return nil } -func (em *eventMetadata) initVersion(itr *EventMetadataIterator) error { +func (em *EventMetadata) initVersion(itr *EventMetadataIterator) error { version, err := itr.Version() if err != nil { return err @@ -368,7 +368,7 @@ func (em *eventMetadata) initVersion(itr *EventMetadataIterator) error { return nil } -func (em *eventMetadata) initEventDataTemplate(itr *EventMetadataIterator) error { +func (em *EventMetadata) initEventDataTemplate(itr *EventMetadataIterator) error { xml, err := itr.Template() if err != nil { return err @@ -391,7 +391,7 @@ func (em *eventMetadata) initEventDataTemplate(itr *EventMetadataIterator) error return nil } -func (em *eventMetadata) initEventMessage(itr *EventMetadataIterator, publisher *PublisherMetadata) error { +func (em *EventMetadata) initEventMessage(itr *EventMetadataIterator, publisher *PublisherMetadata) error { messageID, err := itr.MessageID() if err != nil { return err @@ -405,7 +405,7 @@ func (em *eventMetadata) initEventMessage(itr *EventMetadataIterator, publisher return em.setMessage(msg) } -func (em *eventMetadata) setMessage(msg string) error { +func (em *EventMetadata) setMessage(msg string) error { msg = sys.RemoveWindowsLineEndings(msg) tmplID := strconv.Itoa(int(em.EventID)) @@ -424,7 +424,7 @@ func (em *eventMetadata) setMessage(msg string) error { return nil } -func (em *eventMetadata) equal(other *eventMetadata) bool { +func (em *EventMetadata) equal(other *EventMetadata) bool { if em == other { return true } diff --git a/winlogbeat/sys/wineventlog/metadata_store_test.go b/winlogbeat/sys/wineventlog/metadata_store_test.go index 0c89251bb7aa..205f703105d1 100644 --- a/winlogbeat/sys/wineventlog/metadata_store_test.go +++ b/winlogbeat/sys/wineventlog/metadata_store_test.go @@ -30,7 +30,7 @@ import ( func TestPublisherMetadataStore(t *testing.T) { logp.TestingSetup() - s, err := newPublisherMetadataStore( + s, err := NewPublisherMetadataStore( NilHandle, "Microsoft-Windows-Security-Auditing", logp.NewLogger("metadata")) diff --git a/winlogbeat/sys/wineventlog/renderer.go b/winlogbeat/sys/wineventlog/renderer.go index d52f4399fa2a..40392abd15d5 100644 --- a/winlogbeat/sys/wineventlog/renderer.go +++ b/winlogbeat/sys/wineventlog/renderer.go @@ -48,7 +48,7 @@ const ( // Renderer is used for converting event log handles into complete events. type Renderer struct { // Cache of publisher metadata. Maps publisher names to stored metadata. - metadataCache map[string]*publisherMetadataStore + metadataCache map[string]*PublisherMetadataStore // Mutex to guard the metadataCache. The other members are immutable. mutex sync.RWMutex @@ -71,7 +71,7 @@ func NewRenderer(session EvtHandle, log *logp.Logger) (*Renderer, error) { } return &Renderer{ - metadataCache: map[string]*publisherMetadataStore{}, + metadataCache: map[string]*PublisherMetadataStore{}, session: session, systemContext: systemContext, userContext: userContext, @@ -112,7 +112,7 @@ func (r *Renderer) Render(handle EvtHandle) (*winevent.Event, error) { } // Associate raw system properties to names (e.g. level=2 to Error). - enrichRawValuesWithNames(md, event) + winevent.EnrichRawValuesWithNames(&md.WinMeta, event) eventData, fingerprint, err := r.renderUser(handle, event) if err != nil { @@ -135,9 +135,9 @@ func (r *Renderer) Render(handle EvtHandle) (*winevent.Event, error) { return event, nil } -// getPublisherMetadata return a publisherMetadataStore for the provider. It +// getPublisherMetadata return a PublisherMetadataStore for the provider. It // never returns nil, but may return an error if it couldn't open a publisher. -func (r *Renderer) getPublisherMetadata(publisher string) (*publisherMetadataStore, error) { +func (r *Renderer) getPublisherMetadata(publisher string) (*PublisherMetadataStore, error) { var err error // NOTE: This code uses double-check locking to elevate to a write-lock @@ -159,11 +159,11 @@ func (r *Renderer) getPublisherMetadata(publisher string) (*publisherMetadataSto } // Load metadata from the publisher. - md, err = newPublisherMetadataStore(r.session, publisher, r.log) + md, err = NewPublisherMetadataStore(r.session, publisher, r.log) if err != nil { // Return an empty store on error (can happen in cases where the // log was forwarded and the provider doesn't exist on collector). - md = newEmptyPublisherMetadataStore(publisher, r.log) + md = NewEmptyPublisherMetadataStore(publisher, r.log) err = errors.Wrapf(err, "failed to load publisher metadata for %v "+ "(returning an empty metadata store)", publisher) } @@ -307,7 +307,7 @@ func (r *Renderer) render(context EvtHandle, eventHandle EvtHandle) (*sys.Pooled } // addEventData adds the event/user data values to the event. -func (r *Renderer) addEventData(evtMeta *eventMetadata, values []interface{}, event *winevent.Event) { +func (r *Renderer) addEventData(evtMeta *EventMetadata, values []interface{}, event *winevent.Event) { if len(values) == 0 { return } @@ -361,8 +361,8 @@ func (r *Renderer) addEventData(evtMeta *eventMetadata, values []interface{}, ev } // formatMessage adds the message to the event. -func (r *Renderer) formatMessage(publisherMeta *publisherMetadataStore, - eventMeta *eventMetadata, eventHandle EvtHandle, values []interface{}, +func (r *Renderer) formatMessage(publisherMeta *PublisherMetadataStore, + eventMeta *EventMetadata, eventHandle EvtHandle, values []interface{}, eventID uint16) (string, error) { if eventMeta != nil { @@ -394,45 +394,3 @@ func (r *Renderer) formatMessageFromTemplate(msgTmpl *template.Template, values return string(bb.Bytes()), nil } - -// enrichRawValuesWithNames adds the names associated with the raw system -// property values. It enriches the event with keywords, opcode, level, and -// task. The search order is defined in the EvtFormatMessage documentation. -func enrichRawValuesWithNames(publisherMeta *publisherMetadataStore, event *winevent.Event) { - // Keywords. Each bit in the value can represent a keyword. - rawKeyword := int64(event.KeywordsRaw) - isClassic := keywordClassic&rawKeyword > 0 - for mask, keyword := range winMeta.Keywords { - if rawKeyword&mask > 0 { - event.Keywords = append(event.Keywords, keyword) - rawKeyword -= mask - } - } - for mask, keyword := range publisherMeta.Keywords { - if rawKeyword&mask > 0 { - event.Keywords = append(event.Keywords, keyword) - rawKeyword -= mask - } - } - - // Opcode (search in winmeta first). - var found bool - if !isClassic { - event.Opcode, found = winMeta.Opcodes[event.OpcodeRaw] - if !found { - event.Opcode = publisherMeta.Opcodes[event.OpcodeRaw] - } - } - - // Level (search in winmeta first). - event.Level, found = winMeta.Levels[event.LevelRaw] - if !found { - event.Level = publisherMeta.Levels[event.LevelRaw] - } - - // Task (fall-back to winmeta if not found). - event.Task, found = publisherMeta.Tasks[event.TaskRaw] - if !found { - event.Task = winMeta.Tasks[event.TaskRaw] - } -}