From: Max Vilimpoc Date: Sat, 29 Aug 2026 17:38:00 +0000 (+0200) Subject: dotfiles: let the group read the kernel logger ACL it was granted X-Git-Url: https://vilimpoc.org/repos/dotfiles/commitdiff_plain/d52d627830e8e04a7ccada4b0725474b91281656 dotfiles: let the group read the kernel logger ACL it was granted The rights mask handed to EventAccessControl was 0x0FE1 -- the WMI and TRACELOG rights and nothing else. The SYSTEM and Administrators entries on that GUID carry 0x120FFF, and the missing 0x120000 is READ_CONTROL and SYNCHRONIZE: without READ_CONTROL the group cannot read back the descriptor it was just added to, so EventAccessQuery answers "access denied" whether or not the grant landed, which makes it useless as the one cheap probe available from the unelevated account. Now 0x120FE1. Also corrected, in the step and the README: the ACE is machine state, and a logon does nothing for it. ETW reads these descriptors into a cache, so a reboot is what is expected to put it into effect -- the ACE is in the descriptor (D:...(A;;0xfe1;;;LU)) and xperf -on base is still denied from a fresh shell on the running system. A first run therefore wants both: a new logon for the group membership and the privilege, a reboot for this. Not yet confirmed: whether the reboot is in fact sufficient. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01YMh8i2QzkHNdE3MkKfcaT6 --- diff --git a/README.md b/README.md index 421e1fe..9615def 100644 --- a/README.md +++ b/README.md @@ -178,8 +178,11 @@ throwaway VM reachable from a Linux host. Two consequences worth knowing. A privilege and a group membership are both read into the access token **at logon**, so the account must sign out and back in for 1 and 2 — any new logon does it, and an `ssh` login into the box is the - quick way to check without dropping the desktop. (The ACE in 3 is machine - state, read when a session starts, so it applies immediately.) And this only + quick way to check without dropping the desktop. The ACE in 3 is machine state + instead, and a logon does nothing for it: ETW reads these descriptors into a + cache, so it takes a **reboot** — with the ACE written and readable, `xperf -on + base` was still denied from a fresh shell on the running system. Plan on both + on a first run. And this only helps a **non-admin** account: UAC hands an administrator a filtered token carrying just five harmless privileges, so an admin's ordinary shell still cannot trace however the policy reads. Verify from the target account, diff --git a/setup-windows-with-uac.ps1 b/setup-windows-with-uac.ps1 index a546a0a..8e8e797 100644 --- a/setup-windows-with-uac.ps1 +++ b/setup-windows-with-uac.ps1 @@ -248,7 +248,12 @@ public static class EtwAcl # TRACELOG_ACCESS_KERNEL_LOGGER is the one that names the NT Kernel Logger # specifically; the rest are what any controller needs to create a session, # write it to disk and enable providers on it. -$EtwControllerRights = 0x0FE1 +# +# READ_CONTROL (0x20000) and SYNCHRONIZE (0x100000) go with them - the SYSTEM and +# Administrators entries on this GUID carry 0x120FFF. Without READ_CONTROL the +# group cannot read the descriptor back, which makes EventAccessQuery useless as +# a check on whether the grant landed: it answers "access denied" either way. +$EtwControllerRights = 0x120FE1 function Grant-EtwGuidAccess([string]$Guid, [string]$Sid, [uint32]$Rights) { Initialize-EtwAclType @@ -400,8 +405,12 @@ try { # For the same reason 1 and 2 do not take effect in an already-open session: the # account has to sign out and back in. Any NEW logon does it - an ssh login into # this box is one, which is the quick way to check without dropping the desktop. -# The ACE in 3 is machine state, read when a session is started, so that one -# applies immediately. +# The ACE in 3 is machine state rather than token state, so a logon does nothing +# for it. ETW reads these descriptors into a cache, so a REBOOT is what is +# expected to put the change into effect: with the ACE written and readable in +# the descriptor, xperf -on base was still answering "Access is denied" from a +# fresh shell on the running system. So on a first run, plan on both - a new +# logon for 1 and 2, a reboot for 3. # # Analysis never needed any of this: wpa.exe opens an existing .etl as a plain # user. This step is only about collection. @@ -422,9 +431,13 @@ try { } # --- The kernel logger's own descriptor --- - # Idempotent: adding the ACE for a SID that already has it rewrites the same - # entry. Kept in its own try so that a failure here still leaves the group + # Safe to repeat: a second ACE for the same SID unions to the same access. + # Kept in its own try so that a failure here still leaves the group # membership below to be done - user-mode sessions work without it. + # + # ETW reads these descriptors out of the registry into a cache, so a REBOOT + # is what puts a change here into effect - not a new logon, which is what the + # group membership and the privilege need. Both, on a first run. try { Grant-EtwGuidAccess $SystemTraceControlGuid $PerfLogUsersSid $EtwControllerRights Write-Host (" Granted Performance Log Users the controller rights (0x{0:X4}, TRACELOG_ACCESS_KERNEL_LOGGER included) on SystemTraceControlGuid" -f $EtwControllerRights) @@ -489,7 +502,8 @@ try { } Write-Host '' - Write-Host " $target must sign out and back in before this takes effect." -ForegroundColor Yellow + Write-Host " $target must sign out and back in for the group and the privilege," -ForegroundColor Yellow + Write-Host ' and the box must be REBOOTED for the kernel logger ACE (ETW caches it).' -ForegroundColor Yellow Write-Host ' Then, from that account (NOT elevated):' -ForegroundColor Yellow Write-Host ' whoami /priv | findstr SeSystemProfilePrivilege' -ForegroundColor Yellow Write-Host ' xperf -on base ; xperf -stop C:\Temp\trace.etl' -ForegroundColor Yellow diff --git a/setup-windows.bat b/setup-windows.bat index 9dda32e..a42c118 100644 --- a/setup-windows.bat +++ b/setup-windows.bat @@ -8,6 +8,7 @@ winget install Anthropic.ClaudeCode winget install Brave.Brave winget install Git.Git +winget install Google.AndroidGPUInspector winget install Microsoft.DotNet.SDK.10 winget install Microsoft.PowerShell Microsoft.Sysinternals.ProcessExplorer Microsoft.Sysinternals.ProcessMonitor Microsoft.Sysinternals.SDelete Microsoft.VisualStudioCode Microsoft.WindowsTerminal winget install Oracle.VirtualBox