Windows Event Log message strings support

For those of you following log2timeline-dev@ you might already know that the development version of plaso now has support to output Windows Event Log message strings. So now instead of having to rely on other tools or manually looking up every event identifier on eventid.net you can enjoy having full Windows Event log message strings in your timeline.

How to use

The message strings are generated in the formatting phase, hence run log2timeline.py as you did before:
log2timeline.py storage.plaso Security.evtx

But things are different when you run psort.py e.g.:
log2timeline.py storage.plaso

Before the Windows Event Log message strings support:
2012-03-14T08:13:44.905177+00:00,Content Modification Time,EVT,WinEVTX,[7040 / 0x1b80] Record Number: 12064 Event Level: 4 Source Name: Service Control Manager Computer Name: WKS-WIN764BITB.shieldbase.local Strings: ['Windows Modules Installer'  'auto start'  'demand start'  'TrustedInstaller'],winevtx,OS:/Test/System.evtx,-,1,15

After the Windows Event Log message strings support:
2012-03-14T08:13:44.905177+00:00,Content Modification Time,EVT,WinEVTX,[7040 / 0x1b80] Record Number: 12064 Event Level: 4 Source Name: Service Control Manager Computer Name: WKS-WIN764BITB.shieldbase.local Message string: The start type of the Windows Modules Installer service was changed from auto start to demand start. Strings: ['Windows Modules Installer'  'auto start'  'demand start'  'TrustedInstaller'],winevtx,OS:/Test/System.evtx,-,1,15

The Windows Event Log message string templates are stored in an SQLite database named winevt-rc.db. On Linux and Mac OS X this database is typically installed in: /usr/share/plaso/. Psort.py will typically look for the winevt-rc.db file in the following data locations:
<source file>/../data/
<sys.prefix>/share/plaso/

If psort.py finds a suitable winevt-rc.db file it will generate formatted Windows Event Log message strings as part of its output. However if it does not, the message strings are omitted.

If psort.py cannot find a suitable winevt-rc.db file or you want to use a custom one you can manually provide it with the data location, the directory that contains the winevt-rc.db file, e.g.:
psort.py --data mycase/plasodata/ plaso.dump

Note that it is possible that psort.py will generate a formatted Windows Event Log message string for some Windows Event Log events but not for others. The winevt-rc.db file that is  distributed with Plaso contains a fixed set of common Windows Event Log message string templates, however these message string templates can vary per installation. Since it is impossible for us to ship them all, we allow you to build your own winevt-rc.db instead.

Introduction into Windows Event Log message string template handling

Have you ever experienced Windows Event Viewer showing you events with message strings like "The description for Event ID 10016 from source Microsoft-Windows-DistributedCOM cannot be found."? The reason for this is that the available Windows Event Log message string templates varies per installation [Also see: KB165959].

As part of the libevt and libevtx projects that are used in plaso to read the Windows Event Log formats (EVT and EVTX), we needed to figure out how Event Viewer generates message strings. Since they are not stored within .Evt or .Evtx files we needed to figure out where are they stored and how can we read them. Alas the Windows internals documentation by Microsoft lacks the necessary details and therefore the following information was obtained by piecing together available information complemented with reverse engineering.

Windows (at minimum as of NT4) maintains a list of Event Log providers in the Windows Registry under the key:
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\EventLog\

This key contains a subkey per log type (e.g. System) and log source (e.g. Workstation):
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\EventLog\System\Workstation

This subkey contains a value named EventMessageFile. This value contains one or more filenames e.g. %SystemRoot%\System32\netmsg.dll

The message string templates are stored in these “message resource files”, which are PE/COFF executable files that contain a resource (".rsrc") section. One resource in this resource section should be a message-table resource, as shown below using Resource Hacker.


This message-table resource contains a list of the message string templates with identifiers that seem to match the event identifiers, at least for .Evt files. For .Evtx files the message identifier can be determined by combining the event identifier and qualifiers.

E.g. on Windows XP if the message resource is file: C:\Windows\System32\netmsg.dll and the event identifier is 3260 (0x00000cbc), the corresponding event message string would be:
This computer has been successfully joined to %1 '%2'.

Here %1 and %2 are placeholders to refer to respectively the first and second strings in the corresponding Event Log record. The actual order of the strings in the formatted string might vary, depending on the grammar of the language that the message string is being generated in.

Cases not mentioned here are how to deal with Multilingual User Interface (MUI) resource forwarding and parameter expansion. For more information about these see:

How to build your own winevt-rc.db

Extracting the message string templates for every plaso run can be wasteful in terms of processing instead plaso uses a portable message resource database (winevt-rc.db). To build your own winevt-rc.db you’ll need to use the scripts from the winevt-kb project. This project comes with the following scripts:
  • extract.py, which extracts the Event Log providers and message string templates from a mounted Windows volume or disk image.
  • export.py, which creates a portable version of the message resource database.

extract.py uses dfVFS to process a mounted Windows Volume or various types of disk images. To extract the Event Log providers and message string templates from a given disk image named win7.qcow2 run:
mkdir ./winevt-kb/
./extract.py --db ./winevt-kb/ ~/Images/win7.qcow2

This will create various SQLite database files under ./winevt-kb/. If you have a second disk image of a different Windows installation you would like to add to the database e.g. win2k8.vmdk run:
./extract.py --db ./winevt-kb/ ~/Images/win2k8.vmdk

Note that the message string templates are language (locale) dependent. E.g. on an Icelandic version of Windows the message resource files will contain message string templates in Icelandic (LCID: 0x040f). Extract.py will extract all the availble locales in a message resource or that of the locale indicated by Multilingual User Interface (MUI) resource forwarding.

Once you have extracted the message string templates from all relevant Windows installations you can create a portable message resource database by running:
python export.py --db winevt-rc.db --string_format pep3101 ./winevt-kb/

For more information see: winevt-kb wiki: Scripts

This portable message resource database can now be used by psort.py
psort.py --data ./ plaso.dump

Note that value of --data should point to the directory where winevt-rc.db is stored, in the example that is the current directory (or ".").

psort.py will output US English message strings (LCID: 0x0409) by default. You can set the preferred language by passing a language identifier e.g. Icelandic:
psort.py --language is-IS plaso.dump

Psort.py will fall back on US English if the message string template is not available in winevt-rc.db in the preferred language. If no US English message string template is available as well, the message string is omitted from the output.

Note that the Windows Event Log message strings support in both plaso and winevt-kb is ongoing process hence if you have question, ideas, find bugs reach out via the appropriate issue tracker or mailing list.

Additional details and related work

We are aware of related work like GrokEVT but it was not used in the creation of plaso’s Windows Event Log message strings support (or related projects). However during the implementation we have noticed from questions on the development mailing list that GrokEVT uses different terminology in some places, e.g. event RVA instead of message identifier, which makes things confusing as RVA (Relative Virtual Address) has a significant different meaning within the context of the PE/COFF format.

Be mindful before raising issues and asking questions and read the documentation of libevtlibevtx and libexe. Your question may be very well be answered there.

Comments

Popular posts from this blog

Parsing the $MFT NTFS metadata file

Incident Response in the Cloud

Container Forensics with Docker Explorer