EvtxECmd Maps
This skill describes how an agent should understand, create, and validate
EvtxECmd map files in this repository (the files under evtx/Maps/ ending in
.map). Map files are YAML documents that tell EvtxECmd how to extract values
from an event's EventData (and optionally System) elements and project them
into a small set of standardized columns (UserName, RemoteHost,
ExecutableInfo, PayloadData1 … PayloadData6).
A starter template is included alongside this skill at
assets/!Channel-Name_Provider-Name_EventID.template. Always start a new
map by copying that template rather than writing one from scratch.
1. What a map file is
A map is a YAML file whose filename and four header fields together identify a
specific event:
| Header field |
Required |
Meaning |
Author |
optional |
Name / contact of the map author. |
Description |
required |
Human description of the event. No trailing period. |
EventId |
required |
The integer Event ID (matches <EventID> in the XML). |
Channel |
required |
The exact value from the <Channel> element. |
Provider |
required |
The exact value of <Provider Name="…">. Mandatory since December 2020 to disambiguate event IDs that are reused by multiple providers. |
Below the header is a Maps: sequence describing how to build each output
column, and an optional Lookups: sequence defining value-translation tables.
The map is matched to an event when all of Channel, Provider, and
EventId match the event's XML. The filename does not select the map, but it
must follow the naming rules below so duplicates can be detected.
Filename rules
Format:
<Channel-Name>_<Provider-Name>_<EventID>.map
- Underscores (
_) separate the three elements.
- Hyphens (
-) replace any spaces, slashes, or special characters within
Channel and Provider names.
- The extension must be
.map (lowercase is used throughout the repo).
- Filenames may be long; that is expected.
Example — for Channel = Microsoft-Windows-TaskScheduler/Operational,
Provider = Microsoft-Windows-TaskScheduler, EventID = 201:
Microsoft-Windows-TaskScheduler-Operational_Microsoft-Windows-TaskScheduler_201.map
To override an existing default map without losing your changes on update,
prepend 1_ to the filename. Maps load alphabetically, so the 1_… copy wins:
1_Security_Microsoft-Windows-Security-Auditing_4624.map
2. Authoring workflow
Get real XML for the event. Run EvtxECmd against a sample log to dump
the records to XML:
EvtxECmd.exe -f <your eventlog.evtx> --xml c:\temp\xml
Open the resulting XML and locate the event of interest. Note the values of
<Channel>, <Provider Name="…">, and <EventID>, and inspect the
<EventData> block for the <Data Name="…"> fields you want to surface.
Copy the template. Start from
assets/!Channel-Name_Provider-Name_EventID.template (also located at
evtx/Maps/!Channel-Name_Provider-Name_EventID.template). Save it under
evtx/Maps/ using the filename rules above.
Fill in the header. Set Author, Description, EventId, Channel,
Provider. There must be no blank line between Provider: and Maps:.
Define each Maps: entry. Each entry produces one output column:
Property: — must be exactly one of
UserName, RemoteHost, ExecutableInfo,
PayloadData1, PayloadData2, PayloadData3,
PayloadData4, PayloadData5, PayloadData6.
Use this exact casing (e.g. UserName, never Username).
PropertyValue: — the rendered string, with %name% placeholders for
every variable referenced in Values.
Values: — list of { Name, Value } pairs. Name must match a
%name% placeholder. Value is an XPath expression, normally
"/Event/EventData/Data[@Name=\"<FieldName>\"]". You can also index by
position: /Event/EventData/Data[1] (first <Data> node), [2], etc.
Refine: (optional, on a Values entry) — a regex applied to the XPath
result to extract a substring. Example:
Refine: "IPv4 address: [0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}".
- Delete any
Property blocks you don't need. Not every event has
enough data to fill all six PayloadDataN columns.
- When organizing
PayloadData1…PayloadData6 for an event that's similar
to existing maps (e.g. Sysmon), follow the column order used by those
maps for analyst consistency.
Quoting and escaping. XPath strings must be wrapped in double quotes,
and embedded quotes inside the XPath escaped with \". PropertyValue
strings that contain spaces, colons, or backslashes should be quoted, and a
literal backslash is written as \\ (e.g. "%domain%\\%user%").
Lookups (optional). Use a Lookups: block to translate raw values
(often numeric codes) into human-readable strings. The lookup is applied
when its Name matches the Name of a Values entry. To keep both raw
and translated values in the same column, reference the field twice with
different Names — only the one whose name equals a Lookups Name is
translated:
Lookups:
-
Name: WakeSourceType
Default: Unknown code
Values:
0: Unknown
1: Power button
3: Waking from sleep to hibernate
If the map has multiple lookup tables, nest them all under a single
Lookups: key (see Security_Microsoft-Windows-Security-Auditing_4769.map
and …_4771.map for examples).
Documentation footer. End the file with two commented blocks:
# Documentation: — one URL per line (Microsoft docs, blogs, research),
each line commented with #. Use # N/A if there is none.
# Example Event Data: — a sanitized copy of a real <Event>…</Event>
XML block, every line prefixed with #. Remove any sensitive data.
- The file must end with a single trailing newline (the
.yamllint rule
new-line-at-end-of-file is enabled).
Test against real data. Run EvtxECmd on the source log and confirm the
target columns are populated as expected before submitting.
3. Reference structure
This is the canonical shape of a map. The full template is in
assets/!Channel-Name_Provider-Name_EventID.template.
Author: Your name <you@example.com>
Description: Short description of the event
EventId: 4624
Channel: Security
Provider: Microsoft-Windows-Security-Auditing
Maps:
-
Property: UserName
PropertyValue: "%domain%\\%user%"
Values:
-
Name: domain
Value: "/Event/EventData/Data[@Name=\"SubjectDomainName\"]"
-
Name: user
Value: "/Event/EventData/Data[@Name=\"SubjectUserName\"]"
-
Property: PayloadData1
PropertyValue: "LogonType %LogonType%"
Values:
-
Name: LogonType
Value: "/Event/EventData/Data[@Name=\"LogonType\"]"
Lookups:
-
Name: LogonType
Default: Unknown
Values:
2: Interactive
3: Network
4: Batch
5: Service
# Documentation:
# https://learn.microsoft.com/...
#
# Example Event Data:
# <Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
# ...
# </Event>
4. Validating a map file
Before committing a new or modified map, an agent must validate it. CI
runs the same check via .github/workflows/verify.yml, which invokes
yamllint evtx/Maps using the rules in the repository's .yamllint. The
.yamllint yaml-files list explicitly includes *.map, so map files are
linted as YAML.
4.1 Structural / lint validation
Run from the repository root:
pip install yamllint
yamllint evtx/Maps
To target only the file you are editing:
yamllint evtx/Maps/<your-file>.map
The repo's .yamllint enforces (failures, not warnings):
braces, brackets, colons, commas, hyphens, indentation — correct
YAML punctuation and 2-space block indentation consistent with neighbors.
empty-lines — no stray blank lines (in particular, no blank line between
Provider: and Maps:).
key-duplicates — every key in a mapping must be unique. In a map file,
this means each Property: value (UserName, PayloadData1, …) may appear
at most once in Maps:, and each Name: inside a single Values: list
must be unique.
trailing-spaces — no spaces at end of line.
new-line-at-end-of-file — file must end with exactly one \n.
comments, comments-indentation, and truthy are configured as warnings
and will not fail CI, but should still be addressed when easy.
If yamllint evtx/Maps exits 0, the structural check passes.
4.2 Semantic checks the linter cannot catch
After yamllint is clean, also confirm by inspection:
- Filename matches headers. Filename is
<Channel>_<Provider>_<EventId>.map with /, spaces, and special chars in
Channel/Provider replaced by -. The Channel/Provider/EventId in the
filename match the corresponding header fields exactly.
- All required headers are present and non-placeholder:
Description,
EventId, Channel, Provider. Description has no trailing period.
Property values are from the allowed set with exact casing:
UserName, RemoteHost, ExecutableInfo, PayloadData1–PayloadData6.
- No duplicate
Property entries within Maps:.
- Every
%name% placeholder in PropertyValue has a matching Name
entry in that block's Values:, and vice versa (no orphan variables, no
unresolved placeholders).
- XPaths are quoted with
"…" and embedded " escaped as \".
Backslashes in PropertyValue strings are doubled (\\).
Lookups: is a single top-level key (all lookup tables are nested
under it), each with Name, Default, and Values of integer/string
pairs. A lookup Name matching a Values Name is what triggers
translation.
- Footer is present: a
# Documentation: block (URLs or N/A) and a
# Example Event Data: block containing a real, sanitized XML sample.
- File ends with a trailing newline.
- Test on real data: run EvtxECmd against a sample
.evtx and confirm
the produced CSV/JSON columns are populated correctly.
If any of the above fails, fix the map and re-run yamllint evtx/Maps
until it is clean.
5. Quick checklist for an agent creating a new map
- Dump the source
.evtx to XML and locate the target event.
- Copy
assets/!Channel-Name_Provider-Name_EventID.template to
evtx/Maps/<Channel>_<Provider>_<EventId>.map.
- Set
Author, Description, EventId, Channel, Provider.
- Replace the template's
Maps: blocks with Property entries that match
the actual event; delete unused PayloadDataN blocks.
- Add
Lookups: only if codes need translating; keep all tables under one
Lookups: key.
- Replace the template footer with real
# Documentation: URLs and a
sanitized # Example Event Data: XML sample.
- Ensure the file ends with a single newline and contains no trailing
whitespace and no blank line between
Provider: and Maps:.
- Run
yamllint evtx/Maps and fix any errors.
- Run the map against real data with EvtxECmd and confirm output columns.
Source: EricZimmerman/evtx — distributed by TomeVault.
1---2name: evtxecmd-maps3description: Understand, author, and validate EvtxECmd map files that normalize Windows event log EventData into first-class CSV/JSON columns. Use when this capability is needed.4---56# EvtxECmd Maps78This skill describes how an agent should understand, create, and validate9EvtxECmd map files in this repository (the files under `evtx/Maps/` ending in10`.map`). Map files are YAML documents that tell EvtxECmd how to extract values11from an event's `EventData` (and optionally `System`) elements and project them12into a small set of standardized columns (`UserName`, `RemoteHost`,13`ExecutableInfo`, `PayloadData1` … `PayloadData6`).1415A starter template is included alongside this skill at16`assets/!Channel-Name_Provider-Name_EventID.template`. **Always start a new17map by copying that template** rather than writing one from scratch.1819---2021## 1. What a map file is2223A map is a YAML file whose filename and four header fields together identify a24specific event:2526| Header field | Required | Meaning |27| -------------- | -------- | ------- |28| `Author` | optional | Name / contact of the map author. |29| `Description` | required | Human description of the event. No trailing period. |30| `EventId` | required | The integer Event ID (matches `<EventID>` in the XML). |31| `Channel` | required | The exact value from the `<Channel>` element. |32| `Provider` | **required** | The exact value of `<Provider Name="…">`. Mandatory since December 2020 to disambiguate event IDs that are reused by multiple providers. |3334Below the header is a `Maps:` sequence describing how to build each output35column, and an optional `Lookups:` sequence defining value-translation tables.3637The map is matched to an event when **all of** `Channel`, `Provider`, and38`EventId` match the event's XML. The filename does not select the map, but it39must follow the naming rules below so duplicates can be detected.4041### Filename rules4243Format:4445```46<Channel-Name>_<Provider-Name>_<EventID>.map47```4849- Underscores (`_`) separate the three elements.50- Hyphens (`-`) replace **any** spaces, slashes, or special characters within51 Channel and Provider names.52- The extension must be `.map` (lowercase is used throughout the repo).53- Filenames may be long; that is expected.5455Example — for `Channel = Microsoft-Windows-TaskScheduler/Operational`,56`Provider = Microsoft-Windows-TaskScheduler`, `EventID = 201`:5758```59Microsoft-Windows-TaskScheduler-Operational_Microsoft-Windows-TaskScheduler_201.map60```6162To override an existing default map without losing your changes on update,63prepend `1_` to the filename. Maps load alphabetically, so the `1_…` copy wins:6465```661_Security_Microsoft-Windows-Security-Auditing_4624.map67```6869---7071## 2. Authoring workflow72731. **Get real XML for the event.** Run EvtxECmd against a sample log to dump74 the records to XML:7576 ```77 EvtxECmd.exe -f <your eventlog.evtx> --xml c:\temp\xml78 ```7980 Open the resulting XML and locate the event of interest. Note the values of81 `<Channel>`, `<Provider Name="…">`, and `<EventID>`, and inspect the82 `<EventData>` block for the `<Data Name="…">` fields you want to surface.83842. **Copy the template.** Start from85 `assets/!Channel-Name_Provider-Name_EventID.template` (also located at86 `evtx/Maps/!Channel-Name_Provider-Name_EventID.template`). Save it under87 `evtx/Maps/` using the filename rules above.88893. **Fill in the header.** Set `Author`, `Description`, `EventId`, `Channel`,90 `Provider`. There must be **no blank line between `Provider:` and `Maps:`**.91924. **Define each `Maps:` entry.** Each entry produces one output column:93 - `Property:` — must be **exactly one of**94 `UserName`, `RemoteHost`, `ExecutableInfo`,95 `PayloadData1`, `PayloadData2`, `PayloadData3`,96 `PayloadData4`, `PayloadData5`, `PayloadData6`.97 Use this exact casing (e.g. `UserName`, never `Username`).98 - `PropertyValue:` — the rendered string, with `%name%` placeholders for99 every variable referenced in `Values`.100 - `Values:` — list of `{ Name, Value }` pairs. `Name` must match a101 `%name%` placeholder. `Value` is an XPath expression, normally102 `"/Event/EventData/Data[@Name=\"<FieldName>\"]"`. You can also index by103 position: `/Event/EventData/Data[1]` (first `<Data>` node), `[2]`, etc.104 - `Refine:` (optional, on a `Values` entry) — a regex applied to the XPath105 result to extract a substring. Example:106 `Refine: "IPv4 address: [0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}"`.107 - **Delete any `Property` blocks you don't need.** Not every event has108 enough data to fill all six `PayloadDataN` columns.109 - When organizing `PayloadData1`…`PayloadData6` for an event that's similar110 to existing maps (e.g. Sysmon), follow the column order used by those111 maps for analyst consistency.1121135. **Quoting and escaping.** XPath strings must be wrapped in double quotes,114 and embedded quotes inside the XPath escaped with `\"`. `PropertyValue`115 strings that contain spaces, colons, or backslashes should be quoted, and a116 literal backslash is written as `\\` (e.g. `"%domain%\\%user%"`).1171186. **Lookups (optional).** Use a `Lookups:` block to translate raw values119 (often numeric codes) into human-readable strings. The lookup is applied120 when its `Name` matches the `Name` of a `Values` entry. To keep both raw121 and translated values in the same column, reference the field twice with122 different `Name`s — only the one whose name equals a `Lookups` `Name` is123 translated:124125 ```yaml126 Lookups:127 -128 Name: WakeSourceType129 Default: Unknown code130 Values:131 0: Unknown132 1: Power button133 3: Waking from sleep to hibernate134 ```135136 If the map has multiple lookup tables, **nest them all under a single137 `Lookups:` key** (see `Security_Microsoft-Windows-Security-Auditing_4769.map`138 and `…_4771.map` for examples).1391407. **Documentation footer.** End the file with two commented blocks:141 - `# Documentation:` — one URL per line (Microsoft docs, blogs, research),142 each line commented with `#`. Use `# N/A` if there is none.143 - `# Example Event Data:` — a sanitized copy of a real `<Event>…</Event>`144 XML block, every line prefixed with `#`. Remove any sensitive data.145 - The file must end with a single trailing newline (the `.yamllint` rule146 `new-line-at-end-of-file` is enabled).1471488. **Test against real data.** Run EvtxECmd on the source log and confirm the149 target columns are populated as expected before submitting.150151---152153## 3. Reference structure154155This is the canonical shape of a map. The full template is in156`assets/!Channel-Name_Provider-Name_EventID.template`.157158```yaml159Author: Your name <you@example.com>160Description: Short description of the event161EventId: 4624162Channel: Security163Provider: Microsoft-Windows-Security-Auditing164Maps:165 -166 Property: UserName167 PropertyValue: "%domain%\\%user%"168 Values:169 -170 Name: domain171 Value: "/Event/EventData/Data[@Name=\"SubjectDomainName\"]"172 -173 Name: user174 Value: "/Event/EventData/Data[@Name=\"SubjectUserName\"]"175 -176 Property: PayloadData1177 PropertyValue: "LogonType %LogonType%"178 Values:179 -180 Name: LogonType181 Value: "/Event/EventData/Data[@Name=\"LogonType\"]"182Lookups:183 -184 Name: LogonType185 Default: Unknown186 Values:187 2: Interactive188 3: Network189 4: Batch190 5: Service191192# Documentation:193# https://learn.microsoft.com/...194#195# Example Event Data:196# <Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">197# ...198# </Event>199```200201---202203## 4. Validating a map file204205Before committing a new or modified map, an agent **must** validate it. CI206runs the same check via `.github/workflows/verify.yml`, which invokes207`yamllint evtx/Maps` using the rules in the repository's `.yamllint`. The208`.yamllint` `yaml-files` list explicitly includes `*.map`, so map files are209linted as YAML.210211### 4.1 Structural / lint validation212213Run from the repository root:214215```bash216pip install yamllint217yamllint evtx/Maps218```219220To target only the file you are editing:221222```bash223yamllint evtx/Maps/<your-file>.map224```225226The repo's `.yamllint` enforces (failures, not warnings):227228- `braces`, `brackets`, `colons`, `commas`, `hyphens`, `indentation` — correct229 YAML punctuation and 2-space block indentation consistent with neighbors.230- `empty-lines` — no stray blank lines (in particular, **no blank line between231 `Provider:` and `Maps:`**).232- `key-duplicates` — every key in a mapping must be unique. In a map file,233 this means each `Property:` value (`UserName`, `PayloadData1`, …) may appear234 **at most once** in `Maps:`, and each `Name:` inside a single `Values:` list235 must be unique.236- `trailing-spaces` — no spaces at end of line.237- `new-line-at-end-of-file` — file must end with exactly one `\n`.238239`comments`, `comments-indentation`, and `truthy` are configured as warnings240and will not fail CI, but should still be addressed when easy.241242If `yamllint evtx/Maps` exits 0, the structural check passes.243244### 4.2 Semantic checks the linter cannot catch245246After `yamllint` is clean, also confirm by inspection:247248- **Filename matches headers.** Filename is249 `<Channel>_<Provider>_<EventId>.map` with `/`, spaces, and special chars in250 Channel/Provider replaced by `-`. The Channel/Provider/EventId in the251 filename match the corresponding header fields exactly.252- **All required headers are present and non-placeholder:** `Description`,253 `EventId`, `Channel`, `Provider`. `Description` has no trailing period.254- **`Property` values are from the allowed set** with exact casing:255 `UserName`, `RemoteHost`, `ExecutableInfo`, `PayloadData1`–`PayloadData6`.256- **No duplicate `Property` entries** within `Maps:`.257- **Every `%name%` placeholder in `PropertyValue`** has a matching `Name`258 entry in that block's `Values:`, and vice versa (no orphan variables, no259 unresolved placeholders).260- **XPaths are quoted** with `"…"` and embedded `"` escaped as `\"`.261 Backslashes in `PropertyValue` strings are doubled (`\\`).262- **`Lookups:` is a single top-level key** (all lookup tables are nested263 under it), each with `Name`, `Default`, and `Values` of integer/string264 pairs. A lookup `Name` matching a `Values` `Name` is what triggers265 translation.266- **Footer is present:** a `# Documentation:` block (URLs or `N/A`) and a267 `# Example Event Data:` block containing a real, sanitized XML sample.268- **File ends with a trailing newline.**269- **Test on real data:** run EvtxECmd against a sample `.evtx` and confirm270 the produced CSV/JSON columns are populated correctly.271272If any of the above fails, fix the map and re-run `yamllint evtx/Maps`273until it is clean.274275---276277## 5. Quick checklist for an agent creating a new map2782791. Dump the source `.evtx` to XML and locate the target event.2802. Copy `assets/!Channel-Name_Provider-Name_EventID.template` to281 `evtx/Maps/<Channel>_<Provider>_<EventId>.map`.2823. Set `Author`, `Description`, `EventId`, `Channel`, `Provider`.2834. Replace the template's `Maps:` blocks with `Property` entries that match284 the actual event; delete unused `PayloadDataN` blocks.2855. Add `Lookups:` only if codes need translating; keep all tables under one286 `Lookups:` key.2876. Replace the template footer with real `# Documentation:` URLs and a288 sanitized `# Example Event Data:` XML sample.2897. Ensure the file ends with a single newline and contains no trailing290 whitespace and no blank line between `Provider:` and `Maps:`.2918. Run `yamllint evtx/Maps` and fix any errors.2929. Run the map against real data with EvtxECmd and confirm output columns.293294---295> Source: [EricZimmerman/evtx](https://github.com/EricZimmerman/evtx) — distributed by [TomeVault](https://tomevault.io).296<!-- tomevault:4.0:skill_md:2026-06-30 -->