From eb580850e359d773c2d45cdf4c663f50372893f3 Mon Sep 17 00:00:00 2001 From: Dan Kortschak <90160302+efd6@users.noreply.github.com> Date: Thu, 31 Mar 2022 09:31:28 +1030 Subject: [PATCH] winlogbeat: fix event handling for Windows 2022 (#30942) This fixes failures in event handling on Windows 2022[1] where parts of events available from the Windows API are not reflected in the events recovered by winlogbeat[2]. There is unfortunately quite a lot of movement in this change due to the need to satisfy linter requirements. Beyond those changes, the substantive changes here are: 1. Addition of new testing infrastructure to allow addition of evtx files and comparison with there expected XML renderings, and adding some test cases (shown below). 2. Fixing a buffer length parameter in the call to _EvtFormatMessage in evtFormatMessage that was the result of a lack of clarity in the API documentation for that syscall. 3. Fixing a var shadowing decl of the publisher handle EvtHandle in FormatEventString. 4. Providing a call back for the legacy (non-experimental) API through wineventlog.Message to allow it to obtain the event message in the case that the RenderingInfo element is not available via the Windows API. 5. Ensure that keyword, opcode and level are obtained by the non-experimental API by calling winevent.EnrichRawValuesWithNames in buildRecordFromXML. This change also required making winevent.Event.OpcodeRaw a pointer to allow an absent System>Opcode element to be distinquished from the zero, but present element. The change also enables testing on Windows 2022. [1]https://github.com/elastic/beats/issues/30621 [2]https://github.com/elastic/beats/pull/30622#issuecomment-1055477970 New events in testing as rendered by the Event Viewer: ec1: eventcreate /id 1000 /t error /l application /d "My custom error event for the application log" - - 1000 0 2 0 0 0x80000000000000 316 Application vagrant - My custom error event for the application log ec2: eventcreate /id 999 /t error /l application /so WinWord /d "Winword event 999 happened due to low diskspace" - - 999 0 2 0 0 0x80000000000000 317 Application vagrant - Winword event 999 happened due to low diskspace ec3: eventcreate /id 5 /t error /l system /d "Catastrophe!" - - 5 0 2 0 0 0x80000000000000 1413 System vagrant - Catastrophe! ec4: eventcreate /id 5 /t error /l system /so Backup /d "Backup failure" - - 5 0 2 0 0 0x80000000000000 1414 System vagrant - Backup failure Co-authored-by: Andrew Kroh --- CHANGELOG.next.asciidoc | 2 + winlogbeat/Jenkinsfile.yml | 5 + winlogbeat/beater/winlogbeat.go | 2 +- winlogbeat/eventlog/wineventlog.go | 47 +++-- .../eventlog/wineventlog_experimental.go | 28 ++- winlogbeat/eventlog/wineventlog_test.go | 23 ++- winlogbeat/sys/winevent/event.go | 30 ++- winlogbeat/sys/winevent/event_test.go | 4 +- winlogbeat/sys/wineventlog/format_message.go | 27 +-- winlogbeat/sys/wineventlog/query_test.go | 12 +- winlogbeat/sys/wineventlog/renderer.go | 41 ++-- winlogbeat/sys/wineventlog/renderer_test.go | 9 +- .../application-windows-error-reporting.xml | 18 ++ winlogbeat/sys/wineventlog/testdata/ec1.evtx | Bin 0 -> 69632 bytes winlogbeat/sys/wineventlog/testdata/ec1.xml | 1 + winlogbeat/sys/wineventlog/testdata/ec2.evtx | Bin 0 -> 69632 bytes winlogbeat/sys/wineventlog/testdata/ec2.xml | 1 + winlogbeat/sys/wineventlog/testdata/ec3.evtx | Bin 0 -> 69632 bytes winlogbeat/sys/wineventlog/testdata/ec3.xml | 1 + .../sys/wineventlog/testdata/ec3and4.evtx | Bin 0 -> 69632 bytes .../sys/wineventlog/testdata/ec3and4.xml | 2 + winlogbeat/sys/wineventlog/testdata/ec4.evtx | Bin 0 -> 69632 bytes winlogbeat/sys/wineventlog/testdata/ec4.xml | 1 + .../wineventlog/testdata/experimental.evtx | Bin 0 -> 69632 bytes .../sys/wineventlog/testdata/experimental.xml | 5 + .../sys/wineventlog/testdata/original.evtx | Bin 0 -> 69632 bytes .../sys/wineventlog/testdata/original.xml | 5 + .../sys/wineventlog/testdata/sysmon-9.01.xml | 32 +++ .../sys/wineventlog/wineventlog_windows.go | 68 ++++--- .../wineventlog/wineventlog_windows_test.go | 192 +++++++++++++----- x-pack/winlogbeat/Jenkinsfile.yml | 5 + 31 files changed, 385 insertions(+), 176 deletions(-) create mode 100644 winlogbeat/sys/wineventlog/testdata/application-windows-error-reporting.xml create mode 100644 winlogbeat/sys/wineventlog/testdata/ec1.evtx create mode 100644 winlogbeat/sys/wineventlog/testdata/ec1.xml create mode 100644 winlogbeat/sys/wineventlog/testdata/ec2.evtx create mode 100644 winlogbeat/sys/wineventlog/testdata/ec2.xml create mode 100644 winlogbeat/sys/wineventlog/testdata/ec3.evtx create mode 100644 winlogbeat/sys/wineventlog/testdata/ec3.xml create mode 100644 winlogbeat/sys/wineventlog/testdata/ec3and4.evtx create mode 100644 winlogbeat/sys/wineventlog/testdata/ec3and4.xml create mode 100644 winlogbeat/sys/wineventlog/testdata/ec4.evtx create mode 100644 winlogbeat/sys/wineventlog/testdata/ec4.xml create mode 100644 winlogbeat/sys/wineventlog/testdata/experimental.evtx create mode 100644 winlogbeat/sys/wineventlog/testdata/experimental.xml create mode 100644 winlogbeat/sys/wineventlog/testdata/original.evtx create mode 100644 winlogbeat/sys/wineventlog/testdata/original.xml create mode 100644 winlogbeat/sys/wineventlog/testdata/sysmon-9.01.xml diff --git a/CHANGELOG.next.asciidoc b/CHANGELOG.next.asciidoc index 42000a41297..b5bace1abbb 100644 --- a/CHANGELOG.next.asciidoc +++ b/CHANGELOG.next.asciidoc @@ -82,6 +82,8 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...main[Check the HEAD dif *Winlogbeat* +- Fix evtx parsing failures. {issue}30621[30621] {pull}30942[30942] + *Functionbeat* diff --git a/winlogbeat/Jenkinsfile.yml b/winlogbeat/Jenkinsfile.yml index eece9aaa2c3..db43d1ed027 100644 --- a/winlogbeat/Jenkinsfile.yml +++ b/winlogbeat/Jenkinsfile.yml @@ -24,6 +24,11 @@ stages: crosscompile: make: "make -C winlogbeat crosscompile" stage: mandatory + windows-2022: + mage: "mage build unitTest" + platforms: ## override default labels in this specific stage. + - "windows-2022" + stage: mandatory windows-2019: mage: "mage build unitTest" platforms: ## override default labels in this specific stage. diff --git a/winlogbeat/beater/winlogbeat.go b/winlogbeat/beater/winlogbeat.go index 86a8b47f7de..26383fcc211 100644 --- a/winlogbeat/beater/winlogbeat.go +++ b/winlogbeat/beater/winlogbeat.go @@ -94,7 +94,7 @@ func (eb *Winlogbeat) init(b *beat.Beat) error { if err != nil { return fmt.Errorf("failed to create new event log: %w", err) } - eb.log.Debugw("Initialized EventLog", "id", eventLog.Name()) + eb.log.Debugf("initialized WinEventLog[%s]", eventLog.Name()) logger, err := newEventLogger(b.Info, eventLog, config, eb.log) if err != nil { diff --git a/winlogbeat/eventlog/wineventlog.go b/winlogbeat/eventlog/wineventlog.go index 2866f4cfbe0..580b7bad2d9 100644 --- a/winlogbeat/eventlog/wineventlog.go +++ b/winlogbeat/eventlog/wineventlog.go @@ -55,6 +55,15 @@ const ( eventLoggingAPIName = "eventlogging" ) +func init() { + // Register wineventlog API if it is available. + available, _ := win.IsAvailable() + if available { + Register(winEventLogAPIName, 0, newWinEventLog, win.Channels) + Register(eventLoggingAPIName, 1, newEventLogging, win.Channels) + } +} + type winEventLogConfig struct { ConfigCommon `config:",inline"` BatchReadSize int `config:"batch_read_size"` // Maximum number of events that Read will return. @@ -160,6 +169,7 @@ type winEventLog struct { lastRead checkpoint.EventLogState // Record number of the last read event. render func(event win.EvtHandle, out io.Writer) error // Function for rendering the event to XML. + message func(event win.EvtHandle) (string, error) // Message fallback function. renderBuf []byte // Buffer used for rendering event. outputBuf *sys.ByteBuffer // Buffer for receiving XML cache *messageFilesCache // Cached mapping of source name to event message file handles. @@ -198,7 +208,7 @@ func (l *winEventLog) openChannel(bookmark win.EvtHandle) error { if err != nil { return err } - defer func() { _ = windows.CloseHandle(signalEvent) }() + defer windows.CloseHandle(signalEvent) //nolint:errcheck // This is just a resource release. var flags win.EvtSubscribeFlag if bookmark > 0 { @@ -286,13 +296,12 @@ func (l *winEventLog) Read() ([]Record, error) { }() detailf("%s EventHandles returned %d handles", l.logPrefix, len(handles)) - //nolint: prealloc // some handles can be skipped, the final size is unknown - var records []Record + var records []Record //nolint:prealloc // This linter gives bad advice and does not take into account conditionals in loops. for _, h := range handles { l.outputBuf.Reset() err := l.render(h, l.outputBuf) var bufErr sys.InsufficientBufferError - if ok := errors.As(err, &bufErr); ok { + if errors.As(err, &bufErr) { detailf("%s Increasing render buffer size to %d", l.logPrefix, bufErr.RequiredSize) l.renderBuf = make([]byte, bufErr.RequiredSize) @@ -314,6 +323,12 @@ func (l *winEventLog) Read() ([]Record, error) { if r.Offset.Bookmark, err = l.createBookmarkFromEvent(h); err != nil { logp.Warn("%s failed creating bookmark: %v", l.logPrefix, err) } + if r.Message == "" { + r.Message, err = l.message(h) + if err != nil { + logp.Err("%s error salvaging message: %v", l.logPrefix, err) + } + } records = append(records, r) l.lastRead = r.Offset } @@ -329,20 +344,20 @@ func (l *winEventLog) Close() error { func (l *winEventLog) eventHandles(maxRead int) ([]win.EvtHandle, int, error) { handles, err := win.EventHandles(l.subscription, maxRead) - switch { - case err == nil: + switch err { //nolint:errorlint // This is an errno or nil. + case nil: if l.maxRead > maxRead { debugf("%s Recovered from RPC_S_INVALID_BOUND error (errno 1734) "+ "by decreasing batch_read_size to %v", l.logPrefix, maxRead) } return handles, maxRead, nil - case errors.Is(err, win.ERROR_NO_MORE_ITEMS): + case win.ERROR_NO_MORE_ITEMS: detailf("%s No more events", l.logPrefix) if l.config.NoMoreEvents == Stop { return nil, maxRead, io.EOF } return nil, maxRead, nil - case errors.Is(err, win.RPC_S_INVALID_BOUND): + case win.RPC_S_INVALID_BOUND: incrementMetric(readErrors, err) if err := l.Close(); err != nil { return nil, 0, fmt.Errorf("failed to recover from RPC_S_INVALID_BOUND: %w", err) @@ -381,13 +396,15 @@ func (l *winEventLog) buildRecordFromXML(x []byte, recoveredErr error) Record { e.RenderErr = append(e.RenderErr, recoveredErr.Error()) } + // Get basic string values for raw fields. + winevent.EnrichRawValuesWithNames(nil, &e) if e.Level == "" { // Fallback on LevelRaw if the Level is not set in the RenderingInfo. e.Level = win.EventLevel(e.LevelRaw).String() } if logp.IsDebug(detailSelector) { - detailf("%s XML=%s Event=%+v", l.logPrefix, string(x), e) + detailf("%s XML=%s Event=%+v", l.logPrefix, x, e) } r := Record{ @@ -489,6 +506,9 @@ func newWinEventLog(options *common.Config) (EventLog, error) { return win.RenderEvent(event, c.EventLanguage, l.renderBuf, l.cache.get, out) } } + l.message = func(event win.EvtHandle) (string, error) { + return win.Message(event, l.renderBuf, l.cache.get) + } return l, nil } @@ -503,12 +523,3 @@ func (l *winEventLog) createBookmarkFromEvent(evtHandle win.EvtHandle) (string, win.Close(bmHandle) return string(l.outputBuf.Bytes()), err } - -func init() { - // Register wineventlog API if it is available. - available, _ := win.IsAvailable() - if available { - Register(winEventLogAPIName, 0, newWinEventLog, win.Channels) - Register(eventLoggingAPIName, 1, newEventLogging, win.Channels) - } -} diff --git a/winlogbeat/eventlog/wineventlog_experimental.go b/winlogbeat/eventlog/wineventlog_experimental.go index 9ac4b82a5c6..604707aca2e 100644 --- a/winlogbeat/eventlog/wineventlog_experimental.go +++ b/winlogbeat/eventlog/wineventlog_experimental.go @@ -21,7 +21,6 @@ package eventlog import ( - "errors" "fmt" "io" "os" @@ -43,6 +42,14 @@ const ( winEventLogExpAPIName = "wineventlog-experimental" ) +func init() { + // Register wineventlog API if it is available. + available, _ := win.IsAvailable() + if available { + Register(winEventLogExpAPIName, 10, newWinEventLogExp, win.Channels) + } +} + // winEventLogExp implements the EventLog interface for reading from the Windows // Event Log API. type winEventLogExp struct { @@ -100,7 +107,7 @@ func (l *winEventLogExp) openChannel(bookmark win.Bookmark) (win.EvtHandle, erro if err != nil { return win.NilHandle, err } - defer func() { _ = windows.CloseHandle(signalEvent) }() + defer windows.CloseHandle(signalEvent) //nolint:errcheck // This is just a resource release. var flags win.EvtSubscribeFlag if bookmark > 0 { @@ -120,11 +127,10 @@ func (l *winEventLogExp) openChannel(bookmark win.Bookmark) (win.EvtHandle, erro win.EvtHandle(bookmark), // Bookmark - for resuming from a specific event flags) - switch { - case err == nil: + switch err { //nolint:errorlint // This is an errno or nil. + case nil: return h, nil - case errors.Is(err, win.ERROR_NOT_FOUND), errors.Is(err, win.ERROR_EVT_QUERY_RESULT_STALE), - errors.Is(err, win.ERROR_EVT_QUERY_RESULT_INVALID_POSITION): + case win.ERROR_NOT_FOUND, win.ERROR_EVT_QUERY_RESULT_STALE, win.ERROR_EVT_QUERY_RESULT_INVALID_POSITION: // The bookmarked event was not found, we retry the subscription from the start. incrementMetric(readErrors, err) return win.Subscribe(0, signalEvent, "", l.query, 0, win.EvtSubscribeStartAtOldestRecord) @@ -213,7 +219,7 @@ func (l *winEventLogExp) processHandle(h win.EvtHandle) (*Record, error) { evt.RenderErr = append(evt.RenderErr, err.Error()) } - //nolint: godox // keep to have a record of feature disparity between non-experimental vs experimental + //nolint:godox // Bad linter! Keep to have a record of feature disparity between non-experimental vs experimental. // TODO: Need to add XML when configured. r := &Record{ @@ -321,11 +327,3 @@ func newWinEventLogExp(options *common.Config) (EventLog, error) { return l, nil } - -func init() { - // Register wineventlog API if it is available. - available, _ := win.IsAvailable() - if available { - Register(winEventLogExpAPIName, 10, newWinEventLogExp, win.Channels) - } -} diff --git a/winlogbeat/eventlog/wineventlog_test.go b/winlogbeat/eventlog/wineventlog_test.go index 0dc33b5098a..ac8986db700 100644 --- a/winlogbeat/eventlog/wineventlog_test.go +++ b/winlogbeat/eventlog/wineventlog_test.go @@ -31,6 +31,7 @@ import ( "github.com/andrewkroh/sys/windows/svc/eventlog" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/winlogbeat/checkpoint" @@ -182,13 +183,27 @@ func testWindowsEventLog(t *testing.T, api string) { const messageSize = 256 // Originally 31800, such a large value resulted in an empty eventlog under Win10. const totalEvents = 1000 for i := 0; i < totalEvents; i++ { - safeWriteEvent(t, writer, eventlog.Info, uint32(i%1000), []string{strconv.Itoa(i) + " " + randomSentence(messageSize)}) + safeWriteEvent(t, writer, eventlog.Info, uint32(i%1000)+1, []string{strconv.Itoa(i) + " " + randomSentence(messageSize)}) } openLog := func(t testing.TB, config map[string]interface{}) EventLog { return openLog(t, api, nil, config) } + t.Run("has_message", func(t *testing.T) { + log := openLog(t, map[string]interface{}{"name": providerName, "batch_read_size": 1}) + defer log.Close() + + for i := 0; i < 10; i++ { + records, err := log.Read() + require.NotEmpty(t, records) + require.NoError(t, err) + + r := records[0] + require.NotEmpty(t, r.Message, "message field is empty: errors:%v\nrecord:%#v", r.Event.RenderErr, r) + } + }) + // Test reading from an event log using a custom XML query. t.Run("custom_xml_query", func(t *testing.T) { cfg := map[string]interface{}{ @@ -302,16 +317,18 @@ func createLog(t testing.TB, messageFiles ...string) (log *eventlog.Log, tearDow } if existed { - wineventlog.EvtClearLog(wineventlog.NilHandle, name, "") + wineventlog.EvtClearLog(wineventlog.NilHandle, name, "") //nolint:errcheck // This is just a resource release. } log, err = eventlog.Open(source) + //nolint:errcheck // This is just a resource release. if err != nil { eventlog.RemoveSource(name, source) eventlog.RemoveProvider(name) t.Fatal(err) } + //nolint:errcheck // This is just a resource release. tearDown = func() { log.Close() wineventlog.EvtClearLog(wineventlog.NilHandle, name, "") @@ -338,7 +355,7 @@ func safeWriteEvent(t testing.TB, log *eventlog.Log, etype uint16, eid uint32, m // setLogSize set the maximum number of bytes that an event log can hold. func setLogSize(t testing.TB, provider string, sizeBytes int) { - output, err := exec.Command("wevtutil.exe", "sl", "/ms:"+strconv.Itoa(sizeBytes), provider).CombinedOutput() + output, err := exec.Command("wevtutil.exe", "sl", "/ms:"+strconv.Itoa(sizeBytes), provider).CombinedOutput() //nolint:gosec // No possibility of command injection. if err != nil { t.Fatal("Failed to set log size", err, string(output)) } diff --git a/winlogbeat/sys/winevent/event.go b/winlogbeat/sys/winevent/event.go index 9c342e73f48..4054626ed8f 100644 --- a/winlogbeat/sys/winevent/event.go +++ b/winlogbeat/sys/winevent/event.go @@ -44,11 +44,6 @@ 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. @@ -67,7 +62,7 @@ type Event struct { Version Version `xml:"System>Version"` LevelRaw uint8 `xml:"System>Level"` TaskRaw uint16 `xml:"System>Task"` - OpcodeRaw uint8 `xml:"System>Opcode"` + OpcodeRaw *uint8 `xml:"System>Opcode,omitempty"` KeywordsRaw HexInt64 `xml:"System>Keywords"` TimeCreated TimeCreated `xml:"System>TimeCreated"` RecordID uint64 `xml:"System>EventRecordID"` @@ -258,7 +253,10 @@ func (u *UserData) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { u.Name = se.Name u.Pairs = in.Pairs - d.Skip() + err = d.Skip() + if err != nil { + return err + } break } } @@ -309,8 +307,7 @@ func (v *Version) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { version, err := strconv.ParseUint(s, 10, 8) if err != nil { - // Ignore invalid version values. - return nil + return nil //nolint:nilerr // Ignore invalid version values. } *v = Version(version) @@ -341,20 +338,19 @@ func (v *HexInt64) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { 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 { + if rawKeyword&mask != 0 { event.Keywords = append(event.Keywords, keyword) - rawKeyword -= mask + rawKeyword &^= mask } } if publisherMeta != nil { for mask, keyword := range publisherMeta.Keywords { - if rawKeyword&mask > 0 { + if rawKeyword&mask != 0 { event.Keywords = append(event.Keywords, keyword) - rawKeyword -= mask + rawKeyword &^= mask } } } @@ -363,10 +359,10 @@ func EnrichRawValuesWithNames(publisherMeta *WinMeta, event *Event) { var found bool if event.Opcode == "" { // Opcode (search in defaultWinMeta first). - if !isClassic { - event.Opcode, found = defaultWinMeta.Opcodes[event.OpcodeRaw] + if event.OpcodeRaw != nil { + event.Opcode, found = defaultWinMeta.Opcodes[*event.OpcodeRaw] if !found && publisherMeta != nil { - event.Opcode = publisherMeta.Opcodes[event.OpcodeRaw] + event.Opcode = publisherMeta.Opcodes[*event.OpcodeRaw] } } } diff --git a/winlogbeat/sys/winevent/event_test.go b/winlogbeat/sys/winevent/event_test.go index b6d893957ed..62fc3a7d6b6 100644 --- a/winlogbeat/sys/winevent/event_test.go +++ b/winlogbeat/sys/winevent/event_test.go @@ -20,7 +20,6 @@ package winevent import ( "encoding/json" "encoding/xml" - "fmt" "strings" "testing" "time" @@ -97,6 +96,7 @@ func TestXML(t *testing.T) { EventIdentifier: EventIdentifier{ID: 91}, LevelRaw: 4, TaskRaw: 9, + OpcodeRaw: new(uint8), // The value in the XML is 0. KeywordsRaw: 0x8020000000000000, TimeCreated: TimeCreated{allXMLTimeCreated}, RecordID: 100, @@ -180,7 +180,7 @@ func TestXML(t *testing.T) { if err != nil { t.Error(err) } - fmt.Println(string(json)) + t.Logf("%s", json) } } } diff --git a/winlogbeat/sys/wineventlog/format_message.go b/winlogbeat/sys/wineventlog/format_message.go index d953c210b56..642eaa69965 100644 --- a/winlogbeat/sys/wineventlog/format_message.go +++ b/winlogbeat/sys/wineventlog/format_message.go @@ -21,9 +21,9 @@ package wineventlog import ( + "fmt" "unsafe" - "github.com/pkg/errors" "golang.org/x/sys/windows" "github.com/elastic/beats/v7/winlogbeat/sys" @@ -80,8 +80,8 @@ func evtFormatMessage(metadataHandle EvtHandle, eventHandle EvtHandle, messageID // Determine the buffer size needed (given in WCHARs). var bufferUsed uint32 err := _EvtFormatMessage(metadataHandle, eventHandle, messageID, valuesCount, valuesPtr, messageFlag, 0, nil, &bufferUsed) - if err != windows.ERROR_INSUFFICIENT_BUFFER { - return "", errors.Wrap(err, "failed in EvtFormatMessage") + if err != windows.ERROR_INSUFFICIENT_BUFFER { //nolint:errorlint // This is an errno. + return "", fmt.Errorf("failed in EvtFormatMessage: %w", err) } // Get a buffer from the pool and adjust its length. @@ -89,16 +89,17 @@ func evtFormatMessage(metadataHandle EvtHandle, eventHandle EvtHandle, messageID defer bb.Free() bb.Reserve(int(bufferUsed * 2)) - err = _EvtFormatMessage(metadataHandle, eventHandle, messageID, valuesCount, valuesPtr, messageFlag, uint32(bb.Len()/2), bb.PtrAt(0), &bufferUsed) - if err != nil { - switch err { - // Ignore some errors so it can tolerate missing or mismatched parameter values. - case windows.ERROR_EVT_UNRESOLVED_VALUE_INSERT: - case windows.ERROR_EVT_UNRESOLVED_PARAMETER_INSERT: - case windows.ERROR_EVT_MAX_INSERTS_REACHED: - default: - return "", errors.Wrap(err, "failed in EvtFormatMessage") - } + err = _EvtFormatMessage(metadataHandle, eventHandle, messageID, valuesCount, valuesPtr, messageFlag, uint32(bb.Len()), bb.PtrAt(0), &bufferUsed) + switch err { //nolint:errorlint // This is an errno or nil. + case nil: // OK + + // Ignore some errors so it can tolerate missing or mismatched parameter values. + case windows.ERROR_EVT_UNRESOLVED_VALUE_INSERT, + windows.ERROR_EVT_UNRESOLVED_PARAMETER_INSERT, + windows.ERROR_EVT_MAX_INSERTS_REACHED: + + default: + return "", fmt.Errorf("failed in EvtFormatMessage: %w", err) } return sys.UTF16BytesToString(bb.Bytes()) diff --git a/winlogbeat/sys/wineventlog/query_test.go b/winlogbeat/sys/wineventlog/query_test.go index f31f98ac6c9..8c3a5031f12 100644 --- a/winlogbeat/sys/wineventlog/query_test.go +++ b/winlogbeat/sys/wineventlog/query_test.go @@ -49,7 +49,7 @@ func TestIgnoreOlderQuery(t *testing.T) { q, err := Query{Log: "Application", IgnoreOlder: time.Hour}.Build() if assert.NoError(t, err) { assert.Equal(t, expected, q) - fmt.Println(q) + t.Log(q) } } @@ -64,7 +64,7 @@ func TestEventIDQuery(t *testing.T) { q, err := Query{Log: "Application", EventID: "1, 1-100, -75"}.Build() if assert.NoError(t, err) { assert.Equal(t, expected, q) - fmt.Println(q) + t.Log(q) } } @@ -78,7 +78,7 @@ func TestLevelQuery(t *testing.T) { q, err := Query{Log: "Application", Level: "Verbose"}.Build() if assert.NoError(t, err) { assert.Equal(t, expected, q) - fmt.Println(q) + t.Log(q) } } @@ -92,7 +92,7 @@ func TestProviderQuery(t *testing.T) { q, err := Query{Log: "Application", Provider: []string{"mysrc"}}.Build() if assert.NoError(t, err) { assert.Equal(t, expected, q) - fmt.Println(q) + t.Log(q) } } @@ -112,7 +112,7 @@ func TestCombinedQuery(t *testing.T) { }.Build() if assert.NoError(t, err) { assert.Equal(t, expected, q) - fmt.Println(q) + t.Log(q) } } @@ -126,6 +126,6 @@ func TestQueryNoParams(t *testing.T) { q, err := Query{Log: "Application"}.Build() if assert.NoError(t, err) { assert.Equal(t, expected, q) - fmt.Println(q) + t.Log(q) } } diff --git a/winlogbeat/sys/wineventlog/renderer.go b/winlogbeat/sys/wineventlog/renderer.go index 7482fae6350..c8035fe94d7 100644 --- a/winlogbeat/sys/wineventlog/renderer.go +++ b/winlogbeat/sys/wineventlog/renderer.go @@ -30,7 +30,6 @@ import ( "unsafe" "github.com/cespare/xxhash/v2" - "github.com/pkg/errors" "go.uber.org/multierr" "golang.org/x/sys/windows" @@ -41,10 +40,10 @@ import ( // 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 // Mutex to guard the metadataCache. The other members are immutable. mutex sync.RWMutex + // Cache of publisher metadata. Maps publisher names to stored metadata. + metadataCache map[string]*PublisherMetadataStore session EvtHandle // Session handle if working with remote log. systemContext EvtHandle // Render context for system values. @@ -56,12 +55,12 @@ type Renderer struct { func NewRenderer(session EvtHandle, log *logp.Logger) (*Renderer, error) { systemContext, err := _EvtCreateRenderContext(0, 0, EvtRenderContextSystem) if err != nil { - return nil, errors.Wrap(err, "failed in EvtCreateRenderContext for system context") + return nil, fmt.Errorf("failed in EvtCreateRenderContext for system context: %w", err) } userContext, err := _EvtCreateRenderContext(0, 0, EvtRenderContextUser) if err != nil { - return nil, errors.Wrap(err, "failed in EvtCreateRenderContext for user context") + return nil, fmt.Errorf("failed in EvtCreateRenderContext for user context: %w", err) } return &Renderer{ @@ -92,7 +91,7 @@ func (r *Renderer) Render(handle EvtHandle) (*winevent.Event, error) { event := &winevent.Event{} if err := r.renderSystem(handle, event); err != nil { - return nil, errors.Wrap(err, "failed to render system properties") + return nil, fmt.Errorf("failed to render system properties: %w", err) } // From this point on it will return both the event and any errors. It's @@ -110,7 +109,7 @@ func (r *Renderer) Render(handle EvtHandle) (*winevent.Event, error) { eventData, fingerprint, err := r.renderUser(handle, event) if err != nil { - errs = append(errs, errors.Wrap(err, "failed to render event data")) + errs = append(errs, fmt.Errorf("failed to render event data: %w", err)) } // Load cached event metadata or try to bootstrap it from the event's XML. @@ -120,7 +119,7 @@ func (r *Renderer) Render(handle EvtHandle) (*winevent.Event, error) { r.addEventData(eventMeta, eventData, event) if event.Message, err = r.formatMessage(md, eventMeta, handle, eventData, uint16(event.EventIdentifier.ID)); err != nil { - errs = append(errs, errors.Wrap(err, "failed to get the event message string")) + errs = append(errs, fmt.Errorf("failed to get the event message string: %w", err)) } if len(errs) > 0 { @@ -158,8 +157,8 @@ func (r *Renderer) getPublisherMetadata(publisher string) (*PublisherMetadataSto // 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) - err = errors.Wrapf(err, "failed to load publisher metadata for %v "+ - "(returning an empty metadata store)", publisher) + err = fmt.Errorf("failed to load publisher metadata for %v "+ + "(returning an empty metadata store): %w", publisher, err) } r.metadataCache[publisher] = md } else { @@ -173,11 +172,11 @@ func (r *Renderer) getPublisherMetadata(publisher string) (*PublisherMetadataSto func (r *Renderer) renderSystem(handle EvtHandle, event *winevent.Event) error { bb, propertyCount, err := r.render(r.systemContext, handle) if err != nil { - return errors.Wrap(err, "failed to get system values") + return fmt.Errorf("failed to get system values: %w", err) } defer bb.Free() - for i := 0; i < int(propertyCount); i++ { + for i := 0; i < propertyCount; i++ { property := EvtSystemPropertyID(i) offset := i * int(sizeofEvtVariant) evtVar := (*EvtVariant)(unsafe.Pointer(bb.PtrAt(offset))) @@ -187,6 +186,7 @@ func (r *Renderer) renderSystem(handle EvtHandle, event *winevent.Event) error { continue } + //nolint:errcheck // Bad linter! switch property { case EvtSystemProviderName: event.Provider.Name = data.(string) @@ -201,7 +201,10 @@ func (r *Renderer) renderSystem(handle EvtHandle, event *winevent.Event) error { case EvtSystemTask: event.TaskRaw = data.(uint16) case EvtSystemOpcode: - event.OpcodeRaw = data.(uint8) + if event.OpcodeRaw == nil { + event.OpcodeRaw = new(uint8) + } + *event.OpcodeRaw = data.(uint8) case EvtSystemKeywords: event.KeywordsRaw = winevent.HexInt64(data.(hexInt64)) case EvtSystemTimeCreated: @@ -240,7 +243,7 @@ func (r *Renderer) renderSystem(handle EvtHandle, event *winevent.Event) error { func (r *Renderer) renderUser(handle EvtHandle, event *winevent.Event) (values []interface{}, fingerprint uint64, err error) { bb, propertyCount, err := r.render(r.userContext, handle) if err != nil { - return nil, 0, errors.Wrap(err, "failed to get user values") + return nil, 0, fmt.Errorf("failed to get user values: %w", err) } defer bb.Free() @@ -260,7 +263,7 @@ func (r *Renderer) renderUser(handle EvtHandle, event *winevent.Event) (values [ for i := 0; i < propertyCount; i++ { offset := i * int(sizeofEvtVariant) evtVar := (*EvtVariant)(unsafe.Pointer(bb.PtrAt(offset))) - binary.Write(argumentHash, binary.LittleEndian, uint32(evtVar.Type)) + binary.Write(argumentHash, binary.LittleEndian, uint32(evtVar.Type)) //nolint:errcheck // Hash writes never fail. values[i], err = evtVar.Data(bb.Bytes()) if err != nil { @@ -283,8 +286,8 @@ func (r *Renderer) render(context EvtHandle, eventHandle EvtHandle) (*sys.Pooled var bufferUsed, propertyCount uint32 err := _EvtRender(context, eventHandle, EvtRenderEventValues, 0, nil, &bufferUsed, &propertyCount) - if err != nil && err != windows.ERROR_INSUFFICIENT_BUFFER { - return nil, 0, errors.Wrap(err, "failed in EvtRender") + if err != nil && err != windows.ERROR_INSUFFICIENT_BUFFER { //nolint:errorlint // This is an errno or nil. + return nil, 0, fmt.Errorf("failed in EvtRender: %w", err) } if propertyCount == 0 { @@ -297,7 +300,7 @@ func (r *Renderer) render(context EvtHandle, eventHandle EvtHandle) (*sys.Pooled err = _EvtRender(context, eventHandle, EvtRenderEventValues, uint32(bb.Len()), bb.PtrAt(0), &bufferUsed, &propertyCount) if err != nil { bb.Free() - return nil, 0, errors.Wrap(err, "failed in EvtRender") + return nil, 0, fmt.Errorf("failed in EvtRender: %w", err) } return bb, int(propertyCount), nil @@ -384,7 +387,7 @@ func (r *Renderer) formatMessageFromTemplate(msgTmpl *template.Template, values defer bb.Free() if err := msgTmpl.Execute(bb, values); err != nil { - return "", errors.Wrapf(err, "failed to execute template with data=%#v template=%v", values, msgTmpl.Root.String()) + return "", fmt.Errorf("failed to execute template with data=%#v template=%v: %w", values, msgTmpl.Root.String(), err) } return string(bb.Bytes()), nil diff --git a/winlogbeat/sys/wineventlog/renderer_test.go b/winlogbeat/sys/wineventlog/renderer_test.go index ea0c179cd1e..a283bc0f057 100644 --- a/winlogbeat/sys/wineventlog/renderer_test.go +++ b/winlogbeat/sys/wineventlog/renderer_test.go @@ -41,7 +41,7 @@ import ( ) func TestRenderer(t *testing.T) { - logp.TestingSetup() + logp.TestingSetup() //nolint:errcheck // Bad linter! Never returns a non-nil error when called without options. t.Run(filepath.Base(sysmon9File), func(t *testing.T) { log := openLog(t, sysmon9File) @@ -86,7 +86,8 @@ func TestRenderer(t *testing.T) { assert.Equal(t, e.Keywords, []string{"Audit Success"}) - assert.EqualValues(t, 0, e.OpcodeRaw) + assert.NotNil(t, 0, e.OpcodeRaw) + assert.EqualValues(t, 0, *e.OpcodeRaw) assert.Equal(t, "Info", e.Opcode) assert.EqualValues(t, 0, e.LevelRaw) @@ -131,7 +132,7 @@ func TestRenderer(t *testing.T) { assert.Equal(t, e.Keywords, []string{"Classic"}) - assert.EqualValues(t, 0, e.OpcodeRaw) + assert.EqualValues(t, (*uint8)(nil), e.OpcodeRaw) assert.Equal(t, "", e.Opcode) assert.EqualValues(t, 4, e.LevelRaw) @@ -197,7 +198,7 @@ func renderAllEvents(t *testing.T, log EvtHandle, renderer *Renderer, ignoreMiss // setLogSize set the maximum number of bytes that an event log can hold. func setLogSize(t testing.TB, provider string, sizeBytes int) { - output, err := exec.Command("wevtutil.exe", "sl", "/ms:"+strconv.Itoa(sizeBytes), provider).CombinedOutput() + output, err := exec.Command("wevtutil.exe", "sl", "/ms:"+strconv.Itoa(sizeBytes), provider).CombinedOutput() //nolint:gosec // No possibility of command injection. if err != nil { t.Fatal("failed to set log size", err, string(output)) } diff --git a/winlogbeat/sys/wineventlog/testdata/application-windows-error-reporting.xml b/winlogbeat/sys/wineventlog/testdata/application-windows-error-reporting.xml new file mode 100644 index 00000000000..0e768eaeebd --- /dev/null +++ b/winlogbeat/sys/wineventlog/testdata/application-windows-error-reporting.xml @@ -0,0 +1,18 @@ +1001400x80000000000000420107Applicationvagrant0WindowsWcpOtherFailure3Not available010.0.17763.850:3inc\auto_hive.hWindows::Rtl::AutoHive::Unload358c00001210xaad0d4fb +\\?\C:\Windows\Logs\CBS\CBS.log +\\?\C:\Windows\Logs\CBS\CbsPersist_20200212163557.log +\\?\C:\Windows\Logs\CBS\CbsPersist_20200211235949.log +\\?\C:\Windows\Logs\CBS\CbsPersist_20200211033558.cab +\\?\C:\Windows\Logs\CBS\CbsPersist_20200210020038.cab +\\?\C:\Windows\Logs\CBS\CbsPersist_20200209082850.cab +\\?\C:\Windows\servicing\Sessions\Sessions.xml +\\?\C:\Windows\WinSxs\pending.xml +\\?\C:\Windows\WinSxs\poqexec.log +\\?\C:\Windows\Logs\Cbs\FilterList.log +\\?\C:\ProgramData\Microsoft\Windows\WER\Temp\WERC5A1.tmp.WERInternalMetadata.xml +\\?\C:\ProgramData\Microsoft\Windows\WER\Temp\WERC7D5.tmp.xml +\\?\C:\ProgramData\Microsoft\Windows\WER\Temp\WERC7F3.tmp.csv +\\?\C:\ProgramData\Microsoft\Windows\WER\Temp\WERC9F8.tmp.txt +\\?\C:\ProgramData\Microsoft\Windows\WER\Temp\WERCA08.tmp.mdmp +\\?\C:\ProgramData\Microsoft\Windows\WER\ReportQueue\Critical_10.0.17763.850_3_b785171a54ee6e13bf912aeeb5bef5d9105e314b_00000000_cab_0c38cad1\memory.hdmp +\\?\C:\Windows\Temp\WERCAD4.tmp.WERDataCollectionStatus.txt\\?\C:\ProgramData\Microsoft\Windows\WER\ReportQueue\Critical_10.0.17763.850_3_b785171a54ee6e13bf912aeeb5bef5d9105e314b_00000000_cab_0c38cad105e9de0ad-0fa4-4daa-aec1-8127dc88e6c71000 diff --git a/winlogbeat/sys/wineventlog/testdata/ec1.evtx b/winlogbeat/sys/wineventlog/testdata/ec1.evtx new file mode 100644 index 0000000000000000000000000000000000000000..3e498db3ae0f143210ac1798040776c2c29e444d GIT binary patch literal 69632 zcmeI$U5Hd=9LMqh%$%7$JF7F=CYgzi(F+Q`BnswBFs>_wnp##6-VE+;yE;1~yR*Kq zL0XAY65jMiH&H=!(@h8xU3e2Afn7;fH$emuA!!tq7u)au%sDkK$r2KD@qLz=Ip;k8 z^Spfi&v}NO{`%0Ck@}!bFWKb6QGI4DXErA@J>;g(tG{1+@TMD~0R#|0009ILKmY** z5I_I{1Q3`}puaxUH{957>3{b(`aJ3_=|_Q+vDw1+f4yhMhGz)ye#&z$zS$WzzhL%G zm)YgK*|$+=joD|qzEM9z{M&MVhI>w{&&z6izWVfXHHrUF*VFQV$cGyO(uF7#$E*ut_&)srsL)M9MP3AYwE0NLyBCk z^QNw^utTbA=yR2=)Zc0yt+cgzAN;HP@$1gAnW?F-m8&#w&D{li%#Nt#R_IX+ygD_t zTjNSIdSx=UouT)G>T5tzW2(L1r<5+nt*=D(hz2{VN}o_q$L#wQKBzixK3C1zc127i zi{+PES4ZT-wpn%edBeWiye#>uXuE7ex7XG8kY3)qtCb=vWJ@_KMC$D>T}T)C{O&G$ zA_*H2QbTpwQjbNE(z{3}>FOT1khg6L^fc8&kaXpFOv99g`P@U zT>o;9Ivoj|oqPj|2|WG)`EuGYS-dWJ=}qD(*xX#EsD<+PHnJr*yF>d?jm3xTBWcTL zOGPXCSdQzabT4@OYLE4WFi&GWBr;{)qqr^A=WQl)oMpYasMKqVBfC|hT881JRjco<_A9n|7Ta9! zL$z^u#a0Y)3#~U?|EITdX0d&G`L3(8-v`1G*u@+evQgXv#~UN%4H=}&jn%|X4U z>sj^c&#Zqv`YL#_8EGf+9VgV5%#QhET~UaC%XwLRwqTp2+EB=t7OFq9S?wv2|H^NB z>{wv&$nC1Fge>?D>3eP^fctJd7LL;aRkS~~ueHMNT~XWrv_vXeG)-mx`r_X|6a)}J z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{ z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~ z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY** z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0 x009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|00D=FPz@KC<7RUeq literal 0 HcmV?d00001 diff --git a/winlogbeat/sys/wineventlog/testdata/ec1.xml b/winlogbeat/sys/wineventlog/testdata/ec1.xml new file mode 100644 index 00000000000..d1607a64835 --- /dev/null +++ b/winlogbeat/sys/wineventlog/testdata/ec1.xml @@ -0,0 +1 @@ +100002000x80000000000000316ApplicationvagrantMy custom error event for the application log diff --git a/winlogbeat/sys/wineventlog/testdata/ec2.evtx b/winlogbeat/sys/wineventlog/testdata/ec2.evtx new file mode 100644 index 0000000000000000000000000000000000000000..7b8eb85263de7a7fad8d9c69b8032f1a13b53796 GIT binary patch literal 69632 zcmeI$Ux-v?7{~GF%$%7$JFBy9s~{#eMieW!E2f~C!Md&#YHFGibm6jpa&>lAc4ys{ zz0pjP2LQ3Fx{-+PEQrYdTy$k6L0ANp7u)YSbKYE+WC;nn_`b_IbKdhl z=l%0}-}4STz15*@!_`5Xn{wHW6Z*_q-fU4cH{`bS-G5wv=(a1N0t661009ILKmY** z5I_I{1Q3{4ptm~IbEtO2!hiR-`aIz^=|_PRiP_KhfA-S670(mk?OZtja@XvzMMbk$ zn#`^g%)W_dmzaH|`Tpr8!lyHicU}MLcNbTGJokb|;!)l0c1o8%Ku;emC|Iu@vq7s_UHNBq z6c1;GAGQ{3%0{fJ!f_Q8qV;x2VRbud4_KG}#;sp>1{Kq%>rQ&}>sDmQ9FitJQ= zRQJ1VQe`!LuC+D#Tc@ivwn68?zndSwDVK|8Wb$ng2JvN~#tEy;7hqvll<=Be3a^8w@)M9t*Mp)cSo11KZ z7B;MQYbwi?TP%(>tt*rXt9sy4!FDLnr>B|*nFr-;xiYQU((Ij%ZC}cNBn`=VgOOE~ z@m25XofSpfr8)DNa20PZ@|p^Ek22w9Is9p2+f{sAQ`OM$VdTmMTM|opw=&OUHEufF zqDF^P#vYA#P#y4D8Bk2h<1dacqX(x;H%(f2NIXSr%SR{_w*10b+K;J1@3PNJ zLq1n7S;_lyS`URi;Ei8etS1fgepJ(*1lA`Nw{2tgQkSlktXnnK)p1`Sb&a%9Z@I}@ zi@p!|w6FiT&AjPGO+KbuJamV(=GB)GwGsA>3-2{+08?qlC(?!*)BCXZ|~2^&+vP=)0*;?dgq)gb!u50ifJ$Nj{pH+2G^P_PkSCqCJZ2(?Y7H{nn%v zwC1`sa(ZR1FyMm?!HA2`X21* z_0B|7>r*tLmgKm)mV+Y>O4DWtbjXwfeql9EmNl z#M-$~CEB!mqzRzAwZIu=_$Pm9d?3`Nro(fBJ`flO1Gk*?U zdj8JotH1uBha0=;`RRORS?gC_pG@f~kCLUonEo~BY3tKI{b4uV znyUBdeon3WJL_MIz6zcjjkS~bE0dO%%})AjT~UaCyLno9p=evAT2siF7OKC9IqfO2 z|GIAn?PSX0k&O*3ys{NxhYnP1WBOM~SBEbK-{yTqS9DD1s-iB8>Ri=%GQB&j={ln0 zsM_`Ac_aDvj;ApHjT~nL5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~ z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY** z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0 z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{ z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL PKmY**5I_Kd|AW9^g%K21 literal 0 HcmV?d00001 diff --git a/winlogbeat/sys/wineventlog/testdata/ec2.xml b/winlogbeat/sys/wineventlog/testdata/ec2.xml new file mode 100644 index 00000000000..5e2e8e38b7d --- /dev/null +++ b/winlogbeat/sys/wineventlog/testdata/ec2.xml @@ -0,0 +1 @@ +99902000x80000000000000317ApplicationvagrantWinword event 999 happened due to low diskspace diff --git a/winlogbeat/sys/wineventlog/testdata/ec3.evtx b/winlogbeat/sys/wineventlog/testdata/ec3.evtx new file mode 100644 index 0000000000000000000000000000000000000000..fb0bdc95fceb5e06797de26bb17b28ae28138bcd GIT binary patch literal 69632 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 literal 0 HcmV?d00001 diff --git a/winlogbeat/sys/wineventlog/testdata/ec3.xml b/winlogbeat/sys/wineventlog/testdata/ec3.xml new file mode 100644 index 00000000000..fdd0622ae59 --- /dev/null +++ b/winlogbeat/sys/wineventlog/testdata/ec3.xml @@ -0,0 +1 @@ +502000x800000000000001413SystemvagrantCatastrophe! diff --git a/winlogbeat/sys/wineventlog/testdata/ec3and4.evtx b/winlogbeat/sys/wineventlog/testdata/ec3and4.evtx new file mode 100644 index 0000000000000000000000000000000000000000..74e7cd1e2cf6b1c5b16a2553ed71cd0b62eb6b13 GIT binary patch literal 69632 zcmeI$Uuf1<9LMqR^JmYVJ=16E)P{<=h)N+{l4P0DHYb)^YGz%8Fx=+mo;?${`G<8e z6)Qrri-P`K6a_&<-Bctccokk{H%01IK^GNXWFbUR>+?O&?>ufpn;>-&?=!YNzjMC7 zbI$K|&iVdy9i^W2eWh-jS~5w+n0}{CSF=)6LvHx`=s(Hor-u}v| zKVDpWF4d4q*^Ja(Ee|e@qx$EOxvO`6^x^o=vzlHybW~5`QLT-3Kp*`9y?i>O#yV`j zbz9knb^WZqb9<7;Qw=qC&<3oe#vwJ-q*ht4!iH_H-DfNGHDtR~)2*0JeO|8LeX7}K zgSr~D9z`zK^`Pok*a5Yb^?RkY=<9BMYO&S&*c?w=H4x{Ti!FQTx<-yFXIgj2mCh+9R6mfExXQa_a6%mzma# zZB~7MvPCX;)=toQ$kxT~e2;lqdZA!jZA2ZGG-8jweN4A1W-XU4W-OOY)!Qwqh+Dg< zuGV%WVSS=0t1Vruw`^96x>y%+Pj{WIu}uo}#VLg#^PsdX(#6bVV|I*YZF|7)4|P zsY9Q#&!i%sE*7ldb2+A)Vg`8YmwIatVLp#im`P-PN^$G&Nse^kQo&l)~+hbTy zTIsh~YYjQi0>134KA&wqbfqVMrfb|Z#~L!4%Yep+S>xo#b$WnKVTR!Kx)R*?yy?F`uCbkivSZDc6YJA+$Jo|b%sx8{C$WCpf za+tT)*Z1|rqmtE4D;4Z1%@=V^IUmplv@Lw1m4l+&YDLp&yEU%&H*BumrW-x)dUY|7c=dMfWTd9oSSn8_9!tvPFR6{^h_zO`5N$Lh*=-sV}} zX8Raw&4=&26++x1YYg>Q`|*V}s}G&zYU7y2q!_D?#YXLTFE#V@IC)HntzV^=#W|cqupoG?<*Fi;zxb-_l2jm@NW3;-vgbRg1-km<9m+ujPI)$^1AQ#Hi7K2er?OW z=2`qEHTrR`^B~XGlk#yvwVscwdDkm^7o@c;A;)@!A4Fe(kWszDGio(=dWGlCYKEMn z3O`(7NY8*V$9bgx1F4$77OKMYm){ZcQ#At>ldR$qo>fAG@1A1J4lxJJ_dc}3S3T=Z zYV@;yjT7y?`iTxR^>bVN7f)#GRZeK!hMGqx&*%w5x&9NX#nRjI%88h`0hZ`Z+^KU^ z3R$W<={x@N^FToW0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~ z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY** z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0 z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{ z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0;r H|0wV`q_}7! literal 0 HcmV?d00001 diff --git a/winlogbeat/sys/wineventlog/testdata/ec3and4.xml b/winlogbeat/sys/wineventlog/testdata/ec3and4.xml new file mode 100644 index 00000000000..5844cfbfe91 --- /dev/null +++ b/winlogbeat/sys/wineventlog/testdata/ec3and4.xml @@ -0,0 +1,2 @@ +502000x800000000000001414SystemvagrantBackup failure +502000x800000000000001413SystemvagrantCatastrophe! diff --git a/winlogbeat/sys/wineventlog/testdata/ec4.evtx b/winlogbeat/sys/wineventlog/testdata/ec4.evtx new file mode 100644 index 0000000000000000000000000000000000000000..94547179581c7f96ae5e8ffdef658d4b09173fe6 GIT binary patch literal 69632 zcmeI$OK4nG9LMqh%-osWOp-}sj7Tjt5nm0MgktegTgVf&t$kRl3lWAqnlzJ%G?OMF zF4C5&NVINT=tj|{(4ANx(3NIa5fsy|TnLJE6Gc!9#^3+Wy_yC~kb)b(C(PrV^S|fu zIp>~BroS{YFjgA2^(h?}Ea)?B8M95P^&vN$@BZ!T?i+4|1`t310R#|0009ILKmY** z5I|r>-u;u zZp*KKEB?MuvAt^Z{dMgmeT-@h|8=@sV`^{Lnrd9hy6^t#%GK9*EvFh&DXUK{-tyii zkMiW-kG3y8^U1w`965BhXW_JF;!)krHlwdTK~EpoXRY5(*sztYqWnvG<&MRbpEhP~ z)+Vf^$|+T3Q#))_VHJDc9=1;XP1&GIh80uP_YQrIspPm#DmQ5(itJE+QstdCqq?#_ zw_BI~?$@_2drzCF?eMIA>4VoLa6#J!*q@udY6>aV0CdG9TK3 zsP_}T=d`K4I1M&~i> zOPcdN=4spIydBh~MH!80zGG3JZdC{@mo8*17o_U!4izL@`_|eTI}(SDiKeW&bfM0I zK#RInnPg87UCi2E1^VKYq9F62v~5wQA>Nq%^MM_X@W-Q&w0D@YR%Lw8dpfr@XZtld zUk5kw?o!@T*6vg$xmAvR5!xPA&uO711veyU56xOjAm;{n%Y^z!PL1;))M^5=(ZHvpj;hQ1sE^}7W9q^cRmJ zv@qvqsW0uBhe8RD#HUd3FyM;H3J>*<}2P!0RSOe>~}Xm-15a>)@q zvNvZ>X;$85JhOUh&IE;KYYXgVg=+IfFYQ%5qpGjaS}e3C??bg=^a?E>#ci?XsQjPa zzO*)f&Y9fev|!1hn3TMjRBFe2%C_k3+lG~we;>KHc-#DsKl>e5Jwa!dxAi7xyMOS< ztE1%42@(PbAb502000x800000000000001414SystemvagrantBackup failure diff --git a/winlogbeat/sys/wineventlog/testdata/experimental.evtx b/winlogbeat/sys/wineventlog/testdata/experimental.evtx new file mode 100644 index 0000000000000000000000000000000000000000..1fbfa0a461fbe44a73baa7f648c3d9e0270ac6cf GIT binary patch literal 69632 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 f4Cdm`{-(zDgZC`oiOEa404000x8000000000000020050WinlogbeatTestGovagrant4 college quality neutral feather article article trolley attract bargain college arrange recover feather arrange percent wriggle wriggle feather college highway feather neutral quality manager manager recover arrange article arrange manager quality bargain +304000x8000000000000020049WinlogbeatTestGovagrant3 highway article bargain article college trolley percent college attract recover arrange attract manager highway trolley bargain recover trolley arrange manager bargain wriggle arrange manager trolley bargain recover highway bargain feather manager percent +204000x8000000000000020048WinlogbeatTestGovagrant2 wriggle college highway wriggle quality manager college article neutral bargain arrange quality highway percent attract attract arrange manager wriggle neutral highway article feather recover highway highway hunting arrange article manager neutral attract +104000x8000000000000020047WinlogbeatTestGovagrant1 feather bargain feather neutral bargain recover hunting quality attract neutral wriggle quality percent manager feather neutral attract neutral highway bargain bargain attract college article wriggle quality percent wriggle article recover hunting bargain +004000x8000000000000020046WinlogbeatTestGovagrant0 wriggle neutral trolley hunting highway attract college percent highway recover arrange bargain percent arrange quality arrange manager quality trolley feather percent hunting highway quality neutral arrange recover quality recover article bargain wriggle diff --git a/winlogbeat/sys/wineventlog/testdata/original.evtx b/winlogbeat/sys/wineventlog/testdata/original.evtx new file mode 100644 index 0000000000000000000000000000000000000000..a973a51a4c34e1e3fae8c7c41bec8ac211825aaf GIT binary patch literal 69632 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 a)VO}&&ZRpsdFg*wCv6JXdC3pZ>;D00lwa`x literal 0 HcmV?d00001 diff --git a/winlogbeat/sys/wineventlog/testdata/original.xml b/winlogbeat/sys/wineventlog/testdata/original.xml new file mode 100644 index 00000000000..40ce93c2a1b --- /dev/null +++ b/winlogbeat/sys/wineventlog/testdata/original.xml @@ -0,0 +1,5 @@ +404000x8000000000000020055WinlogbeatTestGovagrant4 college quality neutral feather article article trolley attract bargain college arrange recover feather arrange percent wriggle wriggle feather college highway feather neutral quality manager manager recover arrange article arrange manager quality bargain +304000x8000000000000020054WinlogbeatTestGovagrant3 highway article bargain article college trolley percent college attract recover arrange attract manager highway trolley bargain recover trolley arrange manager bargain wriggle arrange manager trolley bargain recover highway bargain feather manager percent +204000x8000000000000020053WinlogbeatTestGovagrant2 wriggle college highway wriggle quality manager college article neutral bargain arrange quality highway percent attract attract arrange manager wriggle neutral highway article feather recover highway highway hunting arrange article manager neutral attract +104000x8000000000000020052WinlogbeatTestGovagrant1 feather bargain feather neutral bargain recover hunting quality attract neutral wriggle quality percent manager feather neutral attract neutral highway bargain bargain attract college article wriggle quality percent wriggle article recover hunting bargain +004000x8000000000000020051WinlogbeatTestGovagrant0 wriggle neutral trolley hunting highway attract college percent highway recover arrange bargain percent arrange quality arrange manager quality trolley feather percent hunting highway quality neutral arrange recover quality recover article bargain wriggle diff --git a/winlogbeat/sys/wineventlog/testdata/sysmon-9.01.xml b/winlogbeat/sys/wineventlog/testdata/sysmon-9.01.xml new file mode 100644 index 00000000000..82a6ff6dca4 --- /dev/null +++ b/winlogbeat/sys/wineventlog/testdata/sysmon-9.01.xml @@ -0,0 +1,32 @@ +244200x800000000000000032Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:52.433{42f11c3b-ccaa-5c8f-0000-0010b4e22700}1600C:\Program Files (x86)\Google\Chrome\Application\chrome.exeC:\Users\vagrant\AppData\Local\Google\Chrome\User Data\Default\Storage\ext\gfdkimpbcpahaombhbimeihdjnejgicl\def\ee4a6e45-bffd-49f4-98ae-32aebcc890b5.tmp2019-03-18 16:52:05.3392019-03-18 16:57:52.417 +244200x800000000000000031Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:52.433{42f11c3b-ccaa-5c8f-0000-0010b4e22700}1600C:\Program Files (x86)\Google\Chrome\Application\chrome.exeC:\Users\vagrant\AppData\Local\Google\Chrome\User Data\Default\Storage\ext\nmmhkkegccagdldgiimedpiccmgmieda\def\ecb9c915-c4c2-4600-a920-f2bc302990a8.tmp2019-03-18 16:52:08.4962019-03-18 16:57:52.417 +534500x800000000000000030Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:52.433{42f11c3b-ccab-5c8f-0000-001064eb2700}2680C:\Program Files (x86)\Google\Chrome\Application\chrome.exe +244200x800000000000000029Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:52.417{42f11c3b-ccaa-5c8f-0000-0010b4e22700}1600C:\Program Files (x86)\Google\Chrome\Application\chrome.exeC:\Users\vagrant\AppData\Local\Google\Chrome\User Data\Default\37ed32e9-3c5f-4663-8457-c70743e9456d.tmp2019-03-18 16:51:54.9802019-03-18 16:57:52.417 +244200x800000000000000028Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:52.417{42f11c3b-ccaa-5c8f-0000-0010b4e22700}1600C:\Program Files (x86)\Google\Chrome\Application\chrome.exeC:\Users\vagrant\AppData\Local\Google\Chrome\User Data\Default\1450fedf-ac4c-4e35-b371-ed5d3bbe4776.tmp2019-03-18 16:52:05.0282019-03-18 16:57:52.402 +244200x800000000000000027Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:52.417{42f11c3b-ccaa-5c8f-0000-0010b4e22700}1600C:\Program Files (x86)\Google\Chrome\Application\chrome.exeC:\Users\vagrant\AppData\Local\Google\Chrome\User Data\162d4140-cfab-4d05-9c92-bca60515a622.tmp2019-03-18 16:52:04.9802019-03-18 16:57:52.402 +244200x800000000000000026Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:52.387{42f11c3b-ccaa-5c8f-0000-0010b4e22700}1600C:\Program Files (x86)\Google\Chrome\Application\chrome.exeC:\Users\vagrant\AppData\Local\Google\Chrome\User Data\fe823684-c940-49f2-a940-14b02cbafba9.tmp2019-03-18 16:52:04.9802019-03-18 16:57:52.387 +534500x800000000000000025Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:52.364{42f11c3b-cccc-5c8f-0000-0010e8272900}3208C:\Program Files (x86)\Google\Chrome\Application\chrome.exe +534500x800000000000000024Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:52.350{42f11c3b-ccc6-5c8f-0000-001005082900}4832C:\Program Files (x86)\Google\Chrome\Application\chrome.exe +354300x800000000000000023Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:49.218{42f11c3b-6e19-5c8c-0000-0010eb030000}4SystemNT AUTHORITY\SYSTEMudptruefalse10.0.2.15vagrant-2012-r2.local.crowbird.com137netbios-nsfalse169.254.180.25137netbios-ns +354300x800000000000000022Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:49.213{42f11c3b-6e19-5c8c-0000-0010eb030000}4SystemNT AUTHORITY\SYSTEMudptruefalse10.0.2.15vagrant-2012-r2.local.crowbird.com137netbios-nsfalse169.254.255.255137netbios-ns +354300x800000000000000021Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:48.276{42f11c3b-6e19-5c8c-0000-0010eb030000}4SystemNT AUTHORITY\SYSTEMudptruefalse10.0.2.15vagrant-2012-r2.local.crowbird.com137netbios-nsfalse10.0.2.3137netbios-ns +354300x800000000000000020Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:48.264{42f11c3b-6e19-5c8c-0000-0010eb030000}4SystemNT AUTHORITY\SYSTEMudptruefalse10.0.2.15vagrant-2012-r2.local.crowbird.com137netbios-nsfalse40.77.226.250137netbios-ns +354300x800000000000000019Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:48.251{42f11c3b-0bad-5c8c-0000-0010dfbc0000}924C:\Windows\System32\svchost.exeNT AUTHORITY\NETWORK SERVICEudptruetruea9fe:b419:0:0:f880:2301:e0:ffff55717truee000:fc:0:0:0:0:0:05355llmnr +354300x800000000000000018Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:48.251{42f11c3b-0bad-5c8c-0000-0010dfbc0000}924C:\Windows\System32\svchost.exeNT AUTHORITY\NETWORK SERVICEudptruetruefe80:0:0:0:616f:32fa:b04f:b41955717trueff02:0:0:0:0:0:1:35355llmnr +354300x800000000000000017Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:48.251{42f11c3b-6e19-5c8c-0000-0010eb030000}4SystemNT AUTHORITY\SYSTEMudpfalsefalse169.254.255.255137netbios-nsfalse169.254.180.25137netbios-ns +354300x800000000000000016Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:48.250{42f11c3b-6e19-5c8c-0000-0010eb030000}4SystemNT AUTHORITY\SYSTEMudptruefalse169.254.180.25137netbios-nsfalse169.254.255.255137netbios-ns +354300x800000000000000015Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:48.250{42f11c3b-0bad-5c8c-0000-0010dfbc0000}924C:\Windows\System32\svchost.exeNT AUTHORITY\NETWORK SERVICEudptruetruea00:20f:0:0:18a2:6e00:e0:ffff55542truee000:fc:4300:6800:7200:6f00:6d00:65005355llmnr +354300x800000000000000014Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:48.250{42f11c3b-0bad-5c8c-0000-0010dfbc0000}924C:\Windows\System32\svchost.exeNT AUTHORITY\NETWORK SERVICEudptruetruefe80:0:0:0:e488:b85c:5262:ff86vagrant-2012-r2.local.crowbird.com55542trueff02:0:0:0:0:0:1:35355llmnr +354300x800000000000000013Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:48.250{42f11c3b-6e19-5c8c-0000-0010eb030000}4SystemNT AUTHORITY\SYSTEMudpfalsefalse10.0.2.255137netbios-nsfalse10.0.2.15vagrant-2012-r2.local.crowbird.com137netbios-ns +354300x800000000000000012Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:48.250{42f11c3b-6e19-5c8c-0000-0010eb030000}4SystemNT AUTHORITY\SYSTEMudptruefalse10.0.2.15vagrant-2012-r2.local.crowbird.com137netbios-nsfalse10.0.2.255137netbios-ns +354300x800000000000000011Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:48.214{42f11c3b-ccaa-5c8f-0000-0010b4e22700}1600C:\Program Files (x86)\Google\Chrome\Application\chrome.exeVAGRANT-2012-R2\vagranttcptruefalse10.0.2.15vagrant-2012-r2.local.crowbird.com1139false40.77.226.250443https +354300x800000000000000010Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:48.148{42f11c3b-ccaa-5c8f-0000-0010b4e22700}1600C:\Program Files (x86)\Google\Chrome\Application\chrome.exeVAGRANT-2012-R2\vagranttcptruefalse10.0.2.15vagrant-2012-r2.local.crowbird.com1138false40.77.226.250443https +354300x80000000000000009Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:48.070{42f11c3b-0bad-5c8c-0000-0010dfbc0000}924C:\Windows\System32\svchost.exeNT AUTHORITY\NETWORK SERVICEudpfalsefalse10.0.2.15vagrant-2012-r2.local.crowbird.com62141false10.0.2.353domain +354300x80000000000000008Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:47.847{42f11c3b-0bad-5c8c-0000-0010dfbc0000}924C:\Windows\System32\svchost.exeNT AUTHORITY\NETWORK SERVICEudptruetruea00:20f:0:0:18a2:6e00:e0:ffff62141truea00:203:3000:3000:3000:3000:3000:330053domain +154100x80000000000000007Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:39.012{42f11c3b-ce03-5c8f-0000-0010e9462a00}4508C:\Windows\System32\wbem\WmiPrvSE.exe6.3.9600.16384 (winblue_rtm.130821-1623)WMI Provider HostMicrosoft® Windows® Operating SystemMicrosoft CorporationC:\Windows\system32\wbem\wmiprvse.exe -EmbeddingC:\Windows\system32\NT AUTHORITY\SYSTEM{42f11c3b-6e1a-5c8c-0000-0020e7030000}0x3e70SystemSHA1=5A4C0E82FF95C9FB762D46A696EF9F1B68001C21{42f11c3b-6e1b-5c8c-0000-00102f610000}560C:\Windows\System32\svchost.exeC:\Windows\system32\svchost.exe -k DcomLaunch +534500x80000000000000006Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:38.981{42f11c3b-cdf4-5c8f-0000-0010071e2a00}4648C:\Users\vagrant\Downloads\Sysmon.exe +534500x80000000000000005Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:38.981{42f11c3b-cdf4-5c8f-0000-0010e61e2a00}4616C:\Users\vagrant\AppData\Local\Temp\Sysmon.exe +154100x80000000000000004Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:37.964{42f11c3b-ce01-5c8f-0000-00102c412a00}5028C:\Windows\System32\wbem\unsecapp.exe6.3.9600.16384 (winblue_rtm.130821-1623)Sink to receive asynchronous callbacks for WMI client applicationMicrosoft® Windows® Operating SystemMicrosoft CorporationC:\Windows\system32\wbem\unsecapp.exe -EmbeddingC:\Windows\system32\NT AUTHORITY\SYSTEM{42f11c3b-6e1a-5c8c-0000-0020e7030000}0x3e70SystemSHA1=6DF8163A6320B80B60733F9D62E2F39B4B16B678{42f11c3b-6e1b-5c8c-0000-00102f610000}560C:\Windows\System32\svchost.exeC:\Windows\system32\svchost.exe -k DcomLaunch +154100x80000000000000003Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:37.949{42f11c3b-ce01-5c8f-0000-0010c73e2a00}4860C:\Windows\Sysmon.exe9.01System activity monitorSysinternals SysmonSysinternals - www.sysinternals.comC:\Windows\Sysmon.exeC:\Windows\system32\NT AUTHORITY\SYSTEM{42f11c3b-6e1a-5c8c-0000-0020e7030000}0x3e70SystemSHA1=AC93C3B38E57A2715572933DBCB2A1C2892DBC5E{42f11c3b-6e1a-5c8c-0000-0010f14d0000}488C:\Windows\System32\services.exeC:\Windows\system32\services.exe +434400x80000000000000002Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:38.011Started9.014.20 +16341600x80000000000000001Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:37.933C:\Users\vagrant\Downloads\"C:\Users\vagrant\Downloads\Sysmon.exe" -i -n diff --git a/winlogbeat/sys/wineventlog/wineventlog_windows.go b/winlogbeat/sys/wineventlog/wineventlog_windows.go index 11cd5319e68..96d4187387d 100644 --- a/winlogbeat/sys/wineventlog/wineventlog_windows.go +++ b/winlogbeat/sys/wineventlog/wineventlog_windows.go @@ -28,10 +28,9 @@ import ( "sort" "syscall" - "github.com/elastic/beats/v7/libbeat/common" - "golang.org/x/sys/windows" + "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/winlogbeat/sys" ) @@ -74,7 +73,7 @@ func Channels() ([]string, error) { if err != nil { return nil, err } - defer _EvtClose(handle) + defer _EvtClose(handle) //nolint:errcheck // This is just a resource release. var channels []string cpBuffer := make([]uint16, 512) @@ -83,7 +82,7 @@ loop: var used uint32 err := _EvtNextChannelPath(handle, uint32(len(cpBuffer)), &cpBuffer[0], &used) if err != nil { - errno, ok := err.(syscall.Errno) + errno, ok := err.(syscall.Errno) //nolint:errorlint // This is an errno or nil. if ok { switch errno { case ERROR_INSUFFICIENT_BUFFER: @@ -203,7 +202,7 @@ func EventHandles(subscription EvtHandle, maxHandles int) ([]EvtHandle, error) { // Munge ERROR_INVALID_OPERATION to ERROR_NO_MORE_ITEMS when no handles // were read. This happens you call the method and there are no events // to read (i.e. polling). - if err == ERROR_INVALID_OPERATION && numRead == 0 { + if err == ERROR_INVALID_OPERATION && numRead == 0 { //nolint:errorlint // This is an errno or nil. return nil, ERROR_NO_MORE_ITEMS } return nil, err @@ -241,12 +240,11 @@ func RenderEvent( // Only a single string is returned when rendering XML. err = FormatEventString(EvtFormatMessageXml, eventHandle, providerName, EvtHandle(publisherHandle), lang, renderBuf, out) - // Recover by rendering the XML without the RenderingInfo (message string). if err != nil { // Do not try to recover from InsufficientBufferErrors because these // can be retried with a larger buffer. - if _, ok := err.(sys.InsufficientBufferError); ok { + if errors.Is(err, sys.InsufficientBufferError{}) { return err } @@ -256,6 +254,26 @@ func RenderEvent( return err } +// Message reads the event data associated with the EvtHandle and renders +// and returns the message only. +func Message(h EvtHandle, buf []byte, pubHandleProvider func(string) sys.MessageFiles) (message string, err error) { + providerName, err := evtRenderProviderName(buf, h) + if err != nil { + return "", err + } + + var pub EvtHandle + if pubHandleProvider != nil { + messageFiles := pubHandleProvider(providerName) + if messageFiles.Err == nil { + // There is only ever a single handle when using the Windows Event + // Log API. + pub = EvtHandle(messageFiles.Handles[0].Handle) + } + } + return getMessageStringFromHandle(&PublisherMetadata{Handle: pub}, h, nil) +} + // RenderEventXML renders the event as XML. If the event is already rendered, as // in a forwarded event whose content type is "RenderedText", then the XML will // include the RenderingInfo (message). If the event is not rendered then the @@ -315,7 +333,7 @@ func CreateBookmarkFromXML(bookmarkXML string) (EvtHandle, error) { // CreateRenderContext creates a render context. Close must be called on // returned EvtHandle when finished with the handle. func CreateRenderContext(valuePaths []string, flag EvtRenderContextFlag) (EvtHandle, error) { - var paths []uintptr + paths := make([]uintptr, 0, len(valuePaths)) for _, path := range valuePaths { utf16, err := syscall.UTF16FromString(path) if err != nil { @@ -384,11 +402,12 @@ func FormatEventString( // Open a publisher handle if one was not provided. ph := publisherHandle if ph == 0 { - ph, err := OpenPublisherMetadata(0, publisher, lang) + var err error + ph, err = OpenPublisherMetadata(0, publisher, lang) if err != nil { return err } - defer _EvtClose(ph) + defer _EvtClose(ph) //nolint:errcheck // This is just a resource release. } // Create a buffer if one was not provided. @@ -396,7 +415,7 @@ func FormatEventString( if buffer == nil { err := _EvtFormatMessage(ph, eventHandle, 0, 0, 0, messageFlag, 0, nil, &bufferUsed) - if err != nil && err != ERROR_INSUFFICIENT_BUFFER { + if err != nil && err != ERROR_INSUFFICIENT_BUFFER { //nolint:errorlint // This is an errno or nil. return err } @@ -408,8 +427,8 @@ func FormatEventString( err := _EvtFormatMessage(ph, eventHandle, 0, 0, 0, messageFlag, uint32(len(buffer)/2), &buffer[0], &bufferUsed) bufferUsed *= 2 - if err == ERROR_INSUFFICIENT_BUFFER { - return sys.InsufficientBufferError{err, int(bufferUsed)} + if err == ERROR_INSUFFICIENT_BUFFER { //nolint:errorlint // This is an errno or nil. + return sys.InsufficientBufferError{Cause: err, RequiredSize: int(bufferUsed)} } if err != nil { return err @@ -426,7 +445,7 @@ func Publishers() ([]string, error) { if err != nil { return nil, fmt.Errorf("failed in EvtOpenPublisherEnum: %w", err) } - defer Close(publisherEnumerator) + defer Close(publisherEnumerator) //nolint:errcheck // This is just a resource release. var ( publishers []string @@ -437,7 +456,7 @@ func Publishers() ([]string, error) { loop: for { if err = _EvtNextPublisherId(publisherEnumerator, uint32(len(buffer)), &buffer[0], &bufferUsed); err != nil { - switch err { + switch err { //nolint:errorlint // This is an errno or nil. case ERROR_NO_MORE_ITEMS: break loop case ERROR_INSUFFICIENT_BUFFER: @@ -466,7 +485,7 @@ func offset(buffer []byte, reader io.Reader) (uint64, error) { var err error switch runtime.GOARCH { default: - return 0, fmt.Errorf("Unhandled architecture: %s", runtime.GOARCH) + return 0, fmt.Errorf("unhandled architecture: %s", runtime.GOARCH) case "amd64": err = binary.Read(reader, binary.LittleEndian, &dataPtr) if err != nil { @@ -489,8 +508,8 @@ func offset(buffer []byte, reader io.Reader) (uint64, error) { offset := dataPtr - bufferPtr if offset > uint64(len(buffer)) { - return 0, fmt.Errorf("Invalid pointer %x. Cannot dereference an "+ - "address outside of the buffer [%x:%x].", dataPtr, bufferPtr, + return 0, fmt.Errorf("invalid pointer %x: cannot dereference an "+ + "address outside of the buffer [%x:%x]", dataPtr, bufferPtr, bufferPtr+uint64(len(buffer))) } @@ -503,7 +522,7 @@ func readString(buffer []byte, reader io.Reader) (string, error) { offset, err := offset(buffer, reader) if err != nil { // Ignore NULL values. - if err == ErrorEvtVarTypeNull { + if err == ErrorEvtVarTypeNull { //nolint:errorlint // This is never wrapped. return "", nil } return "", err @@ -517,11 +536,11 @@ func evtRenderProviderName(renderBuf []byte, eventHandle EvtHandle) (string, err var bufferUsed, propertyCount uint32 err := _EvtRender(providerNameContext, eventHandle, EvtRenderEventValues, uint32(len(renderBuf)), &renderBuf[0], &bufferUsed, &propertyCount) - if err == ERROR_INSUFFICIENT_BUFFER { - return "", sys.InsufficientBufferError{err, int(bufferUsed)} + if err == ERROR_INSUFFICIENT_BUFFER { //nolint:errorlint // This is an errno or nil. + return "", sys.InsufficientBufferError{Cause: err, RequiredSize: int(bufferUsed)} } if err != nil { - return "", fmt.Errorf("evtRenderProviderName %v", err) + return "", fmt.Errorf("evtRenderProviderName: %w", err) } reader := bytes.NewReader(renderBuf) @@ -532,14 +551,15 @@ func renderXML(eventHandle EvtHandle, flag EvtRenderFlag, renderBuf []byte, out var bufferUsed, propertyCount uint32 err := _EvtRender(0, eventHandle, flag, uint32(len(renderBuf)), &renderBuf[0], &bufferUsed, &propertyCount) - if err == ERROR_INSUFFICIENT_BUFFER { - return sys.InsufficientBufferError{err, int(bufferUsed)} + if err == ERROR_INSUFFICIENT_BUFFER { //nolint:errorlint // This is an errno or nil. + return sys.InsufficientBufferError{Cause: err, RequiredSize: int(bufferUsed)} } if err != nil { return err } if int(bufferUsed) > len(renderBuf) { + //nolint:stylecheck // These are proper nouns. return fmt.Errorf("Windows EvtRender reported that wrote %d bytes "+ "to the buffer, but the buffer can only hold %d bytes", bufferUsed, len(renderBuf)) diff --git a/winlogbeat/sys/wineventlog/wineventlog_windows_test.go b/winlogbeat/sys/wineventlog/wineventlog_windows_test.go index ff4fe566e9c..e6b494e3b24 100644 --- a/winlogbeat/sys/wineventlog/wineventlog_windows_test.go +++ b/winlogbeat/sys/wineventlog/wineventlog_windows_test.go @@ -19,79 +19,163 @@ package wineventlog import ( "bytes" + "encoding/xml" + "flag" + "fmt" + "io" "os" "path/filepath" + "reflect" + "strings" "testing" + "github.com/google/go-cmp/cmp" "github.com/stretchr/testify/assert" -) - -var sysmonEvtx string -func init() { - var err error - sysmonEvtx, err = filepath.Abs("testdata/sysmon-9.01.evtx") - if err != nil { - panic(err) - } + "github.com/elastic/beats/v7/winlogbeat/sys/winevent" +) - if _, err = os.Lstat(sysmonEvtx); err != nil { - panic(err) - } -} +var updateXML = flag.Bool("update", false, "update XML golden files from evtx files in testdata") + +func TestWinEventLog(t *testing.T) { + for _, test := range []struct { + path string + events int + }{ + {path: "application-windows-error-reporting.evtx", events: 1}, + {path: "sysmon-9.01.evtx", events: 32}, + {path: "ec1.evtx", events: 1}, // eventcreate /id 1000 /t error /l application /d "My custom error event for the application log" + {path: "ec2.evtx", events: 1}, // eventcreate /id 999 /t error /l application /so WinWord /d "Winword event 999 happened due to low diskspace" + {path: "ec3.evtx", events: 1}, // eventcreate /id 5 /t error /l system /d "Catastrophe!" + {path: "ec4.evtx", events: 1}, // eventcreate /id 5 /t error /l system /so Backup /d "Backup failure" + {path: "ec3and4.evtx", events: 2}, // ec3 and ec3 exported as a single evtx. + {path: "original.evtx", events: 5}, // a capture from a short generation of the eventlog WindowsEventLogAPI test. + {path: "experimental.evtx", events: 5}, // a capture from a short generation of the eventlog WindowsEventLogAPIExperimental test. + } { + t.Run(test.path, func(t *testing.T) { + evtx, err := filepath.Abs(filepath.Join("testdata", test.path)) + if err != nil { + t.Fatal(err) + } + xmlPath := evtx[:len(evtx)-len("evtx")] + "xml" -func TestEvtOpenLog(t *testing.T) { - h, err := EvtOpenLog(0, sysmonEvtx, EvtOpenFilePath) - if err != nil { - t.Fatal(err) - } - defer Close(h) -} + if _, err = os.Lstat(evtx); err != nil { + t.Fatal(err) + } -func TestEvtQuery(t *testing.T) { - h, err := EvtQuery(0, sysmonEvtx, "", EvtQueryFilePath) - if err != nil { - t.Fatal(err) + t.Run("EvtOpenLog", func(t *testing.T) { + h, err := EvtOpenLog(0, evtx, EvtOpenFilePath) + if err != nil { + t.Fatal(err) + } + defer Close(h) //nolint:errcheck // This is just a resource release. + }) + + t.Run("EvtQuery", func(t *testing.T) { + h, err := EvtQuery(0, evtx, "", EvtQueryFilePath) + if err != nil { + t.Fatal(err) + } + defer Close(h) //nolint:errcheck // This is just a resource release. + }) + + t.Run("ReadEvtx", func(t *testing.T) { + // Open .evtx file. + h, err := EvtQuery(0, evtx, "", EvtQueryFilePath|EvtQueryReverseDirection) + if err != nil { + t.Fatal(err) + } + defer Close(h) //nolint:errcheck // This is just a resource release. + + // Get handles to events. + buf := make([]byte, 32*1024) + var out io.Writer + if *updateXML { + f, err := os.Create(xmlPath) + if err != nil { + t.Fatalf("failed to create golden file: %v", err) + } + defer f.Close() + out = f + } else { + out = &bytes.Buffer{} + } + var count int + for { + handles, err := EventHandles(h, 8) + if err == ERROR_NO_MORE_ITEMS { //nolint:errorlint // This is never wrapped. + t.Log(err) + break + } + if err != nil { + t.Fatal(err) + } + + // Read events. + for _, h := range handles { + if err = RenderEventXML(h, buf, out); err != nil { + t.Fatal(err) + } + Close(h) //nolint:errcheck // This is just a resource release. + fmt.Fprintln(out) + count++ + } + } + if !*updateXML { + f, err := os.Open(xmlPath) + if err != nil { + t.Fatalf("failed to read golden file: %v", err) + } + want, err := unmarshalXMLEvents(f) + if err != nil { + t.Fatalf("failed to unmarshal golden events: %v", err) + } + got, err := unmarshalXMLEvents(out.(*bytes.Buffer)) + if err != nil { + t.Fatalf("failed to unmarshal obtained events: %v", err) + } + if !reflect.DeepEqual(want, got) { + t.Errorf("unexpected result for %s: got:- want:+\n%s", test.path, cmp.Diff(want, got)) + } + } + + if count != test.events { + t.Errorf("expected to read %d events but got %d from %s", test.events, count, test.path) + } + }) + }) } - defer Close(h) } -func TestReadEvtx(t *testing.T) { - // Open .evtx file. - h, err := EvtQuery(0, sysmonEvtx, "", EvtQueryFilePath|EvtQueryReverseDirection) - if err != nil { - t.Fatal(err) - } - defer Close(h) - - // Get handles to events. - buf := make([]byte, 32*1024) - out := new(bytes.Buffer) - count := 0 +// unmarshalXMLEvents unmarshals a complete set of events from the XML data +// in the provided io.Reader. GUID values are canonicalised to lowercase. +func unmarshalXMLEvents(r io.Reader) ([]winevent.Event, error) { + var events []winevent.Event + decoder := xml.NewDecoder(r) for { - handles, err := EventHandles(h, 8) - if err == ERROR_NO_MORE_ITEMS { - t.Log(err) - break - } + var e winevent.Event + err := decoder.Decode(&e) if err != nil { - t.Fatal(err) - } - - // Read events. - for _, h := range handles { - out.Reset() - if err = RenderEventXML(h, buf, out); err != nil { - t.Fatal(err) + if err != io.EOF { //nolint:errorlint // This is never wrapped. + return nil, err } - Close(h) - count++ + break } + events = append(events, canonical(e)) } + return events, nil +} - if count != 32 { - t.Fatal("expected to read 32 events but got", count, "from", sysmonEvtx) +// canonical return e with its GUID values canonicalised to lower case. +// Different versions of Windows render these values in different cases; ¯\_(ツ)_/¯ +func canonical(e winevent.Event) winevent.Event { + e.Provider.GUID = strings.ToLower(e.Provider.GUID) + for i, kv := range e.EventData.Pairs { + if strings.Contains(strings.ToLower(kv.Key), "guid") { + e.EventData.Pairs[i].Value = strings.ToLower(kv.Value) + } } + return e } func TestChannels(t *testing.T) { diff --git a/x-pack/winlogbeat/Jenkinsfile.yml b/x-pack/winlogbeat/Jenkinsfile.yml index 9eb81c51632..4971257eefa 100644 --- a/x-pack/winlogbeat/Jenkinsfile.yml +++ b/x-pack/winlogbeat/Jenkinsfile.yml @@ -29,6 +29,11 @@ stages: platforms: ## override default labels in this specific stage. - "windows-2019" stage: mandatory + windows-2022: + mage: "mage build unitTest" + platforms: ## override default labels in this specific stage. + - "windows-2022" + stage: mandatory windows-2019: mage: "mage build unitTest" platforms: ## override default labels in this specific stage.