Common misconceptions about Windows EventLogs

 Common misconceptions about Windows EventLogs


Background

I regularly get people new to DFIR reaching out with questions about Windows EventLogs and it saddens me that there are so many DFIR related write-ups out there that provide these people with incorrect and incomplete information about Windows EventLogs. Windows EventLog is a complex subsystem of Windows with various edge cases. Common misconceptions I come across regularly:


  1. EventID is globally unique.

  2. EventIDs directly map to event messages.

  3. All event strings are used in the message.

  4. All the event message information is in the template string.

  5. Template strings remain the same.

  6. Event XML is proper XML 1.0.

  7. Data element names in Event XML are unique.

  8. EventLogs and ETW are equivalent.


Hopefully this article will help debunk some of these misconceptions and provide people new to DFIR a reference to assess the reliability of information out there.


Misconception 1: EventID is globally unique

Probably one of the most common misconceptions about EventIDs is that they are globally unique. From “Event Identifiers (Event Logging)” by Microsoft [1]:


“Event identifiers uniquely identify a particular event. Each event source can define its own numbered events and the description strings to which they are mapped in its message file.”


"Each event source can define its own numbered events" implies that event identifiers are only unique given a specific event source (also known as locally/relatively unique). Unfortunately there are many sources out there that only reference the EventID without the event source and its version. 


If you want to validate this yourself, just lookup EventID 1 on for example MyEventlog. You might have noticed that besides multiple event sources there are also multiple messages for event source “WinVNC4”. This can happen due to differences between different versions of the same event source.


The “Event XML” references the event source name (represented by either “EventSourceName” or “Name”) in the "Provider" element:


<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">

  <System>

    <Provider Name="Microsoft-Windows-Search"

              Guid="{CA4E628D-8567-4896-AB6B-835B221F373F}"

              EventSourceName="Windows Search Service"/>


Windows uses the event source name or identifier (“Guid” attribute) for example in the “Services\EventLog” and/or “WINEVT\Publishers” Windows Registry keys [2] that contain more information about where the event messages are stored.


Misconception 2: EventIDs directly map to event messages

From “Windows XML Event Log (EVTX) format” section “5.4. Externally stored values” [3] and projects like GrokEVT [4] we know that event messages are stored in (PE/COFF) message resource files. The event messages are stored with a message (template) string identifier. There are multiple ways to determine the message (template) string identifier from an EventIDs:

  • One-to-one mappings of the EventID to a message (template) string identifier

  • Mappings that use the EventID and Qualifiers attribute

  • Mappings that use the WEVT_TEMPLATE PE/COFF resource


Mappings that use the EventID and Qualifiers attribute

In some cases we need the EventID Qualifiers attribute to determine the message (template) string identifier. Let’s consider the following example :


<EventID Qualifiers="16384">7036</EventID>


The value of EventID with the Qualifiers correspond to the following message (template) string identifier:


message (template) string identifier = ( qualifiers << 16 ) | event identifier


16384 in hexadecimal is 0x4000

 7036 in hexadecimal is 0x1b7c

message (template) string identifier = ( 0x4000 << 16 ) | 0x1b7c = 0x40001b7c


Note that this has only been observed with event sources that are solely defined under the “Services\EventLog” Windows Registry key.


Mappings that use the WEVT_TEMPLATE (PE/COFF) resource

Another way the EventID can be mapped to a message (template) string identifier is via information in the WEVT_TEMPLATE resource. For example we have the following event sources:


Log source          : Microsoft-Windows-OfflineFiles

Identifier          : {95353826-4fbe-41d4-9c42-f521c6e86360}

Log type            : System

Event message files : %systemroot%\system32\cscsvc.dll


Log source          : Microsoft-Windows-BranchCacheSMB

Identifier          : {4a933674-fb3d-4e8d-b01d-17ee14e91a3e}

Event message files : %systemroot%\system32\cscsvc.dll


As you can see both event sources use the same event message resource files. If we extract the event identifiers and message (template) strings with the following PowerShell commands on Windows 10 20H2:


(Get-WinEvent -ListProvider Microsoft-Windows-OfflineFiles).Events | Format-Table Id, Description


  Id Description                                                                                                       

  -- ----------                                   

   1 The Offline Files service started successfully.                                                                   

   2 The Offline Files service is terminating.

...

2011 Rename of file %1 to file %2 was blocked. The source and/or target file name is an excluded file type.


(Get-WinEvent -ListProvider Microsoft-Windows-BranchCacheSMB).Events | Format-Table Id, Description


  Id Description                                                                                                       

  -- ----------                                   

3000 SMB BranchCache was enabled with min hash version %1 and max hash version %2.                                     

3001 SMB BranchCache was disabled.        

...


And compare that against a section of the message table PE/COFF resource in the %systemroot%\system32\en-US\cscsvc.dll.mui file (product and file version 10.0.19041.1).


message    : 55

identifier : 0xb00007db

data       : Rename of file %1 to file %2 was blocked. The source and/or target file name is an excluded file type.


