Each event record holds its event as binary XML: a stream of tokens that build the XML of the event. Repeated structure is shared: an event is usually a template instance, a reference to a template stored once in the chunk plus the values to fill it. Microsoft documents the token grammar in [MS-EVEN6]; the layouts here follow Joachim Metz’s libevtx documentation, Windows XML Event Log (EVTX) format, which marks several fields as not yet understood. Numbers are little-endian; text is UTF-16LE.
libevtx, citing [MS-EVEN6], gives a document as an optional processing instruction, any number of fragments, an optional processing instruction and an end-of-file token. A fragment is a fragment header followed by an element or a template instance.
Tokens
Some token types carry a “has more data” flag, 0x40: on an element
start it means an attribute list follows; on an attribute that another attribute
follows; on value, CDATA and reference tokens that more data of the element’s or
attribute’s content follows.
| Token | Name (libevtx) | Fields after the token byte |
|---|---|---|
00 | BinXmlTokenEOF | None. |
01, 41 | Open start element (<) | Dependency identifier (2; 0xFFFF for none), data size (4), element name offset (4), then with 41 an attribute list. See elements. |
02 | Close start element (>) | None; element content follows. |
03 | Close empty element (/>) | None. |
04 | End element | None. |
05, 45 | Value | Value type (1), which libevtx gives as 01, string; then the character count (2) and the UTF-16LE text without a terminator. A text can span several value tokens. |
06, 46 | Attribute | Attribute name offset (4), then the attribute data: a value, a substitution, or a character or entity reference. |
07, 47 | CDATA section | Character count (2) and text. |
08, 48 | Character entity reference | The character value (2), written out as &#n;. |
09, 49 | Entity reference | Entity name offset (4). libevtx assumes only lt, gt, amp, quot and apos occur. |
0A | Processing instruction target | Name offset (4). |
0B | Processing instruction data | Character count (2) and text. |
0C | Template instance | See templates. |
0D | Normal substitution | Substitution identifier (2, 0 for the instance’s first value) and value type (1). |
0E | Optional substitution | The same; if the value’s type is null (00), the element is left out. |
0F | Fragment header | Major version (1) = 1, minor version (1) = 1, flags (1) = 0. |
For either substitution, an array value repeats the substitution once per element
(an empty array gives one empty element), and a size value (10) is paired
with a hexadecimal 32- or 64-bit integer value. A binary XML value (21)
holds an open start element, a fragment or a template instance.
Elements and attributes
An element is an element start and a close empty element token, or an element
start, a close start element token, the content and an end element token. The data
size counts everything after the first 5 or 7 bytes of the element start: the name,
attribute list, close tag, content and end tag. Name offsets count from the start of
the chunk; libevtx notes the name can be stored right there, before the attribute
list. Per [MS-EVEN6], as cited by libevtx, the dependency identifier is left out when
the element start is the value of a binary XML substitution. Name offsets are absent
in the binary XML of a Windows Event Template (WEVT_TEMPLATE)
resource.
An attribute list is a data size (4, not counting itself) and the
attributes; the last attribute uses token 06, the others
46.
Value types
| Type | Name | Value |
|---|---|---|
00 | Null | No value. |
01 | String | UTF-16LE, no terminator. |
02 | AnsiString | 8-bit text in a code page, no terminator. |
03, 04 | Int8, UInt8 | 1 byte. |
05, 06 | Int16, UInt16 | 2 bytes. |
07, 08 | Int32, UInt32 | 4 bytes. |
09, 0A | Int64, UInt64 | 8 bytes. |
0B, 0C | Real32, Real64 | IEEE 754 single and double. |
0D | Bool | A 32-bit integer, 0 or 1 (libevtx marks this as unconfirmed). |
0E | Binary | Bytes. |
0F | Guid | 16 bytes, little-endian. |
10 | SizeT | 32 or 64 bits, paired with 14 or 15. |
11 | FileTime | A 64-bit FILETIME. |
12 | SysTime | 16 bytes: year, month, day of week, day, hours, minutes, seconds, milliseconds, 2 bytes each. |
13 | Sid | An NT security identifier. |
14 | HexInt32 | 32-bit unsigned, shown in hexadecimal. |
15 | HexInt64 | 64-bit unsigned, shown in hexadecimal. |
20 | EvtHandle | Unknown. |
21 | BinXml | A binary XML fragment. |
23 | EvtXml | Unknown. |
Bit 0x80 marks an array of the type in the low bits. libevtx lists
81–8D and 8F–95; per MSDN, as it
cites, binary and binary XML arrays are not supported. Arrays of strings
(81, 82) are strings each with a terminating zero, one after
another; other arrays are the values back to back. The boolean and SID arrays
(8D, 93) are marked unconfirmed.
Names
Element, attribute, entity and processing-instruction names are referred to by their offset from the start of the chunk.
| Offset | Size | Field |
|---|---|---|
0 | 4 | Unknown (absent in WEVT_TEMPLATE resources) |
4 | 2 | Name hash; the algorithm is not known |
6 | 2 | Number of characters |
8 | varies | The name, UTF-16LE, with a terminating zero |
Templates
A template instance token (0C) is followed by the template definition
and then the template instance data. Offsets count from the token byte.
| Offset | Size | Field |
|---|---|---|
1 | 1 | Unknown (seen: 1) |
2 | 4 | Unknown (perhaps the template identifier) |
6 | 4 | Template definition data offset, from the start of the chunk. It points either directly after this field, where the rest of the definition follows, or to a definition stored earlier in the chunk. |
The definition data at that offset:
| Offset | Size | Field |
|---|---|---|
0 | 4 | Unknown (perhaps the next template definition’s offset); 0 if not used |
4 | 16 | Template identifier, a GUID |
20 | 4 | Data size: the fragment header, element and end-of-file token that follow |
24 | varies | A fragment header, the element tree with substitution tokens where values go, and an end-of-file token |
Then the instance data: the number of values (4), a 4-byte descriptor per value (size 2, type 1, and an unknown byte seen as 0), then the values’ data in order. Substitution tokens in the template pick values by identifier.