[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-81138":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":9,"language":10,"languages":9,"totalLinesOfCode":9,"stars":11,"forks":12,"watchers":13,"openIssues":14,"contributorsCount":14,"subscribersCount":14,"size":14,"stars1d":12,"stars7d":15,"stars30d":16,"stars90d":14,"forks30d":14,"starsTrendScore":17,"compositeScore":18,"rankGlobal":9,"rankLanguage":9,"license":19,"archived":20,"fork":20,"defaultBranch":21,"hasWiki":22,"hasPages":22,"topics":23,"createdAt":9,"pushedAt":9,"updatedAt":24,"readmeContent":25,"aiSummary":26,"trendingCount":14,"starSnapshotCount":14,"syncStatus":12,"lastSyncTime":27,"discoverSource":28},81138,"EtwWatcher","jonny-jhnson\u002FEtwWatcher","jonny-jhnson","Browse and diff ETW provider snapshots across Windows builds. Backed by ETWInspector.",null,"JavaScript",39,2,32,0,3,7,6,1.43,"MIT License",false,"main",true,[],"2026-06-12 02:04:11","# EtwWatcher\n\nA static web app for browsing and diffing snapshots of Windows ETW (Event Tracing for Windows) provider state across builds. Snapshots are produced by [ETWInspector](https:\u002F\u002Fgithub.com\u002Fjonny-jhnson\u002FETWInspector) and committed to this repo as NDJSON.\n\n## Using it\n\n> **Live site: https:\u002F\u002Fjonny-jhnson.github.io\u002FEtwWatcher\u002F**\n\nYou don't need to clone or run anything to use EtwWatcher. Open the live site and you can:\n\n- **Browse** any committed snapshot - filter providers by name\u002FGUID, scope by Manifest or MOF, drill into events, search descriptions\u002Fkeywords\u002Ftemplate fields.\n- **Diff** any two snapshots to see providers added, changed, and removed - including per-event field-level changes.\n- **Bring your own** snapshot via the upload zone at the top of the page. The file is parsed entirely in your browser; nothing is uploaded anywhere. Either plain `.ndjson` (straight from `Export-EtwSnapshot`) or gzipped `.ndjson.gz` works - the upload zone detects the format from the filename and decompresses in-browser when needed. You only need the `.ndjson.gz` form if you want a smaller file to share around; produce one by dropping the plain `.ndjson` into `snapshots\u002F` and running `.\u002Fscripts\u002Fupdate-manifest.ps1` (it compresses in place).\n- **Share findings** by copying the URL - it captures the active tab, picked snapshots, and all filters, so a teammate clicking your link sees the exact same view.\n\n## Why this exists\n\nDetection engineers, threat hunters, and Windows internals researchers frequently need to answer questions like:\n\n- What ETW providers and events exist on a given Windows build?\n- Which events were added, removed, or had their metadata changed between two builds?\n- Did a Patch Tuesday update silently rename or rewrite an event that an existing detection depends on?\n- Which keywords and template fields does a specific event expose, and how did those evolve?\n\nToday, getting this information usually means provisioning a VM, installing tooling, dumping provider state, and repeating the whole process on a second VM to compare. That's a meaningful barrier - and it's why a lot of detection content is written against assumptions that go stale silently.\n\nEtwWatcher does that work once. Real Windows snapshots are produced by [ETWInspector](https:\u002F\u002Fgithub.com\u002Fjonny-jhnson\u002FETWInspector), committed to this repo, and rendered in a browser-side UI. Anyone can browse, search, and diff provider state across Windows builds without standing up infrastructure - and link a teammate directly to a specific finding.\n\n## What's coming\n\nSnapshots will be added on an ongoing basis. The intent is to cover:\n\n- **Patch Tuesday cumulative updates** for currently-supported Windows builds, so you can see what shifted between e.g. `26200.7171` and `26200.7462`.\n- **Insider \u002F Canary builds** as Microsoft ships them - early signal on what providers and events are being added or restructured before they hit general availability.\n\nIf you want a specific build snapshotted, open an issue with the build number, or grab [ETWInspector](https:\u002F\u002Fgithub.com\u002Fjonny-jhnson\u002FETWInspector) and contribute the NDJSON directly via the [Adding a snapshot](#adding-a-snapshot-contributors) flow below.\n\n## What it does\n\n- **Browse** - pick a snapshot and explore every Manifest, MOF, or TraceLogging provider on that Windows build. Filter by provider (name, GUID, resource path), event description, keyword name, or template XML field. Toggle All \u002F Manifest \u002F MOF \u002F TraceLogging at the top to scope by schema source. Click a provider to see its events, levels, opcodes, keyword names, full template XML, and (for TraceLogging) the list of binaries the provider was discovered in.\n- **Diff** - pick two snapshots and see exactly what changed: providers added, providers whose events were added\u002Fremoved\u002Fchanged, and per-event field-level diffs with line-by-line highlighting on Description and Template. New schema versions of an existing event Id are paired against the closest version in the older snapshot and rendered as a \"new version\" diff (e.g. `Id 2 v1 -> v3 [NEW VERSION]`) instead of as separate \"added\" events.\n\nEverything runs in your browser. No backend, no telemetry. The page fetches the NDJSON files committed to `\u002Fsnapshots\u002F` and parses them client-side.\n\nManifest, MOF, and TraceLogging providers are covered (out of the four ETW provider types - WPP is not yet supported). Toggle between them in the Browse and Diff views with the schema-source segmented control.\n\n## Querying providers\n\nBrowse and Diff both expose the same four text filters plus a schema-source toggle. All filters are **case-insensitive substring matches** and are **AND-combined** - a provider has to satisfy every filter you've set. Leave a box empty to ignore that dimension.\n\n| Filter | What it matches |\n| --- | --- |\n| **Provider** | `ProviderName`, `ProviderGuid`, or `ResourceFilePath` (any of the three). Use this to pin to a known GUID, search a name fragment like `Kernel-Process`, or scope by binary path. |\n| **Description** | Substring of an event's `Description`. For Manifest events this is the human-readable description; for TraceLogging events it's the event name (e.g. `ProcessStarted`). |\n| **Keyword** | Substring of an ETW keyword name. Keywords are the 64-bit bitmask flags a provider declares (e.g. `KERNEL_THREATINT_KEYWORD_ALLOCVM_REMOTE` on Microsoft-Windows-Threat-Intelligence) - consumers enable a session by OR'ing these together to receive only events tagged with the matching bits. Use this filter when you know the keyword you want to subscribe to and need to find which provider declares it. |\n| **Template** | Substring of an event's template XML - field names, `inType`\u002F`outType` values. Use this to find every event that exposes a field like `ProcessId` or `TargetUserName`. |\n| **Schema toggle** | `All` \u002F `Manifest` \u002F `MOF` \u002F `TraceLogging`. Filters out providers from the other source kinds. |\n\nA few practical patterns:\n\n- **\"What providers carry a `CommandLine` field?\"** - clear all filters, set Template to `CommandLine`. The provider list narrows to providers with at least one event containing that field.\n- **\"Show me everything new in TraceLogging this build.\"** - in the Diff view, set Schema toggle to `TraceLogging`. Providers Added \u002F Changed \u002F Removed sections all scope down.\n- **\"Find this specific provider.\"** - paste the GUID (with or without braces) into the Provider box. Substring matching means partial GUIDs work too.\n- **\"Reset.\"** - click `Clear filters` next to the schema toggle.\n\nThe active filter set is also encoded into the URL (`#view=browse&snap=...&p=...&d=...&k=...&t=...&s=manifest`), so once a query lands on something interesting, copy the URL send to a teammate. By clicking it, they sees the same filtered view.\n\n### Querying your own snapshot\n\nUpload a snapshot via the drop zone at the top of the page and the Browse and Diff views work against it identically - same four filters, same schema toggle, same URL state. Plain `.ndjson` straight from `Export-EtwSnapshot` works; `.ndjson.gz` works too (decompressed in the browser). Uploaded files live only in the current tab; close it and they're gone.\n\n> Note: MOF *providers* are listed, but their *events* don't currently populate due to enumeration complexities - the MOF event metadata isn't always present in WMI even when the provider class is registered. Manifest and TraceLogging providers carry their full event metadata. Better approaches to MOF event enumeration are being actively explored.\n\n> Note on TraceLogging: events are not individually mapped to a specific provider. TraceLogging metadata is compiled into the binary itself as a `_TraceLoggingMetadata_t` structure beginning with the four-byte signature `ETW0`. It carries an array of provider metadata and an array of event metadata, but no per-event provider ID. When a binary declares multiple TraceLogging providers, each one ends up listed against the binary's full event set. If you need a real per-event binding, do static analysis on the binary via IDA or leverage a plugin like - [TLGMapper](https:\u002F\u002Fgithub.com\u002FAsuNa-jp\u002FTLGMapper) which walks `TraceLoggingWrite` calls and recovers the actual mapping. Better approaches to in-tool attribution are being actively explored.\n\n## ETW Provider Snapshots\n\nStored in [NDJSON](https:\u002F\u002Fgithub.com\u002Fndjson\u002Fndjson-spec) (newline-delimited JSON: one JSON object per line) in `\u002Fsnapshots\u002F`:\n\n- First line of each file is a header: `{\"SchemaVersion\":\"1.0\",\"OSVersion\":\"10.0.x.y.z\"}` (the OS version is `Major.Minor.Build.UBR`, read straight from the registry by ETWInspector).\n- Each subsequent line is one provider record.\n\n`snapshots\u002Fmanifest.json` is the index of which snapshots show up in the dropdowns - it's regenerated automatically by the deploy workflow whenever NDJSONs change.\n\n## Adding a snapshot (contributors)\n\n1. On a target machine, install [ETWInspector](https:\u002F\u002Fgithub.com\u002Fjonny-jhnson\u002FETWInspector) and run:\n   ```powershell\n   Import-Module .\\EtwInspector\\EtwInspectorModule\\EtwInspector.psd1 -Force\n   Export-EtwSnapshot C:\\Snapshots\\\u003Cfilename>.ndjson\n   ```\n   Naming convention: `\u003Cmajor>_\u003Cminor>_\u003Cbuild>_\u003CUBR>.ndjson` (e.g. `10_0_26200_7171.ndjson`).\n2. Copy the file into this repo's `snapshots\u002F` directory.\n3. Run `.\u002Fscripts\u002Fupdate-manifest.ps1` from the repo root **before committing**. This is required, not optional:\n   ```powershell\n   .\\scripts\\update-manifest.ps1\n   ```\n   The script gzips every plain `*.ndjson` in `snapshots\u002F` in place (the originals are removed; only `*.ndjson.gz` ships) and rewrites `snapshots\u002Fmanifest.json` sorted by OS version. TraceLogging-aware snapshots routinely exceed 100 MB, which is GitHub's hard per-file push limit - if you skip this step, your push is rejected outright. CI cannot fix this for you, since the rejection happens before the workflow runs.\n4. Commit the resulting `*.ndjson.gz` and the updated `manifest.json`, then push. The deploy workflow re-runs `update-manifest.ps1` on its end, but at that point it's a no-op safety net (the compression already happened locally; the manifest just gets validated).\n\nExisting manifest labels are preserved across re-runs (customizations like `(Insider)` survive); new entries get a default label of `Build \u003COSVersion>` that you can edit if you want a prettier name.\n\n## Running locally\n\nYou only need this if you're developing the site itself. The site is plain HTML + JS + Tailwind via CDN with no build step:\n\n```bash\n# Python\npython -m http.server 8080\n\n# Node\nnpx http-server -p 8080\n```\n\nThen open `http:\u002F\u002Flocalhost:8080`.\n\n> Note: opening `index.html` directly via `file:\u002F\u002F` won't work - the JS uses `fetch()` and ES module imports, both of which require an HTTP origin. Use a local server.\n\n## Tech\n\n- Vanilla HTML \u002F JS \u002F CSS\n- [Tailwind CSS](https:\u002F\u002Ftailwindcss.com) loaded via CDN\n- ES modules, no bundler\n- Hosted on [GitHub Pages](https:\u002F\u002Fpages.github.com\u002F)\n\n## Backing tool\n\nSnapshots are produced by [ETWInspector](https:\u002F\u002Fgithub.com\u002Fjonny-jhnson\u002FETWInspector) - a PowerShell module that enumerates Manifest, MOF, and TraceLogging providers and exports them as JSON or NDJSON. The diff algorithm in this site (`js\u002Fdiff.js`) is a JavaScript port of `Compare-EtwSnapshot` from the same module.\n\n## License\n\nMIT. See [LICENSE](.\u002FLICENSE).\n","EtwWatcher 是一个用于浏览和对比不同 Windows 版本间 ETW（Event Tracing for Windows）提供者状态快照的静态网页应用。其核心功能包括通过名称或GUID过滤提供者、按Manifest或MOF范围筛选、深入查看事件详情以及搜索描述、关键字和模板字段等，并支持两个快照之间的差异比较，展示提供者的增删改情况及每个事件字段级别的变化。此外，用户还可以上传自定义快照并在浏览器中直接解析，无需实际上传任何数据到服务器。该工具特别适用于检测工程师、威胁猎手及Windows内部研究者快速获取并对比ETW提供者与事件信息，尤其是在评估补丁更新对现有检测规则的影响时。基于JavaScript构建，易于使用且开放源代码。","2026-06-11 04:03:40","CREATED_QUERY"]