message    : 56

identifier : 0xb1000bb8

data       : SMB BranchCache was enabled with min hash version %1 and max hash version %2.


message    : 57

identifier : 0xb1000bb9

data       : SMB BranchCache was disabled.


The %systemroot%\system32\en-US\cscsvc.dll.mui file contains message (template) strings for both the Microsoft-Windows-OfflineFiles and Microsoft-Windows-BranchCacheSMB event source and these to map to different message (template) string identifiers.


In the related %systemroot%\system32\cscsvc.dll file there is a WEVT_TEMPLATE (PE/COFF) resource that contains an “event definition” that maps the EventID to a message (template) string identifier [5]. For example:


identifier         : 0x0bb8

version            : 0

channel            : 16

level              : 4

opcode             : 0

task               : 0

keywords           : 0x8000000000000800

message identifier : 0xb1000bb8

template offset    : 0x00000000

opcode offset      : 0x00004b68

level offset       : 0x00004b98

task offset        : 0x00000000

...


Misconception 3: All event strings are used in the message

Typically an EventLog record specifies event strings. For example:


  <EventData>

    <Data Name="param1">Volume Shadow Copy</Data>

    <Data Name="param2">stopped</Data>

  </EventData>


Here the event strings “Volume Shadow Copy” and “stopped” are specified as EventData in the Event XML. In the example the corresponding event message (template) string is “The %1 service entered the %2 state.” where the first event string is used to replace the first placeholder (%1) in the final event message, etc. Where the final event message would be: “The Volume Shadow Copy service entered the stopped state.”


However there are cases where the event message (template) string does not contain a placeholder for a specific event string. For example for Microsoft-Windows-OfflineFiles EventID 2003 on Windows 10 20H2:


Sync info for %1%nServer copy exists, client copy deleted.%n%13%nSee details for more information.


As you can see this event message (template) string only has placeholders for the first and thirteenth event strings. How the other event strings should be interpreted in such cases based on the EventLog record, without additional facts, is pure speculation from a digital forensics point-of-view.


Misconception 4: All the event message information is in the template string

Event messages can use a concept referred to as “parameter expansion”. The following event message (template) string: “The %1 call failed for %2 with the following error:

%3.” and event strings in EventData:


  <EventData>

    <Data Name="param1">ScRegSetValueExW</Data>

    <Data Name="param2">FailureActions</Data>

    <Data Name="param3">%%5</Data>

  </EventData>


However EventLog viewer will translate this to the following string:


The ScRegSetValueExW call failed for FailureActions with the following error:

Access is denied.


As you can see “Access is denied.” is not defined either in the event message (template) string or in the event strings. Here %%5 corresponds to the message string with identifier 5 stored in the parameter message file of the event source [6].


Misconception 5: Template strings remain the same

Event message (template) string cans differ for different versions of (PE/COFF) message resource files. For example comparing the event message (template) string of Microsoft-Windows-BranchCacheSMB EventID 3000 on a Windows 7 and Windows 10 20H2 version of %systemroot%\system32\en-US\cscsvc.dll.mui:


Windows 7, product and file version 6.1.7600.16385:

SMB BranchCache was enabled.


Windows 10 20H2, product and file version 10.0.19041.1:

SMB BranchCache was enabled with min hash version %1 and max hash version %2.


Not only is the event message (template) string different on Windows 10 20H2 it also has placeholders. It is unclear if a Windows 7 EventLog record would contain the event strings that would be expected on Windows 10 20H2.


Misconception 6: Event XML is proper XML 1.0

Though [MS-EVEN6] [7] might hint that Event XML is proper XML 1.0, in practice it is not. The evtx-specimens project has a script that allows you to generate EventLog records with characters considered invalid XML 1.0 [8].


Another example of where Event XML can deviate from proper XML 1.0 can be seen in the following example:


<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">

  <System>

    <Provider Name="Microsoft-Windows-Store" Guid="{9C2A37F3-E5FD-5CAE-BCD1-43DAFEEE1FF0}"/>

    <EventID>8001</EventID>

    <Version>0</Version>

    <Level>4</Level>

    <Task>8001</Task>

    <Opcode>14</Opcode>

    <Keywords>0x8000100000000000</Keywords>

    <TimeCreated SystemTime="2018-09-03T01:54:01.996300600Z"/>

    <EventRecordID>218351</EventRecordID>

    <Correlation/>

    <Execution ProcessID="784" ThreadID="4980"/>

    <Channel>Microsoft-Windows-Store/Operational</Channel>

    <Computer>base-wkstn-01.shieldbase.lan</Computer>

    <Security UserID="S-1-5-19"/>

  </System>

  <EventData>

    <Data Name="Message">[1374] [000001B9730DC1F0:558F5D32-0827-EB7B-6AD6-D5DB4138B3AA] StopProcessing : Key:NegotiatingUnleased</Data>

    <Data Name="Function">StateMachine<class KeyMachine,class KeyState>::PumpEvents</Data>

    <Data Name="Source">onecoreuap\enduser\winstore\licensemanager\lib\statemachine.h</Data>

    <Data Name="Line Number">173</Data>

  </EventData>

