]> vilimpoc.org git repositories - dotfiles/commit
dotfiles: let a standard account collect ETW traces
authorMax Vilimpoc <max@vilimpoc.org>
Sat, 29 Aug 2026 16:43:11 +0000 (18:43 +0200)
committerMax Vilimpoc <max@vilimpoc.org>
Tue, 1 Sep 2026 10:53:18 +0000 (12:53 +0200)
commit99725a30bdb3eee44c38e1fd9a28c060341aa058
tree69312ec1e64976900e0195120ddd5625f6fb7110
parent7d4887fe245e7643a497e87e04fc8f97d8ca436f
dotfiles: let a standard account collect ETW traces

Windows Performance Analyzer is not a Visual Studio component -- VS's own
Performance Profiler is a different, .diagsession-based tool that cannot open an
.etl -- it ships with xperf and wpr in the Windows Performance Toolkit, either
as an optional Windows SDK feature (OptionId.WindowsPerformanceToolkit) or
inside the ADK, which bundles the same toolkit.  The WPT step already installed
it; it now detects the toolkit DIRECTORY rather than just xperf.exe, prints the
version of each tool it found (wpa.exe included, since that is the one people
come looking for), and re-asserts the machine PATH entry -- comparing with the
trailing backslash trimmed, because the toolkit's own installer writes one and a
second spelling of the same directory is just noise.

Collection is the half that did not work for an ordinary account, and it fails
in two distinct ways because two distinct things are missing:

    xperf -on base            -> NT Kernel Logger: Access is denied. (0x5)
    wpr -start GeneralProfile -> Failed to enable the policy to profile system
                                 performance.

Controlling ANY event tracing session -- a user-mode one naming a single
provider included, which is the case that shows this is not only about the
kernel -- is checked against the security descriptor ETW keeps per provider
GUID, whose default grants the session-control rights to SYSTEM, Administrators,
the service accounts and BUILTIN\Performance Log Users, and to nobody else.
Switching on the kernel/system provider on top of that needs
SeSystemProfilePrivilege, held by default only by Administrators and
NT SERVICE\WdiServiceHost, and that is the one wpr names in its error.

So grant the privilege to the GROUP and put the account in the group:
membership alone becomes the switch, and enabling the next account is one
net localgroup away with no policy edit.  LsaAddAccountRights rather than a
secedit round-trip -- it adds exactly one right to exactly one SID and is a
no-op when already held, where secedit re-applies every user right on the box to
fix one of them.  SeDebugPrivilege is deliberately not granted: neither CPU
sampling nor walking stacks in your own processes needs it, and it is equivalent
to handing out administrator.

setup-windows.bat passes -TraceUser across the UAC boundary.  Accepting that
prompt with an administrator's credentials runs the elevated half AS that
administrator, so it cannot otherwise tell whose box this is.

Two limits, both documented at the step and in the README.  A privilege and a
group membership are read into the access token at LOGON, so the account has to
sign out and back in -- any new logon does, and an ssh login into the box is the
quick way to check without dropping the desktop.  And this only helps a
NON-ADMIN account: UAC hands an administrator a filtered token keeping five
harmless privileges, so an admin's ordinary shell still cannot trace however the
policy reads.  Analysis was never affected; wpa.exe opens an existing .etl as a
plain user.

Exercised under Windows PowerShell 5.1, which is what the batch file launches:
the script parses, the LSA interop compiles under the in-box CodeDom compiler,
the SID marshalling round-trips S-1-5-32-559, and LsaOpenPolicy fails cleanly
with "Access is denied" from a non-elevated shell.  Get-LocalGroup -SID resolves
the localised group name, and the toolkit detection finds the SDK's WPT and
correctly reports its PATH entry as already present.  The grants themselves are
unverified: they need an elevated run.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YMh8i2QzkHNdE3MkKfcaT6
README.md
setup-windows-with-uac.ps1
setup-windows.bat