Stack intended-reader EVTX recovery on the approved native auditing batch

This commit is contained in:
Shirofune-Security committed 2026-09-22 14:56:09 +09:00
commit 1dfd3a92b9
37 files changed
+1933 -8

No files matched your search

+2
View File
@@ -15,3 +15,5 @@ The export fingerprints the mapping file, lists candidates and reasons per Event
The bundled CSV remains a historical candidate map, not a universally valid event-generation contract. For example, 4703 appears against both Token Right Adjusted and Authorization Policy Change. Microsoft's [Token Right Adjusted page](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-10/security/threat-protection/auditing/audit-token-right-adjusted) lists it, while the [4703 event page](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-10/security/threat-protection/auditing/event-4703) names Authorization Policy Change. WELA retains the conflict rather than inventing a build-independent resolution. Microsoft also states that Token Right Adjusted has no Failure events; setting a Failure mask is not proof of Failure records.
Fixtures check malformed/duplicate identifiers, unknown events, ambiguous 4703/object mappings, and independent RPC/token state through all four legacy baseline renderers. Windows CI runs [`auditpol /list /subcategory:* /v`](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/auditpol-list) and native policy queries under Windows PowerShell 5.1/PowerShell 7. These checks validate identifiers/readback, not generated event XML. Build-specific client, member-server, DC and CA event/outcome validation remains separate acceptance work for issue #380. Native Windows functionality only; Sysmon is out of scope.
A separate [native4703 attribution fixture](native-token-right-attribution.md) compares the two selected masks on disposable standalone Server2022/2025 hosts with actual fixed privilege-adjustment XML. It retains all other audit masks and records the build/UBR and provider schema. This bounded generation evidence leaves historical candidates conditional and does not grant detection readiness.
+2
View File
@@ -76,6 +76,8 @@ CrashOnAuditFail and all 59 audit masks. It never fills or clears a log, changes
retention, tests warning generation, or supplies OneSettings/Windows 11/DC/AD CS
acceptance.
A separate [native OneSettings acceptance fixture](native-onesettings-acceptance.md) exercises public policy and dependent-channel configuration on Server 2022 and the existing refusal on Server 2025, under both PowerShell engines. It verifies typed journals, idempotence, actual invalid-value refusals and exact cleanup. This remains settings evidence only.
Before closing issue #378, retain isolated Windows 11 and Server 2022 evidence of
an authorized benign OneSettings attempt with exact build/patch, policy, channel,
native event XML and collection result. Do not assume an EventID without inspecting
+30
View File
@@ -0,0 +1,30 @@
# Native public OneSettings configuration acceptance
The disposable acceptance fixture invokes the actual `WELA.ps1 audit-notifications` command under Windows PowerShell 5.1 and PowerShell 7. It verifies local configuration and the explicit Privacy channel dependency. It does not generate a OneSettings event or claim effective producer behavior, policy persistence, forwarding or Sigma readiness. Sysmon is excluded.
```powershell
./WELA.ps1 audit-notifications -NotificationAction Plan -NotificationControl OneSettings -EnablePrivacyChannel
./WELA.ps1 audit-notifications -NotificationAction Configure -NotificationControl OneSettings -EnablePrivacyChannel -DryRun
./WELA.ps1 audit-notifications -NotificationAction Configure -NotificationControl OneSettings -EnablePrivacyChannel -Auto -BackupPath C:\Evidence\onesettings-before -ResultsPath C:\Evidence\onesettings.json
```
Configure requires elevation and explicit control selection. Audit without a selection reads both notification controls. The CLI omits an unspecified control argument so these defaults and the required-selection error reach the command; passing an explicit null into the validated control parameter previously produced a binding error with a zero process exit.
Server 2022 requires the real installed `DataCollection.admx` machine mapping for `EnableOneSettingsAuditing` DWORD1, its existing native registry key and readable `Microsoft-Windows-Privacy-Auditing/Operational` metadata. Server 2025 remains unverified by the reviewed source and must refuse configuration. Tests preserve this gate; installing an ADMX alone does not establish support.
On Server 2022, `tests/OneSettingsConfigure.Windows.Tests.ps1 -AllowDisposableOneSettingsWrite` verifies:
- Plan and DryRun against an actually absent value and disabled channel, with no write journal or mutation.
- Policy-only Configure creates exactly DWORD1 and leaves the disabled channel unchanged.
- Explicit `-EnablePrivacyChannel` enables the channel after the producer policy is verified, preserving its existing larger buffer, retention, complete descriptor and other native configuration.
- A combined call from DWORD0 and a disabled channel writes policy then channel, retaining exact typed original records and native readback.
- Repeated configuration produces only AlreadyCompliant results and no write journal.
- Actual string and unreviewed DWORD2 values are preserved; failed producer prerequisites prevent the dependent channel action. Unsupported preview arguments are rejected before dispatch.
On Server 2025, Plan, Configure, DryRun and an explicit channel request exercise the existing unsupported-source refusal. They must not create the selected value, change a channel or write a pre-change journal. This is refusal evidence, not positive Server 2025 support.
The fixture is restricted to explicitly opted-in disposable GitHub-hosted standalone servers. Only the fixture temporarily prepares the selected value and channel. It retains original and restored typed policy, full channel XML, unrelated DataCollection values/descendants and owner/group/DACL, Security/System/Application/CAPI2 settings, service status/start type, Security warning/CrashOnAuditFail and all59 audit masks. Each cleanup check runs independently and records errors. Event records produced during testing are not restored. The fixture never clears a log, requests GPO refresh, modifies diagnostic-data upload policy or invokes a OneSettings download.
Owned public child processes have a three-minute deadline, bounded output, a bounded drain and confirmed termination before cleanup. The evidence manifest records commit, host/engine, source fingerprints and artifact hashes. These local hashes detect altered evidence; they are not signed attestation. Review the current four-way `Native public OneSettings configuration` workflow artifacts before relying on native acceptance.
The broader [audit-notifications guide](audit-notifications.md) describes prerequisites and remaining Windows11, DC/AD CS, event-generation and intended-reader/collector evidence for issue #378.
+27
View File
@@ -0,0 +1,27 @@
# Native Security 4703 audit attribution
The disposable `Native Security 4703 audit attribution` workflow tests the two historical audit-subcategory candidates for event 4703 on standalone Windows Server 2022/2025 under Windows PowerShell 5.1 and PowerShell 7. It does not add a production probe, change WELA policy recommendations, remove historical mapping candidates or grant Sigma readiness.
Microsoft's [Token Right Adjusted guidance](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-10/security/threat-protection/auditing/audit-token-right-adjusted) and [advanced audit-policy reference](https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/plan/security-best-practices/advanced-audit-policy-configuration) associate 4703 with token adjustment. The older [4703 event reference](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-10/security/threat-protection/auditing/event-4703) names Authorization Policy Change. [WELA's mapping review](audit-catalog-mappings.md) retains both historical candidates as conditional. Native evidence below is specific to the recorded Windows build/UBR, provider manifest, engine and fixed operation.
The opted-in test changes exactly two audit masks and the advanced-audit precedence DWORD on an isolated GitHub-hosted runner. First it sets Token Right Adjusted Events (`0CCE924A-69AE-11D9-BED3-505054503030`) to Success and Authorization Policy Change (`0CCE9231-69AE-11D9-BED3-505054503030`) to None. Then it reverses those two masks. The other 57 audit masks remain at their observed original values. This comparison establishes the selected two-mask behavior under that retained context; it is not an experiment with all other audit sources disabled.
The installed provider task definitions and independently read `wevtutil gp` XML must both name `SE_ADT_DETAILEDTRACKING_TOKENRIGHTADJ` with value 13317. The emitted header is checked against that reviewed runtime task; it is not inferred from a candidate event. The observed generic 4703 declaration reports task 0, and that declaration remains in the receipt alongside the runtime definition. The older Microsoft event example uses task 13570; this discrepancy is retained rather than presented as a universal mapping correction.
Each phase starts a fresh owned child. A test-only native helper requires an already-enabled `SeDebugPrivilege` in that child's primary token, disables it, reads the complete privilege inventory, restores its original attributes and verifies the complete inventory again. It refuses impersonation, missing or disabled privileges. It never grants a new right, removes a privilege, opens another process, performs a debug operation or changes an account's assigned rights. The executable path is read through `QueryFullProcessImageName` before the operation so `Get-Process` cannot introduce an extra privilege adjustment inside the measured operation.
Acceptance requires two distinct actual Security 4703 records in the TokenRight-only phase: exactly the fixed disable and restoration. The inverse phase must have no matching records during its bounded observation. A match requires the installed provider GUID/name, eventID/version/task, Security channel, success keyword, observed computer identity, fresh record boundary, owned PID/executable, subject and target SID/logon ID, and exact privilege direction/sentinel. The precise UTC envelope starts before the native adjustment and ends after the required native full-token after-snapshot. Individual syscall-return times and the inner privilege-inventory verification endpoint are also retained. Security logging can timestamp a record just after the adjustment call returns; the measured verification interval is part of the operation, with no artificial delay or padded interval accepted as evidence. A wider query only collects diagnostic candidates; the strict matcher determines attribution.
The child has a 90-second limit, bounded asynchronous output, a bounded drain and confirmed termination before fixture cleanup. Native event reads have a timeout and require one successful Security-channel status. Query errors, schema differences, extra attributable records, caps, missing events, policy drift or failed cleanup fail the fixture; they are never reported as an empty successful observation. Native events and diagnostic XML remain in the short-lived CI artifacts.
Retained evidence includes actual host/build/UBR, native audit name/GUID listing, all 59 original/prepared/restored masks, typed precedence state, full Security-channel configuration, service states, parent/child tokens and complete privilege arrays, precise timestamps, raw event XML, mapping review, source fingerprints and artifact hashes. Cleanup independently restores both selected masks and the original precedence value or absence, then checks all masks, full channel configuration, service states and parent token. It does not erase generated events or recreate a historical event-log contents snapshot; dispose of the runner.
Run only on the explicitly supported disposable hosted fixture:
```powershell
./tests/TokenRightAttribution.Tests.ps1
./tests/AuditCatalogMappings.Tests.ps1
./tests/TokenRightAttribution.Windows.Tests.ps1 -AllowDisposableAuditWrite
```
This is a build-specific regression for issue #380, not universal proof about Windows 11, domain controllers, AD CS, every privilege, failure auditing, remote forwarding, policy persistence or Sigma Boolean/field requirements. All functionality is built into Windows; Sysmon is excluded.
+30
View File
@@ -0,0 +1,30 @@
# Scoped incoming and domain NTLM auditing
`ntlm-auditing` reads or configures two distinct audit values without invoking the broad `configure` workflow. It never writes an NTLM restriction or exception. Configure requires an explicit selection and elevated native 64-bit PowerShell on reviewed Windows 11 builds 22000/22621/22631/26100/26200 or Server 2022/2025 builds 20348/26100. Product type, domain role and join state must agree; role/build overrides are refused. Winmgmt must already be running before any CIM observation.
| Selection | Exact value | Requested setting | Applicability |
| --- | --- | --- | --- |
| Incoming | `HKLM\SYSTEM\CurrentControlSet\Control\Lsa\MSV1_0\AuditReceivingNTLMTraffic` | DWORD 2, audit all accounts | Reviewed client and server roles |
| Domain | `HKLM\SYSTEM\CurrentControlSet\Services\Netlogon\Parameters\AuditNTLMInDomain` | DWORD 7, Enable all | Actual domain controller only |
| Both | Both rows above | Each applicable audit setting | Domain row remains NotApplicable on a non-DC |
```powershell
./WELA.ps1 ntlm-auditing -NtlmAuditAction Audit -ResultsPath audit.json
./WELA.ps1 ntlm-auditing -NtlmAuditAction Plan -NtlmAuditScope Incoming -ResultsPath plan.json
./WELA.ps1 ntlm-auditing -NtlmAuditAction Configure -NtlmAuditScope Incoming -DryRun -ResultsPath preview.json
./WELA.ps1 ntlm-auditing -NtlmAuditAction Configure -NtlmAuditScope Incoming -Auto -BackupPath ./before-incoming -ResultsPath incoming.json
# Run on the reviewed domain controller itself:
./WELA.ps1 ntlm-auditing -NtlmAuditAction Configure -NtlmAuditScope Domain -BackupPath ./before-domain -ResultsPath domain.json
```
Incoming accepts native DWORD 0/1/2 or an absent value. Domain accepts absent or DWORD 0/1/3/5/7, plus historical WELA DWORD 2 for migration to7. The report labels2 `LegacyValue2`; it does not invent its undocumented meaning or credit it as full auditing. All other values/types are refused. Existing parent keys are required. An absent audit value does not imply a measured clean-image default.
Audit and Plan are live read-only assessments. Plan is not an importable authorization file. Configure re-reads the actual host and typed selected state, writes an original `before.jsonl` receipt before mutation, checks for drift after consent, and verifies immediate and final readback. Applied, AlreadyCompliant, Skipped, Failed and Overridden remain distinct. Partial failures return nonzero even if another selected row succeeded. A skipped non-DC domain row can coexist with exit0; this means domain configuration was not applicable, not that domain auditing was enabled. RSoP matches are last-applied observations from `RSOP_RegistryValue`, may be stale or incomplete, and do not prove current ownership or persistence. The registry write is not atomic with GPO or another administrator.
Outgoing policy is managed separately by [outgoing-ntlm](outgoing-ntlm.md). This command preserves outgoing/incoming/domain restrictions, NTLM exceptions, channels, services and advanced audit masks. It does not authenticate, create domain objects, restart services, refresh GPO, or generate NTLM events. Registry compliance alone supplies no forwarding or Sigma credit. Sysmon is out of scope.
For manual recovery, retain the successful selected result and original journal. Review `Before.Policy` and current ownership/drift before restoring that exact typed value, or removing only that value if originally absent. Never remove the parent key, replay another control's receipt, or treat a failed/partial attempt as a confirmed configuration. No automatic rollback occurs.
Native acceptance uses disposable unjoined Server 2022/2025 under Windows PowerShell 5.1 and PowerShell 7. It exercises actual incoming absence/disabled/domain-account-only→all-account auditing, dry run, original journals, repeated Configure, actual non-DC Domain/Both skips, and independent preservation/cleanup. Portable tests exercise DC transitions including historical2, unknown values/types, conflicting hosts, prompt drift, write/readback errors and partial outcomes. Windows 11, joined member/CA, actual DC application, domain authentication/events, policy persistence and collector delivery remain separate acceptance work for #363.
Microsoft documents [incoming values0/1/2](https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-localpoliciessecurityoptions#networksecurity_restrictntlm_auditincomingntlmtraffic) and the [domain audit policy's DC applicability and separation from blocking](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-10/security/threat-protection/security-policy-settings/network-security-restrict-ntlm-audit-ntlm-authentication-in-this-domain). Domain 7 follows the already reviewed WELA domain-audit correction and its pinned baseline evidence; this addition isolates that setting into a dedicated command.
+2
View File
@@ -20,3 +20,5 @@ For manual recovery, inspect the selected successful result and its original `be
Native acceptance uses disposable unjoined Server2022/2025 hosts under PowerShell5.1/7, exercises actual absence/allow→audit, original journals, dry run, repeat, readback and exact cleanup. Existing enforcement and malformed values are never installed on a native runner merely for testing; portable regressions verify those preservation/refusal paths, prompt-time drift and failures. Native tests preserve incoming/domain policy, siblings/access descriptor, channels, service and all59 audit masks. Windows11/DC/ADCS acceptance, authentication behavior, representative NTLM events, GPO persistence and collector delivery remain separate work for #362. No Sigma credit is inferred. Built-in Windows only; Sysmon is excluded.
Microsoft distinguishes outgoing audit from deny, describes GPO precedence and identifies the NTLM Operational log for validation: [outgoing NTLM policy](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-10/security/threat-protection/security-policy-settings/network-security-restrict-ntlm-outgoing-ntlm-traffic-to-remote-servers).
For separate incoming and actual-DC domain audit configuration, use [ntlm-auditing](ntlm-auditing.md).
+1 -1
View File
@@ -52,7 +52,7 @@ ForwardedEvents enablement preserves its size, retention mode and security descr
[Native collector observations](wec-collector-observation.md) use complete bounded WEC name enumeration and strict Unicode XML reads. Failed or partial observations remain unknown; they never become permission to create a subscription. Raw Unicode descriptions/filters and actual disabled state are retained independently of the requested settings.
The supported input is the native Subscription namespace, SourceInitiated type, native EventLog URI, HTTP transport, ForwardedEvents destination and Normal/MinLatency/MinBandwidth delivery preset. Enabled, ReadExistingEvents, content format and locale must be explicit. QueryList uses unique numeric Query IDs, exact native channel paths and nonempty Select/Suppress XPath expressions. Wildcard/provider channel names, external-provider channels, Sysmon/EMET, DTDs, unknown settings and custom delivery are rejected. This checks supported structure, not Windows XPath execution; native `cs` remains the final syntax validator.
The supported input is the native Subscription namespace, SourceInitiated type, native EventLog URI, HTTP transport, ForwardedEvents destination and Normal/MinLatency/MinBandwidth delivery preset. Enabled, ReadExistingEvents, content format and locale must be explicit. QueryList uses unique numeric Query IDs, exact native channel paths and nonempty Select/Suppress XPath expressions. Wildcard/provider channel names, external-provider channels, Sysmon/EMET, DTDs, unknown settings and custom delivery are rejected. This checks supported structure, not Windows XPath execution; native `cs` remains the final syntax validator. Use the separate read-only [`wef-query` preflight](wef-query.md) to execute one exact selected QueryList on the local source under the actual caller token, with native Select/Suppress results and distinct empty/failure/partial evidence. It does not test the forwarding service token or remote delivery.
An empty `AllowedSourceDomainComputers` input is filled from the explicit `SourceSids`; a nonempty value must match that authorization exactly. No empty authorization reaches `wecutil`, avoiding Windows' broader default authorization. Non-domain/certificate authorization is not supported. The example Security 4740 filter is illustrative and is not a complete baseline or a recommendation to lock an account for testing.
+50
View File
@@ -0,0 +1,50 @@
# Native source QueryList preflight
`wef-query` executes the exact QueryList from one explicitly selected subscription in an existing WEF **Source** config against local Windows logs. It checks actual native query behavior and the current caller's read access, preserving matching event XML in a new private evidence directory. It changes no Windows settings, contacts no collector and creates no subscription or event.
```powershell
./WELA.ps1 wef-query -WefQueryConfigPath C:\WEF\source.json `
-WefQuerySubscriptionId 'WELA Native Security Example' `
-WefQueryOutputPath C:\Evidence\query-001 `
-WefQueryMaximumEvents 16
```
Use native 64-bit Windows PowerShell 5.1 or PowerShell 7 under the intended reader's session. The observed host must be within WELA's reviewed Windows 11 / Server 2022/2025 build scope, with EventLog and Winmgmt already running. The command does not start services, elevate, impersonate another user or refresh a token. `-Auto`, `-DryRun`, `-WhatIf`, alternate credentials, remote query options and unrelated configuration arguments are rejected. A source's current domain membership does not authorize a remote operation because this command performs none.
The source JSON and explicitly listed subscriptions use the existing [WEF deployment](wef-deployment.md) schema: collector FQDN/URI, domain-format source SIDs and supported built-in native subscription definitions. Select one exact, case-sensitive subscription ID from that config. The collector identity and requested enabled flag remain recorded operator inputs; neither becomes an observed collector setting or verified identity. An explicitly disabled subscription can still be preflighted against historical local records.
## Exact query and separate error diagnostics
The existing parser validates supported subscription structure, native channel paths, Select/Suppress clauses and excluded external providers. The extracted QueryList text is then passed directly to native `EvtQuery`; WELA does not rewrite XPath, remove suppressions, substitute a fixed query or enable tolerance for matching evidence. The query runs in reverse record order. Windows does not support reverse queries on Analytic/Debug channels; those native failures remain failures, without changing channel state or silently choosing another query mode. Every native channel status must be attributable to a selected channel, and every selected channel must have a reported status before a complete result is possible.
If strict query creation fails, its native error remains the primary outcome. A second, separately labeled native diagnostic query can return per-channel status codes with `EvtQueryTolerateQueryErrors`. Windows may recover only part of a malformed XPath under that flag, so **no records from the diagnostic query are read or accepted as matches**. Missing diagnostic details remain unknown. Numeric error codes are preserved without parsing localized message text.
| Status | Meaning |
| --- | --- |
| `MatchesObserved` | Strict query completed, every selected channel status succeeded, and at least one native matching event was retained. |
| `ReadAllowedEmpty` | Strict query completed with successful channel statuses and no matching events. Empty is distinct from denial, missing logs or invalid syntax. |
| `QueryFailed` | Strict query creation failed; inspect its error and the separate diagnostic channel statuses. |
| `Partial` | The strict query opened, but a cap, read failure, channel error or incomplete cleanup prevented completeness. Retained samples remain individual observations. |
| `Unverified` | Input, worker, context, provenance or artifact checks failed. Inspect the diagnostic and available evidence. |
Only the first two statuses return exit 0. A valid query can legitimately return no records, and a broad valid query can exceed the sample limit. A native success establishes behavior for the current local logs and actual caller at observation time; it does not prove that a future event, another account or the forwarding service will have the same result.
## Bounds and evidence
Each original input is limited to 1 MiB, with 4 MiB aggregate decoded text. The selected QueryList is limited to 65,536 UTF-16 characters, 16 distinct channels and 128 filters. `WefQueryMaximumEvents` accepts 1–64 (default 16). One extra native record is requested to distinguish an exact-sized result from a cap; the extra record is not rendered or retained. Native XML is bounded to 1 MiB of UTF-16 per record and 4 MiB of aggregate UTF-8 matching XML.
The fixed worker uses the same installed PowerShell engine and actual caller context. Its native query handles remain on one thread. Each `EvtNext` uses a five-second timeout; the parent bounds the entire worker to 45 seconds, with bounded output draining and termination waits. A timeout or unconfirmed worker termination cannot earn a complete result. Bounded source, native query-status arrays and pipe buffers prevent unconstrained result allocation.
The new output directory grants access to the current user, SYSTEM and local Administrators. Original inputs and parent ACLs are not changed. Paths must be ordinary local paths accepted by WELA's recovery artifact helpers; existing output directories and observed reparse paths are refused. Raw event payloads can contain sensitive operational data, so retain them as evidence under the intended reader's access policy.
Outputs include decoded `source-config.json`, `subscription.xml`, exact `query.xml`, the worker `request.json`, `worker.json`, individual `event-NNN.xml` matches and a final `manifest.json`. The manifest records original file paths/hashes, source fingerprints, query hash, actual host/DNS context, engine hash/version, before/after reader and channel observations, strict/diagnostic query results and artifact hashes. The worker retains each XML render’s native `PropertyCount` as information; the Server 2022/2025 validation runs observed 1 even though the API documentation specifies 0 for XML. XML parsing uses bounded UTF-16 byte length and its final terminator, following the string rendering contract, independently of that values-array count. The original byte hashes are distinct from the decoded text artifacts. Unsuccessful runs retain whatever evidence was available; a missing final manifest means the output is incomplete.
The worker's SID, logon, group attributes and privileges must match the caller and remain stable. Host, input bytes, implementation, engine, channel configuration and saved hashes are rechecked before completeness. Returned event channel/record identity and exact observed local computer names must be consistent; no same-label arbitrary DNS suffix is accepted. These checks are observations rather than an atomic channel snapshot, and hashes establish consistency rather than authenticating an evidence author.
`ConfigurationChanges` and `ReadyRuleCredit` remain zero. The result does not establish NETWORK SERVICE's effective token, source group membership, policy/SACL generation prerequisites, subscription delivery, origin of historical records, loss, forwarding latency, retention duration or Sigma readiness. Use [channel-read](channel-read.md) for a simple current-token channel read and [wef-arrival](wef-arrival.md) for the separate exact collector-presence workflow. Issue #368 still requires representative multi-host source/collector validation.
## Native validation
The disposable Server 2022/2025 workflow runs both PowerShell engines through the public command. It selects an independently read real System record, verifies complete XML equality, suppresses that same record to obtain a genuine empty result, exercises malformed XPath and a mixed missing-channel query, and proves the event cap with an extra native record. An owned standard user and temporary CAPI2 deny ACE exercise actual access denial. The fixture independently restores the original channel descriptor and removes its owned account, then compares profile/loaded-hive inventories, selected channels, services, all audit masks, precedence and the operator token. The alternate-account process explicitly avoids loading a Windows user profile. These temporary fixture changes are absent from the product. No domain setup, event generation or forwarding is claimed by this native suite.
Microsoft references: [EvtQuery](https://learn.microsoft.com/en-us/windows/win32/api/winevt/nf-winevt-evtquery), [query flags and partial XPath recovery](https://learn.microsoft.com/en-us/windows/win32/api/winevt/ne-winevt-evt_query_flags), [per-channel query information](https://learn.microsoft.com/en-us/windows/win32/api/winevt/nf-winevt-evtgetqueryinfo), [native property types](https://learn.microsoft.com/en-us/windows/win32/api/winevt/ne-winevt-evt_query_property_id), [EvtNext completeness and timeout](https://learn.microsoft.com/en-us/windows/win32/api/winevt/nf-winevt-evtnext), and [native event XML rendering](https://learn.microsoft.com/en-us/windows/win32/api/winevt/nf-winevt-evtrender).