</Event>


Here the Data element “Besides ‘StateMachine<class KeyMachine,class KeyState>::PumpEvents’“ is not proper. Well-formed XML should not contain < in the XML element data.


Misconception 7: Data element names in Event XML are unique

As you can see in the following Event XML names used for Data elements in EventData are not unique. There are multiple Data elements named “IoCount”, “TotalLatencyUs”, “TotalBytes” and “IoTypeIndex”.


<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">

  <System>

    <Provider Name="Microsoft-Windows-Ntfs" Guid="{3FF37A1C-A68D-4D6E-8C9B-F79E8B16C482}"/>

    <EventID>146</EventID>

    <Version>1</Version>

    <Level>4</Level>

    <Task>0</Task>

    <Opcode>0</Opcode>

    <Keywords>0x4000000000200000</Keywords>

    <TimeCreated SystemTime="2018-09-05T01:51:32.107675800Z"/>

    <EventRecordID>3291</EventRecordID>

    <Correlation/>

    <Execution ProcessID="4" ThreadID="15136"/>

    <Channel>Microsoft-Windows-Ntfs/Operational</Channel>

    <Computer>hostname</Computer>

    <Security UserID="S-1-5-18"/>

  </System>

  <EventData>

    <Data Name="VolumeCorrelationId">{4994EA25-0000-0000-0000-501F00000000}</Data>

    <Data Name="VolumeNameLength">2</Data>

    <Data Name="VolumeName">C:</Data>

    <Data Name="IsBootVolume">true</Data>

    <Data Name="HighIoLatencyCount">0</Data>

    <Data Name="IntervalDurationUs">3750962784</Data>

    <Data Name="NCReadIOCount">206</Data>

    <Data Name="NCReadTotalBytes">9112304</Data>

    <Data Name="NCReadAvgLatencyNs">11765267</Data>

    <Data Name="NCWriteIOCount">2858</Data>

    <Data Name="NCWriteTotalBytes">36175488</Data>

    <Data Name="NCWriteAvgLatencyNs">4904584</Data>

    <Data Name="FileFlushCount">560</Data>

    <Data Name="FileFlushAvgLatencyNs">14539870</Data>

    <Data Name="VolumeFlushCount">0</Data>

    <Data Name="VolumeFlushAvgLatencyNs">0</Data>

    <Data Name="FileLevelTrimCount">0</Data>

    <Data Name="FileLevelTrimTotalBytes">0</Data>

    <Data Name="FileLevelTrimExtentsCount">0</Data>

    <Data Name="FileLevelTrimAvgLatencyNs">0</Data>

    <Data Name="VolumeTrimCount">38</Data>

    <Data Name="VolumeTrimTotalBytes">8957952</Data>

    <Data Name="VolumeTrimExtentsCount">303</Data>

    <Data Name="VolumeTrimAvgLatencyNs">53391</Data>

    <Data Name="IoBucketsCount">44</Data>

    <Data Name="TotalBytesBucketsCount">40</Data>

    <Data Name="ExtentsBucketsCount">1</Data>

    <Data Name="IoCount">59</Data>

    <Data Name="IoCount">21</Data>

    ...

    <Data Name="IoCount">13</Data>

    <Data Name="TotalLatencyUs">151222351</Data>

    <Data Name="TotalLatencyUs">252569191</Data>

    ...

    <Data Name="TotalLatencyUs">2073327422</Data>

    <Data Name="TotalBytes">2813952</Data>

    <Data Name="TotalBytes">884736</Data>

    ...

    <Data Name="TotalBytes">8957952</Data>

    <Data Name="TrimExtentsCount">303</Data>

    <Data Name="IoTypeIndex">0</Data>

    <Data Name="IoTypeIndex">1</Data>

    ...

    <Data Name="IoTypeIndex">7</Data>

  </EventData>

</Event>


Misconception 8: EventLogs and ETW are equivalent

EventLog is a standard, centralized way for applications (and the operating system) to record important software and hardware events [9], for the purpose of system administration. 


ETW is short for Event Tracing for Windows. EWT is a kernel-level tracing facility that lets you log kernel or application-defined events to a log file [10]. Note that a log file in the context of ETW is typically an EWT trace log file (.etl) which is different from an EventLog file (.evt or .evtx).


In Windows Vista and later EventLog uses ETW [11], so in short, they are related but not equivalent. 


Conclusion

I hope this article has provided you more insight into common misconceptions about Windows EventLogs. As a digital forensic analyst you need to understand the information and potential edge cases of the data you are analyzing.


Windows EventLog is a complex subsystem of Windows with various edge cases, most of which have not been widely discussed within the digital forensics field. So if you feel you have an interesting one, please reach out on the Open Source DFIR Slack community.


Comments

Popular posts from this blog

Incident Response in the Cloud

Forensic Disk Copies in GCP & AWS