From d35b1374d00cd9870142613142429cd773f7d676 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=94=B0=E4=B8=AD=E3=82=B6=E3=83=83=E3=82=AF=20Isaac=20Ma?=
=?UTF-8?q?this?= <43838376+Shirofune-Security@users.noreply.github.com>
Date: Sun, 20 Sep 2026 13:58:49 +0900
Subject: [PATCH] Add opt-in native DNS and provider audit packs (#411)
* Add selective native provider packs with pinned rule and schema evidence
* Reference PR 411 in provider-pack changelogs
* Fix provider pack service reader export and CI exit propagation
---
.gitattributes | 2 +
.github/workflows/native-provider-packs.yml | 34 ++
CHANGELOG-Japanese.md | 1 +
CHANGELOG.md | 1 +
WELA.ps1 | 20 +-
config/native_provider_packs.json | 530 ++++++++++++++++++
.../04768e11-3acf-895f-9193-daae77c4678f.yml | 27 +
.../14b17417-8ae7-ff8e-fe36-28aaa337ccd5.yml | 31 +
.../1a850b71-6aef-4f31-a509-f31b2c778476.yml | 50 ++
.../2abf05fa-98f2-d00b-6a6a-12d07e55233e.yml | 31 +
.../40077f9e-f597-1087-0c4f-8901d1a07af4.yml | 40 ++
.../4f321a68-176a-4f1d-873a-8793bc49e3b0.yml | 51 ++
.../512e70f5-bf70-4de1-9375-2174999a7f8d.yml | 50 ++
.../6db38b96-3772-4cbf-a8ad-c65d8ac5134e.yml | 23 +
.../9b3ffe56-a479-9b35-d590-9b94c2f7fa35.yml | 30 +
.../provider_rule_sources/LICENSE-upstream.md | 17 +
config/provider_rule_sources/README.md | 3 +
.../c8e0edae-2335-591c-7057-1ac58f03e06c.yml | 42 ++
.../cd6eb342-9dcd-450d-b448-bebd97cb6e89.yml | 23 +
.../dadaca47-d760-88a9-fd35-cbe8a6237499.yml | 28 +
.../e1b0fd63-1017-1597-ec08-3f9e1021e564.yml | 80 +++
.../ec3b018a-d4dd-2d51-4a63-50d078f737dd.yml | 32 ++
.../f0b3a5e9-e4ee-ed23-3b27-4dd30c5974c8.yml | 37 ++
docs/native-provider-packs.md | 52 ++
modules/NativeProviders.psm1 | 2 +-
scripts/NativeProviderPacks.ps1 | 162 ++++++
tests/NativeProviderPacks.Tests.ps1 | 150 +++++
tests/NativeProviderPacks.Windows.Tests.ps1 | 44 ++
website/docs/resources/changelog.ja.md | 1 +
website/docs/resources/changelog.md | 1 +
30 files changed, 1593 insertions(+), 2 deletions(-)
create mode 100644 .github/workflows/native-provider-packs.yml
create mode 100644 config/native_provider_packs.json
create mode 100644 config/provider_rule_sources/04768e11-3acf-895f-9193-daae77c4678f.yml
create mode 100644 config/provider_rule_sources/14b17417-8ae7-ff8e-fe36-28aaa337ccd5.yml
create mode 100644 config/provider_rule_sources/1a850b71-6aef-4f31-a509-f31b2c778476.yml
create mode 100644 config/provider_rule_sources/2abf05fa-98f2-d00b-6a6a-12d07e55233e.yml
create mode 100644 config/provider_rule_sources/40077f9e-f597-1087-0c4f-8901d1a07af4.yml
create mode 100644 config/provider_rule_sources/4f321a68-176a-4f1d-873a-8793bc49e3b0.yml
create mode 100644 config/provider_rule_sources/512e70f5-bf70-4de1-9375-2174999a7f8d.yml
create mode 100644 config/provider_rule_sources/6db38b96-3772-4cbf-a8ad-c65d8ac5134e.yml
create mode 100644 config/provider_rule_sources/9b3ffe56-a479-9b35-d590-9b94c2f7fa35.yml
create mode 100644 config/provider_rule_sources/LICENSE-upstream.md
create mode 100644 config/provider_rule_sources/README.md
create mode 100644 config/provider_rule_sources/c8e0edae-2335-591c-7057-1ac58f03e06c.yml
create mode 100644 config/provider_rule_sources/cd6eb342-9dcd-450d-b448-bebd97cb6e89.yml
create mode 100644 config/provider_rule_sources/dadaca47-d760-88a9-fd35-cbe8a6237499.yml
create mode 100644 config/provider_rule_sources/e1b0fd63-1017-1597-ec08-3f9e1021e564.yml
create mode 100644 config/provider_rule_sources/ec3b018a-d4dd-2d51-4a63-50d078f737dd.yml
create mode 100644 config/provider_rule_sources/f0b3a5e9-e4ee-ed23-3b27-4dd30c5974c8.yml
create mode 100644 docs/native-provider-packs.md
create mode 100644 scripts/NativeProviderPacks.ps1
create mode 100644 tests/NativeProviderPacks.Tests.ps1
create mode 100644 tests/NativeProviderPacks.Windows.Tests.ps1
diff --git a/.gitattributes b/.gitattributes
index 6f1e0056..b167511f 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -2,3 +2,5 @@
/config/security_rules.json text eol=lf
/config/eid_subcategory_mapping.csv text eol=lf
/config/rule_eligibility_manifest.json text eol=lf
+# Full upstream rule artifacts retain their exact pinned bytes on every platform.
+/config/provider_rule_sources/*.yml -text whitespace=-blank-at-eol
diff --git a/.github/workflows/native-provider-packs.yml b/.github/workflows/native-provider-packs.yml
new file mode 100644
index 00000000..3fa128cd
--- /dev/null
+++ b/.github/workflows/native-provider-packs.yml
@@ -0,0 +1,34 @@
+name: Native provider pack regressions
+on:
+ push:
+ branches: ['**']
+ pull_request:
+ workflow_dispatch:
+permissions:
+ contents: read
+jobs:
+ provider-packs:
+ strategy:
+ fail-fast: false
+ matrix:
+ os: [windows-2022, windows-2025]
+ runs-on: ${{ matrix.os }}
+ timeout-minutes: 15
+ steps:
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
+ - name: Safe fixtures in Windows PowerShell 5.1
+ shell: powershell
+ run: |
+ ./tests/NativeProviderPacks.Tests.ps1
+ ./tests/NativeChannelAccess.Tests.ps1
+ - name: Real provider manifests and read-only CLI in Windows PowerShell 5.1
+ shell: powershell
+ run: ./tests/NativeProviderPacks.Windows.Tests.ps1 -OutputDirectory "$env:RUNNER_TEMP/provider-packs-51"
+ - name: Safe fixtures in PowerShell 7
+ shell: pwsh
+ run: |
+ ./tests/NativeProviderPacks.Tests.ps1
+ ./tests/NativeChannelAccess.Tests.ps1
+ - name: Real provider manifests and read-only CLI in PowerShell 7
+ shell: pwsh
+ run: ./tests/NativeProviderPacks.Windows.Tests.ps1 -OutputDirectory "$env:RUNNER_TEMP/provider-packs-7"
diff --git a/CHANGELOG-Japanese.md b/CHANGELOG-Japanese.md
index 3d2a8ef9..29fbd4a9 100644
--- a/CHANGELOG-Japanese.md
+++ b/CHANGELOG-Japanese.md
@@ -4,6 +4,7 @@
**改善:**
+- Windows標準のDNS Client/Server、CAPI2、WinRM、RDP Clientについて、明示的に選択するprovider-packsの監査・計画とチャネル設定を追加しました。固定した完全なルール定義と実際のプロバイダー・チャネル・イベントスキーマを確認し、DNSのチャネル名不一致や不明な前提条件を保持します。復旧記録付きの変更では大きいバッファ・保持方式・ACLを維持し、Analyticalと従来のDNSログは手動確認のみとします。イベント生成・バックエンド検証や検知範囲の向上は未確認です。 (#411) (@Shirofune-Security)
- 任意実行の`audit-notifications`を追加し、OneSettings監査とSecurityログ警告しきい値の監査・計画・設定に対応しました。対象とチャネル変更の明示指定、OS・ADMX確認、型付き復旧記録と変更検出を行い、既存の低いしきい値とチャネルACL・保存方式を保持します。ポリシー一致と実イベント生成を分け、Windowsラボの証拠とSigma利用可能性は未検証と表示します。 (#408) (@Shirofune-Security)
- 読み取り専用の`rule-eligibility`を追加し、ルール・対応表のハッシュ、ルールごとの判定理由、対象外の理由、分子・分母を明示します。任意で取り込んだラボ資料を、対応範囲を限定した完全なルール定義、ネイティブXML、設定、収集・クエリ実行の証拠と照合し、未対応・未確認の項目はConditionalとします。監査のCSV/JSON/HTMLとNavigator出力では、設定が有効なだけでルールを利用可能と判定しません。取り込んだReady判定は記録された環境・時点に限られ、実環境での一連の検証を保証しません。 (#407) (@Shirofune-Security)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b54ca6b4..c6311d16 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,7 @@
**Improvements:**
+- Added explicit native DNS Client/Server, CAPI2, WinRM and RDP Client provider-pack inventory and selective channel configuration. Pinned full rule definitions and live provider/channel/event schemas retain DNS channel mismatches and unknown prerequisites; journaled opt-in changes preserve larger buffers, retention and ACLs. Analytical/classic DNS remain manual-only, and no event/backend readiness uplift is claimed. (#411) (@Shirofune-Security)
- Added opt-in `audit-notifications` audit/plan/configure for OneSettings auditing and Security log warning thresholds, with explicit control/channel selections, reviewed host and ADMX gates, typed recovery journals and drift checks. Earlier warning thresholds and channel ACL/retention are preserved. Reports separate policy matches from warning/event generation; Windows lab evidence and Sigma eligibility remain unverified. (#408) (@Shirofune-Security)
- Added read-only `rule-eligibility` reports with pinned corpus/mapping hashes, per-rule reasons, explicit scope exclusions and numerator/denominator totals. Optional imported lab artifacts are checked against a narrow complete-rule parser, native XML, configuration, ingestion and query evidence; unsupported or incomplete cases stay Conditional. Audit CSV/JSON/HTML and Navigator outputs no longer treat enabled settings as proven usable rules. Imported Ready results apply only to their recorded context/time; no live end-to-end validation is implied. (#407) (@Shirofune-Security)
diff --git a/WELA.ps1 b/WELA.ps1
index fc5f8c69..377da37c 100644
--- a/WELA.ps1
+++ b/WELA.ps1
@@ -49,6 +49,8 @@
[ValidateRange(1,2147483647)][int]$LdapSearchTimeMs,
[ValidateRange(1,2147483647)][int]$LdapExpensiveThreshold,
[ValidateRange(1,2147483647)][int]$LdapInefficientThreshold,
+ [ValidateSet('List','Audit','Plan','Configure')][string]$ProviderAction = 'List',
+ [string[]]$ProviderPack,
[ValidateSet('Audit','Plan','Configure')][string]$NotificationAction = 'Audit',
[ValidateSet('OneSettings','SecurityWarning')][string[]]$NotificationControl,
[ValidateRange(1,90)][int]$WarningPercent = 90,
@@ -83,6 +85,7 @@ Import-Module (Join-Path $ScriptRoot "modules/EventLogSettings.psm1") -ErrorActi
. (Join-Path $ScriptRoot "scripts/EventLogConfiguration.ps1")
Import-Module (Join-Path $ScriptRoot "modules/NativeChannelAccess.psm1") -ErrorAction Stop
. (Join-Path $ScriptRoot "scripts/NativeChannelConfiguration.ps1")
+. (Join-Path $ScriptRoot "scripts/NativeProviderPacks.ps1")
Import-Module (Join-Path $ScriptRoot "modules/WefSubscriptions.psm1") -ErrorAction Stop
. (Join-Path $ScriptRoot "scripts/WefDeployment.ps1")
. (Join-Path $ScriptRoot "scripts/TargetedSaclPlanning.ps1")
@@ -1745,6 +1748,8 @@ Usage:
./WELA.ps1 channel-settings -ChannelAction Audit -WefQuerySet Both -ResultsPath channels.json
./WELA.ps1 channel-settings -ChannelAction Plan -GrantEventLogReaders
./WELA.ps1 channel-settings -ChannelAction Configure -GrantEventLogReaders -DryRun
+ ./WELA.ps1 provider-packs -ProviderAction List
+ ./WELA.ps1 provider-packs -ProviderAction Plan -ProviderPack dns-client,capi2 -ResultsPath provider-plan.json
./WELA.ps1 wef-source -WefAction Plan -WefConfigPath source.json -ResultsPath source-plan.json
./WELA.ps1 wec-collector -WefAction Configure -WefConfigPath collector.json -DryRun
@@ -1825,6 +1830,9 @@ if ($PSBoundParameters.ContainsKey('SaclMode') -and
throw '-SaclMode requires -Profile with plan, audit, audit-settings or configure. It does not control configure-sacl. No command was run.'
}
# Reject unsupported dry-run requests before reaching any command's mutation path.
+if ($Cmd -ne 'provider-packs' -and ($PSBoundParameters.ContainsKey('ProviderAction') -or $PSBoundParameters.ContainsKey('ProviderPack'))) {
+ throw 'Provider options require provider-packs. No command was run.'
+}
if ($Cmd -ne 'powershell-transcription' -and
($PSBoundParameters.ContainsKey('TranscriptionAction') -or $PSBoundParameters.ContainsKey('TranscriptDirectory'))) {
throw 'Transcription options require the dedicated powershell-transcription command. No command was run.'
@@ -1835,6 +1843,7 @@ if ($Cmd -ne 'ad-object-sacl' -and @($PSBoundParameters.Keys | Where-Object {
throw 'AD object SACL options require the dedicated ad-object-sacl command. No command was run.'
}
if ($DryRun -and -not ($Cmd -eq 'audit-notifications' -and $NotificationAction -eq 'Configure') -and -not ($Cmd -eq 'ldap-diagnostics' -and $LdapAction -eq 'Configure') -and -not ($Cmd -eq 'applocker-readiness' -and $AppLockerAction -eq 'Import') -and $Cmd -notin @('configure', 'configure-eventlogs') -and
+ -not ($Cmd -eq 'provider-packs' -and $ProviderAction -eq 'Configure') -and
-not ($Cmd -eq 'firewall-logging' -and $FirewallAction -eq 'Configure') -and
-not ($Cmd -eq 'smb-auditing' -and $SmbAction -eq 'Configure') -and
-not ($Cmd -eq 'powershell-transcription' -and $TranscriptionAction -eq 'Configure') -and
@@ -1842,7 +1851,7 @@ if ($DryRun -and -not ($Cmd -eq 'audit-notifications' -and $NotificationAction -
-not ($Cmd -in @('wef-source','wec-collector') -and $WefAction -eq 'Configure') -and
-not ($Cmd -eq 'ad-object-sacl' -and $AdSaclAction -in @('Configure', 'Rollback')) -and
-not ($Cmd -eq 'wmi-auditing' -and $WmiAction -eq 'Configure')) {
- throw "-DryRun is supported only by configure (including configure -Profile), configure-eventlogs, firewall-logging -FirewallAction Configure, smb-auditing -SmbAction Configure, powershell-transcription -TranscriptionAction Configure, wmi-auditing -WmiAction Configure, channel-settings -ChannelAction Configure, wef-source/wec-collector -WefAction Configure, applocker-readiness -AppLockerAction Import, ad-object-sacl -AdSaclAction Configure|Rollback, ldap-diagnostics -LdapAction Configure, and audit-notifications -NotificationAction Configure. No command was run."
+ throw "-DryRun is supported only by configure (including configure -Profile), configure-eventlogs, firewall-logging -FirewallAction Configure, smb-auditing -SmbAction Configure, powershell-transcription -TranscriptionAction Configure, wmi-auditing -WmiAction Configure, channel-settings -ChannelAction Configure, wef-source/wec-collector -WefAction Configure, applocker-readiness -AppLockerAction Import, ad-object-sacl -AdSaclAction Configure|Rollback, ldap-diagnostics -LdapAction Configure, provider-packs -ProviderAction Configure, and audit-notifications -NotificationAction Configure. No command was run."
}
if (($WmiNamespace -or $WmiIncludeChildren -or $PSBoundParameters.ContainsKey('WmiAction')) -and $Cmd -ne 'wmi-auditing') {
throw '-WmiAction, -WmiNamespace and -WmiIncludeChildren require wmi-auditing. No command was run.'
@@ -1923,6 +1932,15 @@ switch ($Cmd.ToLower()) {
$report
if ($report.ExitCode) { exit $report.ExitCode }
}
+ 'provider-packs' {
+ if ($Help) { Write-Host 'Usage: ./WELA.ps1 provider-packs [-ProviderAction List|Audit|Plan|Configure] [-ProviderPack dns-client,capi2,winrm,rdp-client,dns-server-audit] [-Auto] [-DryRun] [-BackupPath new-directory] [-ResultsPath report.json]. DNS classic/analytical packs are manual inventory. See docs/native-provider-packs.md.'; return }
+ if ($Profile -or $Baseline -or $Role -or $Build -or $HtmlPath -or $PlanPath) { throw 'provider-packs uses explicit pack names, actual host role/build and -ResultsPath JSON; audit profiles and context overrides do not apply.' }
+ if ($ProviderAction -ne 'Configure' -and ($Auto -or $BackupPath)) { throw '-Auto and -BackupPath require ProviderAction Configure.' }
+ if ($ProviderAction -eq 'Configure' -and -not (TestAdministrator)) { throw 'Provider pack configuration requires Administrator privileges.' }
+ $report=Invoke-WelaProviderPackCommand -Action $ProviderAction -Names $ProviderPack -Auto:$Auto -DryRun:$DryRun -BackupPath $BackupPath -ResultsPath $ResultsPath
+ $report
+ if ($report.ExitCode) { exit $report.ExitCode }
+ }
'channel-settings' {
if ($Help) {
Write-Host 'Usage: ./WELA.ps1 channel-settings [-ChannelAction Audit|Plan|Configure] [-ChannelProfile microsoft-wef-appendix-c] [-WefQuerySet Baseline|Suspect|Both] [-GrantEventLogReaders] [-Auto] [-DryRun] [-BackupPath new-directory] [-ResultsPath file.json]'
diff --git a/config/native_provider_packs.json b/config/native_provider_packs.json
new file mode 100644
index 00000000..8655bac5
--- /dev/null
+++ b/config/native_provider_packs.json
@@ -0,0 +1,530 @@
+{
+ "schemaVersion": 1,
+ "id": "native-provider-packs-v1",
+ "reviewed": "2026-09-19",
+ "corpusSha256": "edffff132db9c9cd53d51db62b5bf7f9459d8bdcbbcac6ada806b2ca7881297f",
+ "ruleRepository": "https://github.com/Yamato-Security/hayabusa-rules",
+ "ruleCommit": "10d1b6dc3ec884daf04d736a7fc78bf2ee898664",
+ "buildFamilies": {
+ "Client": [
+ 22000,
+ 22621,
+ 22631,
+ 26100,
+ 26200,
+ 28000
+ ],
+ "Server": [
+ 14393,
+ 17763,
+ 20348,
+ 26100
+ ]
+ },
+ "buildSources": [
+ "https://learn.microsoft.com/en-us/windows/release-health/windows11-release-information",
+ "https://learn.microsoft.com/en-us/windows/release-health/windows-server-release-info"
+ ],
+ "packs": [
+ {
+ "id": "dns-client",
+ "provider": "Microsoft-Windows-DNS-Client",
+ "channel": "Microsoft-Windows-DNS-Client/Operational",
+ "mode": "Configure",
+ "roles": [
+ "Client",
+ "MemberServer",
+ "DomainController",
+ "ADCS"
+ ],
+ "requiredService": null,
+ "minimumBytes": 33554432,
+ "sizeBasis": "WELA opt-in floor, not a Microsoft baseline requirement",
+ "allowedChannelTypes": [
+ "Administrative",
+ "Operational"
+ ],
+ "events": [
+ {
+ "id": 3008,
+ "requiredFields": [
+ "QueryName"
+ ]
+ }
+ ],
+ "ruleIds": [
+ "2abf05fa-98f2-d00b-6a6a-12d07e55233e",
+ "e1b0fd63-1017-1597-ec08-3f9e1021e564",
+ "14b17417-8ae7-ff8e-fe36-28aaa337ccd5",
+ "ec3b018a-d4dd-2d51-4a63-50d078f737dd",
+ "9b3ffe56-a479-9b35-d590-9b94c2f7fa35",
+ "f0b3a5e9-e4ee-ed23-3b27-4dd30c5974c8"
+ ],
+ "source": "https://learn.microsoft.com/en-us/windows/security/operating-system-security/device-management/use-windows-event-forwarding-to-assist-in-intrusion-detection",
+ "rights": "Administrator to configure; event-reader token access remains untested",
+ "enableCommand": "wevtutil sl \"Microsoft-Windows-DNS-Client/Operational\" /e:true"
+ },
+ {
+ "id": "dns-server-audit",
+ "provider": "Microsoft-Windows-DNSServer",
+ "channel": "Microsoft-Windows-DNSServer/Audit",
+ "mode": "Configure",
+ "roles": [
+ "MemberServer",
+ "DomainController",
+ "ADCS"
+ ],
+ "requiredService": "DNS",
+ "minimumBytes": 33554432,
+ "sizeBasis": "WELA opt-in floor, not a Microsoft baseline requirement",
+ "allowedChannelTypes": [
+ "Administrative",
+ "Operational"
+ ],
+ "events": [
+ {
+ "id": 515,
+ "requiredFields": []
+ },
+ {
+ "id": 516,
+ "requiredFields": []
+ },
+ {
+ "id": 519,
+ "requiredFields": []
+ }
+ ],
+ "ruleIds": [],
+ "source": "https://learn.microsoft.com/en-us/windows-server/networking/dns/dns-logging-and-diagnostics",
+ "rights": "Administrator to configure; event-reader token access remains untested",
+ "enableCommand": "wevtutil sl \"Microsoft-Windows-DNSServer/Audit\" /e:true"
+ },
+ {
+ "id": "dns-server-analytical",
+ "provider": "Microsoft-Windows-DNSServer",
+ "channel": "Microsoft-Windows-DNSServer/Analytical",
+ "mode": "ManualOnly",
+ "roles": [
+ "MemberServer",
+ "DomainController",
+ "ADCS"
+ ],
+ "requiredService": "DNS",
+ "minimumBytes": 33554432,
+ "sizeBasis": "WELA opt-in floor, not a Microsoft baseline requirement",
+ "allowedChannelTypes": [
+ "Administrative",
+ "Operational"
+ ],
+ "events": [
+ {
+ "id": 257,
+ "requiredFields": [
+ "QNAME"
+ ]
+ },
+ {
+ "id": 260,
+ "requiredFields": [
+ "QNAME"
+ ]
+ },
+ {
+ "id": 261,
+ "requiredFields": [
+ "QNAME"
+ ]
+ }
+ ],
+ "ruleIds": [
+ "6db38b96-3772-4cbf-a8ad-c65d8ac5134e",
+ "cd6eb342-9dcd-450d-b448-bebd97cb6e89",
+ "c8e0edae-2335-591c-7057-1ac58f03e06c"
+ ],
+ "source": "https://learn.microsoft.com/en-us/windows-server/networking/dns/dns-logging-and-diagnostics",
+ "rights": "Administrator to configure; event-reader token access remains untested",
+ "enableCommand": "Manual review only; no enable command is executed"
+ },
+ {
+ "id": "dns-server-classic",
+ "provider": "Microsoft-Windows-DNS-Server-Service",
+ "channel": "DNS Server",
+ "mode": "ManualOnly",
+ "roles": [
+ "MemberServer",
+ "DomainController",
+ "ADCS"
+ ],
+ "requiredService": "DNS",
+ "minimumBytes": 33554432,
+ "sizeBasis": "WELA opt-in floor, not a Microsoft baseline requirement",
+ "allowedChannelTypes": [
+ "Administrative",
+ "Operational"
+ ],
+ "events": [
+ {
+ "id": 150,
+ "requiredFields": []
+ },
+ {
+ "id": 770,
+ "requiredFields": []
+ },
+ {
+ "id": 771,
+ "requiredFields": []
+ },
+ {
+ "id": 6004,
+ "requiredFields": []
+ }
+ ],
+ "ruleIds": [
+ "04768e11-3acf-895f-9193-daae77c4678f",
+ "40077f9e-f597-1087-0c4f-8901d1a07af4"
+ ],
+ "source": "https://learn.microsoft.com/en-us/windows-server/networking/dns/dns-logging-and-diagnostics",
+ "rights": "Administrator to configure; event-reader token access remains untested",
+ "enableCommand": "Manual review only; no enable command is executed"
+ },
+ {
+ "id": "capi2",
+ "provider": "Microsoft-Windows-CAPI2",
+ "channel": "Microsoft-Windows-CAPI2/Operational",
+ "mode": "Configure",
+ "roles": [
+ "Client",
+ "MemberServer",
+ "DomainController",
+ "ADCS"
+ ],
+ "requiredService": null,
+ "minimumBytes": 102432768,
+ "sizeBasis": "Microsoft WEF Appendix C exact example; Windows rounding preserved",
+ "allowedChannelTypes": [
+ "Administrative",
+ "Operational"
+ ],
+ "events": [
+ {
+ "id": 70,
+ "requiredFields": []
+ }
+ ],
+ "ruleIds": [
+ "dadaca47-d760-88a9-fd35-cbe8a6237499"
+ ],
+ "source": "https://learn.microsoft.com/en-us/windows/security/operating-system-security/device-management/use-windows-event-forwarding-to-assist-in-intrusion-detection",
+ "rights": "Administrator to configure; event-reader token access remains untested",
+ "enableCommand": "wevtutil sl \"Microsoft-Windows-CAPI2/Operational\" /e:true"
+ },
+ {
+ "id": "winrm",
+ "provider": "Microsoft-Windows-WinRM",
+ "channel": "Microsoft-Windows-WinRM/Operational",
+ "mode": "Configure",
+ "roles": [
+ "Client",
+ "MemberServer",
+ "DomainController",
+ "ADCS"
+ ],
+ "requiredService": null,
+ "minimumBytes": 33554432,
+ "sizeBasis": "WELA opt-in floor, not a Microsoft baseline requirement",
+ "allowedChannelTypes": [
+ "Administrative",
+ "Operational"
+ ],
+ "events": [
+ {
+ "id": 6,
+ "requiredFields": []
+ }
+ ],
+ "ruleIds": [
+ "4f321a68-176a-4f1d-873a-8793bc49e3b0"
+ ],
+ "source": "https://learn.microsoft.com/en-us/intune/intune-service/remote-actions/collect-diagnostics",
+ "rights": "Administrator to configure; event-reader token access remains untested",
+ "enableCommand": "wevtutil sl \"Microsoft-Windows-WinRM/Operational\" /e:true"
+ },
+ {
+ "id": "rdp-client",
+ "provider": "Microsoft-Windows-TerminalServices-ClientActiveXCore",
+ "channel": "Microsoft-Windows-TerminalServices-RDPClient/Operational",
+ "mode": "Configure",
+ "roles": [
+ "Client",
+ "MemberServer",
+ "DomainController",
+ "ADCS"
+ ],
+ "requiredService": null,
+ "minimumBytes": 33554432,
+ "sizeBasis": "WELA opt-in floor, not a Microsoft baseline requirement",
+ "allowedChannelTypes": [
+ "Administrative",
+ "Operational"
+ ],
+ "events": [
+ {
+ "id": 1024,
+ "requiredFields": []
+ },
+ {
+ "id": 1102,
+ "requiredFields": []
+ }
+ ],
+ "ruleIds": [
+ "512e70f5-bf70-4de1-9375-2174999a7f8d",
+ "1a850b71-6aef-4f31-a509-f31b2c778476"
+ ],
+ "source": "https://learn.microsoft.com/en-us/windows/security/operating-system-security/device-management/use-windows-event-forwarding-to-assist-in-intrusion-detection",
+ "rights": "Administrator to configure; event-reader token access remains untested",
+ "enableCommand": "wevtutil sl \"Microsoft-Windows-TerminalServices-RDPClient/Operational\" /e:true"
+ }
+ ],
+ "ruleReviews": [
+ {
+ "id": "cd6eb342-9dcd-450d-b448-bebd97cb6e89",
+ "title": "Recursive DNS Request",
+ "path": "hayabusa/builtin/DNS-Server/DNS-ServerAnalytical_260_Info_DNS-Request.yml",
+ "sha256": "2e336af288931632cd497a2698bac73f9ae23272d1c9f450c53ee8adae57200a",
+ "localPath": "provider_rule_sources/cd6eb342-9dcd-450d-b448-bebd97cb6e89.yml",
+ "ruleChannels": [
+ "Microsoft-Windows-DNS-Server/Analytical"
+ ],
+ "requiredEventFields": [],
+ "operators": [],
+ "condition": "selection",
+ "nativeEligibility": "Conditional: event/backend adapter and repeatable evidence required"
+ },
+ {
+ "id": "6db38b96-3772-4cbf-a8ad-c65d8ac5134e",
+ "title": "Recursive DNS Response",
+ "path": "hayabusa/builtin/DNS-Server/DNS-ServerAnalytical_261_Info_DNS-Response.yml",
+ "sha256": "cbc467af34fd99b3737fa4a8df2bdbed93ded59e96d2d477d962d1412ffd00cf",
+ "localPath": "provider_rule_sources/6db38b96-3772-4cbf-a8ad-c65d8ac5134e.yml",
+ "ruleChannels": [
+ "Microsoft-Windows-DNS-Server/Analytical"
+ ],
+ "requiredEventFields": [],
+ "operators": [],
+ "condition": "selection",
+ "nativeEligibility": "Conditional: event/backend adapter and repeatable evidence required"
+ },
+ {
+ "id": "512e70f5-bf70-4de1-9375-2174999a7f8d",
+ "title": "RDP Conn Attempt",
+ "path": "hayabusa/builtin/TerminalServices-RDPClient_Op/RDP-Client_1024_Info_ConnAttempt.yml",
+ "sha256": "965cce3bb99985e323264f62cd01b6180c1e346ab3ec042a92041cbd2d788706",
+ "localPath": "provider_rule_sources/512e70f5-bf70-4de1-9375-2174999a7f8d.yml",
+ "ruleChannels": [
+ "Microsoft-Windows-TerminalServices-RDPClient/Operational"
+ ],
+ "requiredEventFields": [],
+ "operators": [],
+ "condition": "selection",
+ "nativeEligibility": "Conditional: event/backend adapter and repeatable evidence required"
+ },
+ {
+ "id": "1a850b71-6aef-4f31-a509-f31b2c778476",
+ "title": "RDP Attempt",
+ "path": "hayabusa/builtin/TerminalServices-RDPClient_Op/RDP-Client_1102_Info_ConnAttempt.yml",
+ "sha256": "289505628401ab76e2ba21154d8c79a406f12c8a9128e127f6371919341e1f2b",
+ "localPath": "provider_rule_sources/1a850b71-6aef-4f31-a509-f31b2c778476.yml",
+ "ruleChannels": [
+ "Microsoft-Windows-TerminalServices-RDPClient/Operational"
+ ],
+ "requiredEventFields": [],
+ "operators": [],
+ "condition": "selection",
+ "nativeEligibility": "Conditional: event/backend adapter and repeatable evidence required"
+ },
+ {
+ "id": "4f321a68-176a-4f1d-873a-8793bc49e3b0",
+ "title": "Win RM Session Created",
+ "path": "hayabusa/builtin/WinRM_Op/WinRM_6_Info_SessCreated.yml",
+ "sha256": "a1db69172b7a15030ca8f85e05dbee494568ddb84ec1a01ef9184c4f813e5006",
+ "localPath": "provider_rule_sources/4f321a68-176a-4f1d-873a-8793bc49e3b0.yml",
+ "ruleChannels": [
+ "Microsoft-Windows-WinRM/Operational"
+ ],
+ "requiredEventFields": [],
+ "operators": [],
+ "condition": "selection_basic",
+ "nativeEligibility": "Conditional: event/backend adapter and repeatable evidence required"
+ },
+ {
+ "id": "dadaca47-d760-88a9-fd35-cbe8a6237499",
+ "title": "Certificate Private Key Acquired",
+ "path": "sigma/builtin/capi2/win_capi2_acquire_certificate_private_key.yml",
+ "sha256": "5c536cf6f6c72e6cc061f50ca8f57bc45675dffaa08fdad7808de71e78d79c3c",
+ "localPath": "provider_rule_sources/dadaca47-d760-88a9-fd35-cbe8a6237499.yml",
+ "ruleChannels": [
+ "Microsoft-Windows-CAPI2/Operational"
+ ],
+ "requiredEventFields": [],
+ "operators": [],
+ "condition": "capi2 and selection",
+ "nativeEligibility": "Conditional: event/backend adapter and repeatable evidence required"
+ },
+ {
+ "id": "2abf05fa-98f2-d00b-6a6a-12d07e55233e",
+ "title": "DNS Query for Anonfiles.com Domain - DNS Client",
+ "path": "sigma/builtin/dns_client/win_dns_client_anonymfiles_com.yml",
+ "sha256": "8e3a2a16879ae20c9f35a5775e0a3d80cbca7bed1b97bf7a854b66c865d369f2",
+ "localPath": "provider_rule_sources/2abf05fa-98f2-d00b-6a6a-12d07e55233e.yml",
+ "ruleChannels": [
+ "Microsoft-Windows-DNS Client Events/Operational"
+ ],
+ "requiredEventFields": [
+ "QueryName"
+ ],
+ "operators": [
+ "contains"
+ ],
+ "condition": "dns_client and selection",
+ "nativeEligibility": "Conditional: event/backend adapter and repeatable evidence required"
+ },
+ {
+ "id": "f0b3a5e9-e4ee-ed23-3b27-4dd30c5974c8",
+ "title": "Suspicious Cobalt Strike DNS Beaconing - DNS Client",
+ "path": "sigma/builtin/dns_client/win_dns_client_mal_cobaltstrike.yml",
+ "sha256": "84d8b4abc29e83ba9bf33a5468d33abceb6002bb60bcf1311f0ea681d7bc280c",
+ "localPath": "provider_rule_sources/f0b3a5e9-e4ee-ed23-3b27-4dd30c5974c8.yml",
+ "ruleChannels": [
+ "Microsoft-Windows-DNS Client Events/Operational"
+ ],
+ "requiredEventFields": [
+ "QueryName"
+ ],
+ "operators": [
+ "contains",
+ "startswith"
+ ],
+ "condition": "dns_client and (selection_eid and 1 of selection_query_*)",
+ "nativeEligibility": "Conditional: event/backend adapter and repeatable evidence required"
+ },
+ {
+ "id": "14b17417-8ae7-ff8e-fe36-28aaa337ccd5",
+ "title": "DNS Query To MEGA Hosting Website - DNS Client",
+ "path": "sigma/builtin/dns_client/win_dns_client_mega_nz.yml",
+ "sha256": "cc8b3b8d7c41f194581e0dd17cbc41de6b18c041b75f1554c4e1fcc0e7c10b90",
+ "localPath": "provider_rule_sources/14b17417-8ae7-ff8e-fe36-28aaa337ccd5.yml",
+ "ruleChannels": [
+ "Microsoft-Windows-DNS Client Events/Operational"
+ ],
+ "requiredEventFields": [
+ "QueryName"
+ ],
+ "operators": [
+ "contains"
+ ],
+ "condition": "dns_client and selection",
+ "nativeEligibility": "Conditional: event/backend adapter and repeatable evidence required"
+ },
+ {
+ "id": "9b3ffe56-a479-9b35-d590-9b94c2f7fa35",
+ "title": "DNS Query To Put.io - DNS Client",
+ "path": "sigma/builtin/dns_client/win_dns_client_put_io.yml",
+ "sha256": "d7c151d0b5392a179dfad761bafdf2807411251e37227beb2016304b38a36b58",
+ "localPath": "provider_rule_sources/9b3ffe56-a479-9b35-d590-9b94c2f7fa35.yml",
+ "ruleChannels": [
+ "Microsoft-Windows-DNS Client Events/Operational"
+ ],
+ "requiredEventFields": [
+ "QueryName"
+ ],
+ "operators": [
+ "contains"
+ ],
+ "condition": "dns_client and selection",
+ "nativeEligibility": "Conditional: event/backend adapter and repeatable evidence required"
+ },
+ {
+ "id": "e1b0fd63-1017-1597-ec08-3f9e1021e564",
+ "title": "Query Tor Onion Address - DNS Client",
+ "path": "sigma/builtin/dns_client/win_dns_client_tor_onion.yml",
+ "sha256": "923596f2a5e1ef0ba41c2987a04d92c59cf3c0884ddf0d51a581c3a725d412e8",
+ "localPath": "provider_rule_sources/e1b0fd63-1017-1597-ec08-3f9e1021e564.yml",
+ "ruleChannels": [
+ "Microsoft-Windows-DNS Client Events/Operational"
+ ],
+ "requiredEventFields": [
+ "QueryName"
+ ],
+ "operators": [
+ "endswith"
+ ],
+ "condition": "dns_client and selection",
+ "nativeEligibility": "Conditional: event/backend adapter and repeatable evidence required"
+ },
+ {
+ "id": "ec3b018a-d4dd-2d51-4a63-50d078f737dd",
+ "title": "DNS Query To Ufile.io - DNS Client",
+ "path": "sigma/builtin/dns_client/win_dns_client_ufile_io.yml",
+ "sha256": "cfeacb16c5641b3edd943aae3f9b4c39e02c0abe88b73cef659efdaf0987eba6",
+ "localPath": "provider_rule_sources/ec3b018a-d4dd-2d51-4a63-50d078f737dd.yml",
+ "ruleChannels": [
+ "Microsoft-Windows-DNS Client Events/Operational"
+ ],
+ "requiredEventFields": [
+ "QueryName"
+ ],
+ "operators": [
+ "contains"
+ ],
+ "condition": "dns_client and selection",
+ "nativeEligibility": "Conditional: event/backend adapter and repeatable evidence required"
+ },
+ {
+ "id": "04768e11-3acf-895f-9193-daae77c4678f",
+ "title": "Failed DNS Zone Transfer",
+ "path": "sigma/builtin/dns_server/win_dns_server_failed_dns_zone_transfer.yml",
+ "sha256": "3fd1df00d972211dc8e5548e12fb04f555e50e264eee6ed051b84093ca1956a0",
+ "localPath": "provider_rule_sources/04768e11-3acf-895f-9193-daae77c4678f.yml",
+ "ruleChannels": [
+ "DNS Server"
+ ],
+ "requiredEventFields": [],
+ "operators": [],
+ "condition": "dns_server and selection",
+ "nativeEligibility": "Conditional: event/backend adapter and repeatable evidence required"
+ },
+ {
+ "id": "40077f9e-f597-1087-0c4f-8901d1a07af4",
+ "title": "DNS Server Error Failed Loading the ServerLevelPluginDLL",
+ "path": "sigma/builtin/dns_server/win_dns_server_susp_server_level_plugin_dll.yml",
+ "sha256": "6cbcfbdd3add8ff3a1e6a800780b1a47d01f3b38afde3b9332184ea8f5689ae2",
+ "localPath": "provider_rule_sources/40077f9e-f597-1087-0c4f-8901d1a07af4.yml",
+ "ruleChannels": [
+ "DNS Server"
+ ],
+ "requiredEventFields": [],
+ "operators": [],
+ "condition": "dns_server and selection",
+ "nativeEligibility": "Conditional: event/backend adapter and repeatable evidence required"
+ },
+ {
+ "id": "c8e0edae-2335-591c-7057-1ac58f03e06c",
+ "title": "GALLIUM Artefacts - Builtin",
+ "path": "sigma/builtin/emerging-threats/2020/TA/GALLIUM/win_dns_analytic_apt_gallium.yml",
+ "sha256": "224922dcbe19b4435f2e5fee7ebd08f6e748144b36a38490b69800dac4675e4d",
+ "localPath": "provider_rule_sources/c8e0edae-2335-591c-7057-1ac58f03e06c.yml",
+ "ruleChannels": [
+ "Microsoft-Windows-DNS-Server/Analytical"
+ ],
+ "requiredEventFields": [
+ "QNAME"
+ ],
+ "operators": [],
+ "condition": "dns_server_analytic and selection",
+ "nativeEligibility": "Conditional: event/backend adapter and repeatable evidence required"
+ }
+ ]
+}
diff --git a/config/provider_rule_sources/04768e11-3acf-895f-9193-daae77c4678f.yml b/config/provider_rule_sources/04768e11-3acf-895f-9193-daae77c4678f.yml
new file mode 100644
index 00000000..69ebd183
--- /dev/null
+++ b/config/provider_rule_sources/04768e11-3acf-895f-9193-daae77c4678f.yml
@@ -0,0 +1,27 @@
+title: Failed DNS Zone Transfer
+id: 04768e11-3acf-895f-9193-daae77c4678f
+related:
+ - id: 6d444368-6da1-43fe-b2fc-44202430480e
+ type: derived
+status: test
+description: Detects when a DNS zone transfer failed.
+references:
+ - https://kb.eventtracker.com/evtpass/evtpages/EventId_6004_Microsoft-Windows-DNS-Server-Service_65410.asp
+author: Zach Mathis
+date: 2023-05-24
+tags:
+ - attack.reconnaissance
+ - attack.t1590.002
+logsource:
+ product: windows
+ service: dns-server
+detection:
+ dns_server:
+ Channel: DNS Server
+ selection:
+ EventID: 6004 # The DNS server received a zone transfer request from %1 for a non-existent or non-authoritative zone %2.
+ condition: dns_server and selection
+falsepositives:
+ - Unlikely
+level: medium
+ruletype: Sigma
diff --git a/config/provider_rule_sources/14b17417-8ae7-ff8e-fe36-28aaa337ccd5.yml b/config/provider_rule_sources/14b17417-8ae7-ff8e-fe36-28aaa337ccd5.yml
new file mode 100644
index 00000000..20e8eea4
--- /dev/null
+++ b/config/provider_rule_sources/14b17417-8ae7-ff8e-fe36-28aaa337ccd5.yml
@@ -0,0 +1,31 @@
+title: DNS Query To MEGA Hosting Website - DNS Client
+id: 14b17417-8ae7-ff8e-fe36-28aaa337ccd5
+related:
+ - id: 613c03ba-0779-4a53-8a1f-47f914a4ded3
+ type: similar
+ - id: 66474410-b883-415f-9f8d-75345a0a66a6
+ type: derived
+status: test
+description: Detects DNS queries for subdomains related to MEGA sharing website
+references:
+ - https://research.nccgroup.com/2021/05/27/detecting-rclone-an-effective-tool-for-exfiltration/
+author: Nasreddine Bencherchali (Nextron Systems)
+date: 2023-01-16
+tags:
+ - attack.exfiltration
+ - attack.t1567.002
+logsource:
+ product: windows
+ service: dns-client
+ definition: 'Requirements: Microsoft-Windows-DNS Client Events/Operational Event Log must be enabled/collected in order to receive the events.'
+detection:
+ dns_client:
+ Channel: Microsoft-Windows-DNS Client Events/Operational
+ selection:
+ EventID: 3008
+ QueryName|contains: userstorage.mega.co.nz
+ condition: dns_client and selection
+falsepositives:
+ - Legitimate DNS queries and usage of Mega
+level: medium
+ruletype: Sigma
diff --git a/config/provider_rule_sources/1a850b71-6aef-4f31-a509-f31b2c778476.yml b/config/provider_rule_sources/1a850b71-6aef-4f31-a509-f31b2c778476.yml
new file mode 100644
index 00000000..6fcc47e0
--- /dev/null
+++ b/config/provider_rule_sources/1a850b71-6aef-4f31-a509-f31b2c778476.yml
@@ -0,0 +1,50 @@
+author: Zach Mathis
+date: 2022-03-29
+modified: 2025-02-10
+
+title: RDP Attempt
+details: 'TgtIP: %Value%'
+description:
+
+id: 1a850b71-6aef-4f31-a509-f31b2c778476
+level: informational
+status: stable
+logsource:
+ product: windows
+detection:
+ selection:
+ Channel: Microsoft-Windows-TerminalServices-RDPClient/Operational
+ EventID: 1102
+ condition: selection
+falsepositives:
+ - administrator
+tags:
+ - RDP
+ - attack.lateral-movement
+references:
+ruletype: Hayabusa
+
+sample-evtx: |
+
+
+
+ 1102
+ 0
+ 4
+ 101
+ 10
+ 0x4000000000000000
+
+ 7738
+
+
+ Microsoft-Windows-TerminalServices-RDPClient/Operational
+ server.domain.co.jp
+
+
+
+ ServerAddress
+ 172.17.7.161
+ Info
+
+
\ No newline at end of file
diff --git a/config/provider_rule_sources/2abf05fa-98f2-d00b-6a6a-12d07e55233e.yml b/config/provider_rule_sources/2abf05fa-98f2-d00b-6a6a-12d07e55233e.yml
new file mode 100644
index 00000000..68e2c496
--- /dev/null
+++ b/config/provider_rule_sources/2abf05fa-98f2-d00b-6a6a-12d07e55233e.yml
@@ -0,0 +1,31 @@
+title: DNS Query for Anonfiles.com Domain - DNS Client
+id: 2abf05fa-98f2-d00b-6a6a-12d07e55233e
+related:
+ - id: 065cceea-77ec-4030-9052-fc0affea7110
+ type: similar
+ - id: 29f171d7-aa47-42c7-9c7b-3c87938164d9
+ type: derived
+status: test
+description: Detects DNS queries for anonfiles.com, which is an anonymous file upload platform often used for malicious purposes
+references:
+ - https://www.trendmicro.com/vinfo/us/security/news/ransomware-spotlight/ransomware-spotlight-blackbyte
+author: Nasreddine Bencherchali (Nextron Systems)
+date: 2023-01-16
+tags:
+ - attack.exfiltration
+ - attack.t1567.002
+logsource:
+ product: windows
+ service: dns-client
+ definition: 'Requirements: Microsoft-Windows-DNS Client Events/Operational Event Log must be enabled/collected in order to receive the events.'
+detection:
+ dns_client:
+ Channel: Microsoft-Windows-DNS Client Events/Operational
+ selection:
+ EventID: 3008
+ QueryName|contains: .anonfiles.com
+ condition: dns_client and selection
+falsepositives:
+ - Rare legitimate access to anonfiles.com
+level: high
+ruletype: Sigma
diff --git a/config/provider_rule_sources/40077f9e-f597-1087-0c4f-8901d1a07af4.yml b/config/provider_rule_sources/40077f9e-f597-1087-0c4f-8901d1a07af4.yml
new file mode 100644
index 00000000..a497b097
--- /dev/null
+++ b/config/provider_rule_sources/40077f9e-f597-1087-0c4f-8901d1a07af4.yml
@@ -0,0 +1,40 @@
+title: DNS Server Error Failed Loading the ServerLevelPluginDLL
+id: 40077f9e-f597-1087-0c4f-8901d1a07af4
+related:
+ - id: e61e8a88-59a9-451c-874e-70fcc9740d67
+ type: derived
+ - id: f63b56ee-3f79-4b8a-97fb-5c48007e8573
+ type: derived
+ - id: cbe51394-cd93-4473-b555-edf0144952d9
+ type: derived
+status: test
+description: Detects a DNS server error in which a specified plugin DLL (in registry) could not be loaded
+references:
+ - https://medium.com/@esnesenon/feature-not-bug-dnsadmin-to-dc-compromise-in-one-line-a0f779b8dc83
+ - https://technet.microsoft.com/en-us/library/cc735829(v=ws.10).aspx
+ - https://twitter.com/gentilkiwi/status/861641945944391680
+author: Florian Roth (Nextron Systems)
+date: 2017-05-08
+modified: 2023-02-05
+tags:
+ - attack.privilege-escalation
+ - attack.persistence
+ - attack.execution
+ - attack.stealth
+ - attack.t1574.001
+logsource:
+ product: windows
+ service: dns-server
+detection:
+ dns_server:
+ Channel: DNS Server
+ selection:
+ EventID:
+ - 150
+ - 770
+ - 771
+ condition: dns_server and selection
+falsepositives:
+ - Unknown
+level: high
+ruletype: Sigma
diff --git a/config/provider_rule_sources/4f321a68-176a-4f1d-873a-8793bc49e3b0.yml b/config/provider_rule_sources/4f321a68-176a-4f1d-873a-8793bc49e3b0.yml
new file mode 100644
index 00000000..bd2a0917
--- /dev/null
+++ b/config/provider_rule_sources/4f321a68-176a-4f1d-873a-8793bc49e3b0.yml
@@ -0,0 +1,51 @@
+author: Zach Mathis
+date: 2022-04-08
+modified: 2022-12-16
+
+title: 'Win RM Session Created'
+details: 'Conn: %connection%'
+description:
+
+id: 4f321a68-176a-4f1d-873a-8793bc49e3b0
+level: informational
+status: stable
+logsource:
+ product: windows
+ #service: #Not defined in sigma yet.
+ definition:
+detection:
+ selection_basic:
+ Channel: Microsoft-Windows-WinRM/Operational
+ EventID: 6
+ condition: selection_basic
+falsepositives:
+ - unknown
+tags:
+ - PwSh
+ - WinRM
+references:
+ruletype: Hayabusa
+
+sample-message: 'Creating WSMan Session. The connection string is: localhost:47001/WSMan?MSP=6a83d074-bb86-4e52-aa3e-6cc73cc066c8;PSVersion=5.1.14409.1005'
+sample-evtx: |
+
+
+
+ 6
+ 0
+ 4
+ 3
+ 1
+ 0x4000000000000002
+
+ 137
+
+
+ Microsoft-Windows-WinRM/Operational
+ web-server
+
+
+
+ localhost:47001/WSMan?MSP=6a83d074-bb86-4e52-aa3e-6cc73cc066c8;PSVersion=5.1.14409.1005
+
+
\ No newline at end of file
diff --git a/config/provider_rule_sources/512e70f5-bf70-4de1-9375-2174999a7f8d.yml b/config/provider_rule_sources/512e70f5-bf70-4de1-9375-2174999a7f8d.yml
new file mode 100644
index 00000000..b2052660
--- /dev/null
+++ b/config/provider_rule_sources/512e70f5-bf70-4de1-9375-2174999a7f8d.yml
@@ -0,0 +1,50 @@
+author: Zach Mathis
+date: 2022-03-28
+modified: 2025-02-10
+
+title: RDP Conn Attempt
+details: 'TgtIP: %Value%'
+description:
+
+id: 512e70f5-bf70-4de1-9375-2174999a7f8d
+level: informational
+status: stable
+logsource:
+ product: windows
+detection:
+ selection:
+ Channel: Microsoft-Windows-TerminalServices-RDPClient/Operational
+ EventID: 1024
+ condition: selection
+falsepositives:
+ - administrator
+tags:
+ - RDP
+ - attack.lateral-movement
+references:
+ruletype: Hayabusa
+
+sample-evtx: |
+
+
+
+ 1024
+ 0
+ 4
+ 101
+ 10
+ 0x4000000000000000
+
+ 19
+
+
+ Microsoft-Windows-TerminalServices-RDPClient/Operational
+ server.computer.lan
+
+
+
+ Server Name
+ dmz-ftp
+ Info
+
+
\ No newline at end of file
diff --git a/config/provider_rule_sources/6db38b96-3772-4cbf-a8ad-c65d8ac5134e.yml b/config/provider_rule_sources/6db38b96-3772-4cbf-a8ad-c65d8ac5134e.yml
new file mode 100644
index 00000000..138f9fe2
--- /dev/null
+++ b/config/provider_rule_sources/6db38b96-3772-4cbf-a8ad-c65d8ac5134e.yml
@@ -0,0 +1,23 @@
+author: Zach Mathis
+date: 2023-07-01
+modified: 2023-07-01
+
+title: Recursive DNS Response
+description:
+
+id: 6db38b96-3772-4cbf-a8ad-c65d8ac5134e
+level: informational
+status: experimental
+logsource:
+ product: windows
+ service: dns-server-analytic
+ description: 'Requirements: Microsoft-Windows-DNS-Server/Analytical ({EB79061A-A566-4698-9119-3ED2807060E7}) Event Log must be collected in order to receive the events.'
+detection:
+ selection:
+ Channel: Microsoft-Windows-DNS-Server/Analytical
+ EventID: 261
+ condition: selection
+references:
+ - https://cybersecthreat.com/2020/07/24/windows-dns-logging/
+ - https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-r2-and-2012/dn800669(v=ws.11)
+ruletype: Hayabusa
\ No newline at end of file
diff --git a/config/provider_rule_sources/9b3ffe56-a479-9b35-d590-9b94c2f7fa35.yml b/config/provider_rule_sources/9b3ffe56-a479-9b35-d590-9b94c2f7fa35.yml
new file mode 100644
index 00000000..608bdcd0
--- /dev/null
+++ b/config/provider_rule_sources/9b3ffe56-a479-9b35-d590-9b94c2f7fa35.yml
@@ -0,0 +1,30 @@
+title: DNS Query To Put.io - DNS Client
+id: 9b3ffe56-a479-9b35-d590-9b94c2f7fa35
+related:
+ - id: 8b69fd42-9dad-4674-abef-7fdef43ef92a
+ type: derived
+status: test
+description: Detects DNS queries for subdomains related to "Put.io" sharing website.
+references:
+ - https://darkatlas.io/blog/medusa-ransomware-group-opsec-failure
+author: Omar Khaled (@beacon_exe)
+date: 2024-08-23
+tags:
+ - attack.command-and-control
+logsource:
+ product: windows
+ service: dns-client
+ definition: 'Requirements: Microsoft-Windows-DNS Client Events/Operational Event Log must be enabled/collected in order to receive the events.'
+detection:
+ dns_client:
+ Channel: Microsoft-Windows-DNS Client Events/Operational
+ selection:
+ EventID: 3008
+ QueryName|contains:
+ - api.put.io
+ - upload.put.io
+ condition: dns_client and selection
+falsepositives:
+ - Legitimate DNS queries and usage of Put.io
+level: medium
+ruletype: Sigma
diff --git a/config/provider_rule_sources/LICENSE-upstream.md b/config/provider_rule_sources/LICENSE-upstream.md
new file mode 100644
index 00000000..6475b151
--- /dev/null
+++ b/config/provider_rule_sources/LICENSE-upstream.md
@@ -0,0 +1,17 @@
+# Detection Rule License (DRL) 1.1
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this rule set and associated documentation files (the "Rules"), to deal in the Rules without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Rules, and to permit persons to whom the Rules are furnished to do so, subject to the following conditions:
+
+If you share the Rules (including in modified form), you must retain the following if it is supplied within the Rules:
+
+1. identification of the authors(s) ("author" field) of the Rule and any others designated to receive attribution, in any reasonable manner requested by the Rule author (including by pseudonym if designated).
+
+2. a URI or hyperlink to the Rule set or explicit Rule to the extent reasonably practicable
+
+3. indicate the Rules are licensed under this Detection Rule License, and include the text of, or the URI or hyperlink to, this Detection Rule License to the extent reasonably practicable
+
+If you use the Rules (including in modified form) on data, messages based on matches with the Rules must retain the following if it is supplied within the Rules:
+
+1. identification of the authors(s) ("author" field) of the Rule and any others designated to receive attribution, in any reasonable manner requested by the Rule author (including by pseudonym if designated).
+
+THE RULES ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE RULES OR THE USE OR OTHER DEALINGS IN THE RULES.
\ No newline at end of file
diff --git a/config/provider_rule_sources/README.md b/config/provider_rule_sources/README.md
new file mode 100644
index 00000000..9883101e
--- /dev/null
+++ b/config/provider_rule_sources/README.md
@@ -0,0 +1,3 @@
+# Pinned provider rule definitions
+
+Unmodified native rule definitions from Yamato-Security/hayabusa-rules commit `10d1b6dc3ec884daf04d736a7fc78bf2ee898664`. Paths, SHA256 hashes and reviewed fields are in `../native_provider_packs.json`. Authors and upstream references remain in every YAML file. The upstream license is retained alongside them. These are source-review artifacts, not executable rules or successful detection evidence.
diff --git a/config/provider_rule_sources/c8e0edae-2335-591c-7057-1ac58f03e06c.yml b/config/provider_rule_sources/c8e0edae-2335-591c-7057-1ac58f03e06c.yml
new file mode 100644
index 00000000..bf3cfe7d
--- /dev/null
+++ b/config/provider_rule_sources/c8e0edae-2335-591c-7057-1ac58f03e06c.yml
@@ -0,0 +1,42 @@
+title: GALLIUM Artefacts - Builtin
+id: c8e0edae-2335-591c-7057-1ac58f03e06c
+related:
+ - id: 440a56bf-7873-4439-940a-1c8a671073c2
+ type: derived
+ - id: 3db10f25-2527-4b79-8d4b-471eb900ee29
+ type: derived
+status: test
+description: Detects artefacts associated with activity group GALLIUM - Microsoft Threat Intelligence Center indicators released in December 2019.
+references:
+ - https://www.microsoft.com/security/blog/2019/12/12/gallium-targeting-global-telecom/
+ - https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-R2-and-2012/dn800669(v=ws.11)
+author: Tim Burrell
+date: 2020-02-07
+modified: 2023-01-02
+tags:
+ - attack.credential-access
+ - attack.command-and-control
+ - attack.t1071
+ - detection.emerging-threats
+logsource:
+ product: windows
+ service: dns-server-analytic
+ definition: 'Requirements: Microsoft-Windows-DNS-Server/Analytical ({EB79061A-A566-4698-9119-3ED2807060E7}) Event Log must be collected in order to receive the events.'
+detection:
+ dns_server_analytic:
+ Channel: Microsoft-Windows-DNS-Server/Analytical
+ selection:
+ EventID: 257
+ QNAME:
+ - asyspy256.ddns.net
+ - hotkillmail9sddcc.ddns.net
+ - rosaf112.ddns.net
+ - cvdfhjh1231.myftp.biz
+ - sz2016rose.ddns.net
+ - dffwescwer4325.myftp.biz
+ - cvdfhjh1231.ddns.net
+ condition: dns_server_analytic and selection
+falsepositives:
+ - Unknown
+level: high
+ruletype: Sigma
diff --git a/config/provider_rule_sources/cd6eb342-9dcd-450d-b448-bebd97cb6e89.yml b/config/provider_rule_sources/cd6eb342-9dcd-450d-b448-bebd97cb6e89.yml
new file mode 100644
index 00000000..4d784d19
--- /dev/null
+++ b/config/provider_rule_sources/cd6eb342-9dcd-450d-b448-bebd97cb6e89.yml
@@ -0,0 +1,23 @@
+author: Zach Mathis
+date: 2023-07-01
+modified: 2023-07-01
+
+title: Recursive DNS Request
+description:
+
+id: cd6eb342-9dcd-450d-b448-bebd97cb6e89
+level: informational
+status: stable
+logsource:
+ product: windows
+ service: dns-server-analytic
+ description: 'Requirements: Microsoft-Windows-DNS-Server/Analytical ({EB79061A-A566-4698-9119-3ED2807060E7}) Event Log must be collected in order to receive the events.'
+detection:
+ selection:
+ Channel: Microsoft-Windows-DNS-Server/Analytical
+ EventID: 260
+ condition: selection
+references:
+ - https://cybersecthreat.com/2020/07/24/windows-dns-logging/
+ - https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-r2-and-2012/dn800669(v=ws.11)
+ruletype: Hayabusa
\ No newline at end of file
diff --git a/config/provider_rule_sources/dadaca47-d760-88a9-fd35-cbe8a6237499.yml b/config/provider_rule_sources/dadaca47-d760-88a9-fd35-cbe8a6237499.yml
new file mode 100644
index 00000000..7d50e071
--- /dev/null
+++ b/config/provider_rule_sources/dadaca47-d760-88a9-fd35-cbe8a6237499.yml
@@ -0,0 +1,28 @@
+title: Certificate Private Key Acquired
+id: dadaca47-d760-88a9-fd35-cbe8a6237499
+related:
+ - id: e2b5163d-7deb-4566-9af3-40afea6858c3
+ type: derived
+status: test
+description: Detects when an application acquires a certificate private key
+references:
+ - https://www.splunk.com/en_us/blog/security/breaking-the-chain-defending-against-certificate-services-abuse.html
+author: Zach Mathis
+date: 2023-05-13
+tags:
+ - attack.credential-access
+ - attack.t1649
+logsource:
+ product: windows
+ service: capi2
+ definition: 'Requirements: The CAPI2 Operational log needs to be enabled'
+detection:
+ capi2:
+ Channel: Microsoft-Windows-CAPI2/Operational
+ selection:
+ EventID: 70 # Acquire Certificate Private Key
+ condition: capi2 and selection
+falsepositives:
+ - Legitimate application requesting certificate exports will trigger this. Apply additional filters as needed
+level: medium
+ruletype: Sigma
diff --git a/config/provider_rule_sources/e1b0fd63-1017-1597-ec08-3f9e1021e564.yml b/config/provider_rule_sources/e1b0fd63-1017-1597-ec08-3f9e1021e564.yml
new file mode 100644
index 00000000..c565ddc5
--- /dev/null
+++ b/config/provider_rule_sources/e1b0fd63-1017-1597-ec08-3f9e1021e564.yml
@@ -0,0 +1,80 @@
+title: Query Tor Onion Address - DNS Client
+id: e1b0fd63-1017-1597-ec08-3f9e1021e564
+related:
+ - id: b55ca2a3-7cff-4dda-8bdd-c7bfa63bf544
+ type: similar
+ - id: a8322756-015c-42e7-afb1-436e85ed3ff5
+ type: similar
+ - id: 8384bd26-bde6-4da9-8e5d-4174a7a47ca2
+ type: derived
+status: test
+description: Detects DNS resolution of an .onion address related to Tor routing networks
+references:
+ - https://www.logpoint.com/en/blog/detecting-tor-use-with-logpoint/
+ - https://github.com/Azure/Azure-Sentinel/blob/f99542b94afe0ad2f19a82cc08262e7ac8e1428e/Detections/ASimDNS/imDNS_TorProxies.yaml
+author: Nasreddine Bencherchali (Nextron Systems)
+date: 2022-02-20
+modified: 2025-09-12
+tags:
+ - attack.command-and-control
+ - attack.t1090.003
+logsource:
+ product: windows
+ service: dns-client
+ definition: 'Requirements: Microsoft-Windows-DNS Client Events/Operational Event Log must be enabled/collected in order to receive the events.'
+detection:
+ dns_client:
+ Channel: Microsoft-Windows-DNS Client Events/Operational
+ selection:
+ EventID: 3008
+ QueryName|endswith:
+ - .hiddenservice.net
+ - .onion.ca
+ - .onion.cab
+ - .onion.casa
+ - .onion.city
+ - .onion.direct
+ - .onion.dog
+ - .onion.glass
+ - .onion.gq
+ - .onion.guide
+ - .onion.in.net
+ - .onion.ink
+ - .onion.it
+ - .onion.link
+ - .onion.lt
+ - .onion.lu
+ - .onion.ly
+ - .onion.mn
+ - .onion.network
+ - .onion.nu
+ - .onion.pet
+ - .onion.plus
+ - .onion.pt
+ - .onion.pw
+ - .onion.rip
+ - .onion.sh
+ - .onion.si
+ - .onion.to
+ - .onion.top
+ - .onion.ws
+ - .onion
+ - .s1.tor-gateways.de
+ - .s2.tor-gateways.de
+ - .s3.tor-gateways.de
+ - .s4.tor-gateways.de
+ - .s5.tor-gateways.de
+ - .t2w.pw
+ - .tor2web.ae.org
+ - .tor2web.blutmagie.de
+ - .tor2web.com
+ - .tor2web.fi
+ - .tor2web.io
+ - .tor2web.org
+ - .tor2web.xyz
+ - .torlink.co
+ condition: dns_client and selection
+falsepositives:
+ - Unlikely
+level: high
+ruletype: Sigma
diff --git a/config/provider_rule_sources/ec3b018a-d4dd-2d51-4a63-50d078f737dd.yml b/config/provider_rule_sources/ec3b018a-d4dd-2d51-4a63-50d078f737dd.yml
new file mode 100644
index 00000000..a596c28c
--- /dev/null
+++ b/config/provider_rule_sources/ec3b018a-d4dd-2d51-4a63-50d078f737dd.yml
@@ -0,0 +1,32 @@
+title: DNS Query To Ufile.io - DNS Client
+id: ec3b018a-d4dd-2d51-4a63-50d078f737dd
+related:
+ - id: 1cbbeaaf-3c8c-4e4c-9d72-49485b6a176b
+ type: similar
+ - id: 090ffaad-c01a-4879-850c-6d57da98452d
+ type: derived
+status: test
+description: Detects DNS queries to "ufile.io", which was seen abused by malware and threat actors as a method for data exfiltration
+references:
+ - https://thedfirreport.com/2021/12/13/diavol-ransomware/
+author: Nasreddine Bencherchali (Nextron Systems)
+date: 2023-01-16
+modified: 2023-09-18
+tags:
+ - attack.exfiltration
+ - attack.t1567.002
+logsource:
+ product: windows
+ service: dns-client
+ definition: 'Requirements: Microsoft-Windows-DNS Client Events/Operational Event Log must be enabled/collected in order to receive the events.'
+detection:
+ dns_client:
+ Channel: Microsoft-Windows-DNS Client Events/Operational
+ selection:
+ EventID: 3008
+ QueryName|contains: ufile.io
+ condition: dns_client and selection
+falsepositives:
+ - DNS queries for "ufile" are not malicious by nature necessarily. Investigate the source to determine the necessary actions to take
+level: low
+ruletype: Sigma
diff --git a/config/provider_rule_sources/f0b3a5e9-e4ee-ed23-3b27-4dd30c5974c8.yml b/config/provider_rule_sources/f0b3a5e9-e4ee-ed23-3b27-4dd30c5974c8.yml
new file mode 100644
index 00000000..38b41def
--- /dev/null
+++ b/config/provider_rule_sources/f0b3a5e9-e4ee-ed23-3b27-4dd30c5974c8.yml
@@ -0,0 +1,37 @@
+title: Suspicious Cobalt Strike DNS Beaconing - DNS Client
+id: f0b3a5e9-e4ee-ed23-3b27-4dd30c5974c8
+related:
+ - id: f356a9c4-effd-4608-bbf8-408afd5cd006
+ type: similar
+ - id: 0d18728b-f5bf-4381-9dcf-915539fff6c2
+ type: derived
+status: test
+description: Detects a program that invoked suspicious DNS queries known from Cobalt Strike beacons
+references:
+ - https://www.icebrg.io/blog/footprints-of-fin7-tracking-actor-patterns
+ - https://www.sekoia.io/en/hunting-and-detecting-cobalt-strike/
+author: Nasreddine Bencherchali (Nextron Systems)
+date: 2023-01-16
+tags:
+ - attack.t1071.004
+ - attack.command-and-control
+logsource:
+ product: windows
+ service: dns-client
+ definition: 'Requirements: Microsoft-Windows-DNS Client Events/Operational Event Log must be enabled/collected in order to receive the events.'
+detection:
+ dns_client:
+ Channel: Microsoft-Windows-DNS Client Events/Operational
+ selection_eid:
+ EventID: 3008
+ selection_query_1:
+ QueryName|startswith:
+ - aaa.stage.
+ - post.1
+ selection_query_2:
+ QueryName|contains: .stage.123456.
+ condition: dns_client and (selection_eid and 1 of selection_query_*)
+falsepositives:
+ - Unknown
+level: critical
+ruletype: Sigma
diff --git a/docs/native-provider-packs.md b/docs/native-provider-packs.md
new file mode 100644
index 00000000..6f69892d
--- /dev/null
+++ b/docs/native-provider-packs.md
@@ -0,0 +1,52 @@
+# Native provider packs
+
+`provider-packs` is a separate, explicit source-configuration workflow. Normal `configure`, audit profiles, WinRM/RDP service settings and rule eligibility remain unchanged. Sysmon and external telemetry are excluded. No pack grants Ready status to a rule.
+
+```powershell
+./WELA.ps1 provider-packs -ProviderAction List
+./WELA.ps1 provider-packs -ProviderAction Plan -ProviderPack dns-client,capi2 -ResultsPath plan.json
+./WELA.ps1 provider-packs -ProviderAction Configure -ProviderPack dns-client -DryRun
+./WELA.ps1 provider-packs -ProviderAction Configure -ProviderPack dns-client -Auto -BackupPath C:\WELA-Recovery\dns-run-1 -ResultsPath result.json
+```
+
+List reads the bundled definitions; Audit and Plan read actual local Windows metadata. Configure requires Administrator privileges, a nonempty explicit selection and a new recovery directory. Unknown pack names, duplicates, wildcard selection, role overrides and provider options on other commands are rejected. `-DryRun` is supported only for Configure. The PowerShell array examples above are intended for a PowerShell prompt; external `powershell.exe -File` argument parsing may need a wrapper script for multiple values.
+
+| Pack | Exact target provider / channel | Events reviewed | Behavior |
+| --- | --- | --- | --- |
+| `dns-client` | `Microsoft-Windows-DNS-Client` / `Microsoft-Windows-DNS-Client/Operational` | 3008; requires string `QueryName` | Explicit enable and 32 MiB floor if live schema matches. |
+| `dns-server-audit` | `Microsoft-Windows-DNSServer` / `Microsoft-Windows-DNSServer/Audit` | 515, 516, 519 | Server with installed DNS service only; explicit enable and 32 MiB floor. No candidate in the pinned corpus, so no rule credit. |
+| `dns-server-analytical` | `Microsoft-Windows-DNSServer` / `Microsoft-Windows-DNSServer/Analytical` | 257, 260, 261; string `QNAME` | Inventory/manual only; never enables Analytical logging. |
+| `dns-server-classic` | `Microsoft-Windows-DNS-Server-Service` / `DNS Server` | 150, 770, 771, 6004 | Inventory/manual only; never changes classic DNS logging or debug flags. |
+| `capi2` | `Microsoft-Windows-CAPI2` / `Microsoft-Windows-CAPI2/Operational` | 70 | Reuses the existing Appendix C enable/size control exactly. |
+| `winrm` | `Microsoft-Windows-WinRM` / `Microsoft-Windows-WinRM/Operational` | 6 | Explicit channel enable/32 MiB floor only; no listener, authentication, service or firewall changes. |
+| `rdp-client` | `Microsoft-Windows-TerminalServices-ClientActiveXCore` / `Microsoft-Windows-TerminalServices-RDPClient/Operational` | 1024, 1102 | Explicit channel enable/32 MiB floor only; no RDP server enablement or connection attempts. |
+
+Provider and channel names are checked independently against the local registration and provider-to-channel links. Display names and rule aliases are not substituted. Missing or inaccessible registrations remain unknown/unavailable. DNS Server Audit, classic DNS errors, Analytical query traffic and client lookups are different sources; enabling one does not satisfy the others.
+
+The 32 MiB floors are WELA opt-in choices, **not Microsoft baseline requirements**. CAPI2 retains Microsoft's exact example of 102432768 bytes, rounded upward to Windows' supported 64 KiB increment by the existing writer. Larger buffers, retention modes and every existing descriptor are preserved. Reader permissions are only observed: use the existing `channel-settings -GrantEventLogReaders` workflow to review a CAPI2 read grant separately. Structural permissions do not establish effective access for the forwarding identity.
+
+## Build and schema gates
+
+The reviewed OS families are Windows 11 builds 22000, 22621, 22631, 26100, 26200 and 28000, and Windows Server builds 14393, 17763, 20348 and 26100. This identifies families, not their servicing status or a claim that every patch has an identical event schema. Unknown builds/roles are refused for configuration. Actual DNS service registration is required for DNS Server packs; a domain-controller role alone is insufficient. Combined DC/CA hosts follow the existing host-context reader's refusal policy.
+
+On every assessed host WELA reads the exact provider's event ID, version, channel link, template SHA256 and named field/type definitions. Required DNS query-name fields must be native string fields for every returned version of the expected event. Only observed Administrative/Operational channels are eligible for automatic configuration; an unexpected Debug/Analytical type is refused even if the catalog name appears familiar. Empty/unsupported manifests, missing event IDs and unknown schemas cannot be replaced by static claims. The manifest records field definitions, not actual emitted values or a successful operation.
+
+The provider/role/service/schema fingerprint is rechecked before the shared runner's read, after approval immediately before writing, on readback and in final verification. Channel state itself also retains the shared fresh-snapshot guards. Detected changes or unreadable state fail the control. These checks observe current state; they cannot make native writes atomic against later GPO or another administrator.
+
+## Pinned full rule review and DNS mismatch
+
+The catalog pins the exact bundled corpus SHA256 and fifteen complete native Hayabusa/Sigma definitions from commit `10d1b6dc3ec884daf04d736a7fc78bf2ee898664` of [Yamato-Security/hayabusa-rules](https://github.com/Yamato-Security/hayabusa-rules/tree/10d1b6dc3ec884daf04d736a7fc78bf2ee898664). Their original YAML, authors, references and Detection Rule License are retained under `config/provider_rule_sources`; each file has a checked SHA256 and original path in `config/native_provider_packs.json`. YAML is never executed or parsed at runtime. The reviewed fields/operators/conditions are a source inventory, not a complete detection backend.
+
+All six DNS Client definitions themselves require `Microsoft-Windows-DNS Client Events/Operational`; Microsoft's WEF query names `Microsoft-Windows-DNS-Client/Operational`. WELA reports this as `ChannelMismatch`, preserving the full original definitions. It never edits the rule, silently rewrites the channel or credits the six candidates merely because the real channel is enabled. The three DNS Server Analytical rules also retain their original channel strings for comparison against actual registration. The two classic DNS rules remain separate.
+
+Successful channel configuration says nothing about benign operation generation, nonempty event fields, collector arrival, normalized field aliases, modifier/list/Boolean semantics or backend translation. All fifteen candidates stay Conditional, and generic categories remain subject to the existing conservative `rule-eligibility` adapter boundary. Before claiming usability, retain native XML from a benign isolated-host operation, exact build/patch and before/after state, the reviewed channel/field mapping, collector evidence, the actual translated query and matching results. Do not query the suspicious domains in the rule definitions as a test; use a separately reviewed harmless fixture and document the difference.
+
+## Results, recovery and validation limits
+
+`ControlsPlan` is explicitly the pre-write plan, including full-rule review and manifest observations. Configure `Results` contains the shared runner's verified after-state and final result. A selected manual/unavailable pack produces a failed control/nonzero overall exit while independent selected packs may proceed; no partial application is hidden. Dry-run and declined controls are skipped, not applied. `ReadyRules` remains zero and `UnverifiedEvidence` lists the remaining event/backend/access work.
+
+Every attempted native write first records the original enabled flag, exact buffer size, retention and complete descriptor in `before.jsonl`. Restore only the recorded selected channel values using an elevated `wevtutil sl` after reviewing concurrent GPO/administrator changes; do not replace an entire descriptor with an example. No automatic rollback overwrites later changes. Event loss/volume and long-term storage requirements require a measured deployment plan.
+
+The mocked regression suite exercises missing fields/providers, unsupported types/builds, role/service gates, journal-before-write, dry-run, decline, idempotence, preserved ACL/retention/larger buffers, native failure/false success, prompt races and final schema drift. Windows Server 2022/2025 CI on PowerShell 5.1/7 reads real provider manifests and the public CLI plan and checks that channel settings stay unchanged. It creates no DNS queries, log entries, services or subscriptions. Windows 11/DC/CA event-generation and actual backend/collector validation remain pending acceptance work for issue #386.
+
+Primary references: [Microsoft WEF Appendix C/F](https://learn.microsoft.com/en-us/windows/security/operating-system-security/device-management/use-windows-event-forwarding-to-assist-in-intrusion-detection), [DNS logging and diagnostics](https://learn.microsoft.com/en-us/windows-server/networking/dns/dns-logging-and-diagnostics), [EventMetadata](https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.eventing.reader.eventmetadata?view=windowsdesktop-10.0), [EventLogLink](https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.eventing.reader.eventloglink?view=windowsdesktop-10.0), [Windows 11 release families](https://learn.microsoft.com/en-us/windows/release-health/windows11-release-information), and [Windows Server release families](https://learn.microsoft.com/en-us/windows/release-health/windows-server-release-info). The WEF sample identifies event/channel candidates; it does not validate these rule definitions or this implementation on every build.
diff --git a/modules/NativeProviders.psm1 b/modules/NativeProviders.psm1
index 55f416fe..64b4aad8 100644
--- a/modules/NativeProviders.psm1
+++ b/modules/NativeProviders.psm1
@@ -208,4 +208,4 @@ function Export-WelaAuditAssessment {
}
}
-Export-ModuleMember -Function Get-WelaNativeChannel, Get-WelaNativeProvider, Get-WelaNativeSources, Get-WelaNativeSourceState, Export-WelaAuditAssessment
+Export-ModuleMember -Function Get-WelaNativeChannel, Get-WelaNativeService, Get-WelaNativeProvider, Get-WelaNativeSources, Get-WelaNativeSourceState, Export-WelaAuditAssessment
diff --git a/scripts/NativeProviderPacks.ps1 b/scripts/NativeProviderPacks.ps1
new file mode 100644
index 00000000..1ba0a64d
--- /dev/null
+++ b/scripts/NativeProviderPacks.ps1
@@ -0,0 +1,162 @@
+# Opt-in native provider/channel inventory. No rule evaluation or implied readiness.
+function Get-WelaProviderPackCatalog {
+ $base = Join-Path $PSScriptRoot '../config'
+ $catalog = Get-Content -LiteralPath (Join-Path $base 'native_provider_packs.json') -Raw -ErrorAction Stop | ConvertFrom-Json
+ if ($catalog.schemaVersion -ne 1 -or $catalog.id -ne 'native-provider-packs-v1') { throw 'Unsupported provider pack catalog.' }
+ $hash = (Get-FileHash -LiteralPath (Join-Path $base 'security_rules.json') -Algorithm SHA256).Hash
+ if ($hash -ne $catalog.corpusSha256) { throw 'Provider pack corpus pin mismatch; review the updated corpus before using these packs.' }
+ $parsed = Get-Content -LiteralPath (Join-Path $base 'security_rules.json') -Raw | ConvertFrom-Json
+ $ids = @{}; foreach ($rule in @($parsed)) { $ids[$rule.id] = $true }
+ $reviews = @{}
+ foreach ($review in $catalog.ruleReviews) {
+ if (-not $ids.ContainsKey($review.id) -or $reviews.ContainsKey($review.id) -or
+ $review.id -notmatch '^[a-fA-F0-9-]{36}$' -or $review.localPath -cne ('provider_rule_sources/' + $review.id + '.yml')) { throw 'Invalid provider rule review identity/path.' }
+ if ((Get-FileHash -LiteralPath (Join-Path $base $review.localPath) -Algorithm SHA256).Hash -ne $review.sha256) { throw "Pinned full rule changed: $($review.id)" }
+ $reviews[$review.id] = $true
+ }
+ $names = @{}
+ foreach ($pack in $catalog.packs) {
+ if (-not $pack.id -or $names.ContainsKey($pack.id) -or $pack.mode -notin @('Configure','ManualOnly') -or
+ -not $pack.provider -or -not $pack.channel -or $pack.channel -match '[*?\[\]\r\n]' -or $pack.provider -match '[*?\[\]\r\n]' -or
+ $pack.events.Count -eq 0 -or $pack.minimumBytes -lt 1048576) { throw 'Invalid provider pack definition.' }
+ $names[$pack.id] = $true
+ foreach ($id in $pack.ruleIds) { if (-not $reviews.ContainsKey($id)) { throw "Full rule review missing: $id" } }
+ }
+ return $catalog
+}
+
+function Get-WelaProviderTemplateFields {
+ param([string]$Template)
+ if (-not $Template) { return }
+ $settings = New-Object Xml.XmlReaderSettings
+ $settings.DtdProcessing = [Xml.DtdProcessing]::Prohibit; $settings.XmlResolver = $null; $settings.MaxCharactersInDocument = 1048576
+ $reader = [Xml.XmlReader]::Create([IO.StringReader]::new($Template), $settings)
+ try { $xml = New-Object Xml.XmlDocument; $xml.XmlResolver=$null; $xml.Load($reader) } finally { $reader.Dispose() }
+ $seen = @{}
+ foreach ($field in $xml.SelectNodes('//*[local-name()="data"]')) {
+ $name = $field.GetAttribute('name')
+ if (-not $name -or $seen.ContainsKey($name)) { throw 'Template contains missing or duplicate field names.' }
+ $seen[$name]=$true
+ [pscustomobject]@{ Name=$name; InType=$field.GetAttribute('inType'); OutType=$field.GetAttribute('outType') }
+ }
+}
+
+function Get-WelaProviderPackSchema {
+ param($Pack)
+ $provider = $null; $providers=@(); $logs=@()
+ try {
+ $logs = @(Get-WinEvent -ListLog $Pack.channel -ErrorAction Stop | Where-Object LogName -eq $Pack.channel)
+ if ($logs.Count -ne 1) { throw 'Exact channel registration was not returned.' }
+ $providers = @(Get-WinEvent -ListProvider $Pack.provider -ErrorAction Stop | Where-Object Name -eq $Pack.provider)
+ if ($providers.Count -ne 1) { throw 'Exact provider registration was not returned.' }
+ $provider=$providers[0]
+ if ([guid]$provider.Id -eq [guid]::Empty) { throw 'Provider GUID is unknown.' }
+ if (@($logs[0].ProviderNames) -notcontains $Pack.provider -or @($provider.LogLinks.LogName) -notcontains $Pack.channel) { throw 'Provider/channel links disagree.' }
+ $events = @()
+ foreach ($event in $provider.Events) {
+ if (@($Pack.events.id) -contains [int]$event.Id -and $event.LogLink.LogName -eq $Pack.channel) {
+ $fields = @(Get-WelaProviderTemplateFields -Template $event.Template)
+ $sha = [Security.Cryptography.SHA256]::Create()
+ try { $templateHash = ([BitConverter]::ToString($sha.ComputeHash([Text.Encoding]::UTF8.GetBytes([string]$event.Template)))).Replace('-','').ToLowerInvariant() } finally { $sha.Dispose() }
+ $events += [pscustomobject]@{ Id=[int]$event.Id; Version=[int]$event.Version; Channel=[string]$event.LogLink.LogName; Fields=$fields; TemplateSha256=$templateHash }
+ }
+ }
+ [pscustomobject]@{ State='Observed'; Provider=[string]$provider.Name; ProviderGuid=[string]$provider.Id; ChannelType=[string]$logs[0].LogType; Events=$events; Diagnostic=$null }
+ } catch { [pscustomobject]@{ State='Unknown'; Provider=$Pack.provider; ProviderGuid=$null; ChannelType=$null; Events=@(); Diagnostic=$_.Exception.Message } }
+ finally { foreach ($metadata in @($providers) + @($logs)) { if ($metadata -is [IDisposable]) { $metadata.Dispose() } } }
+}
+
+function Get-WelaProviderPackObservation {
+ param($Pack, $Catalog)
+ $reasons = New-Object 'System.Collections.Generic.List[string]'
+ $hostContext=$null; $service=$null
+ try {
+ $hostContext=Get-WelaHostContext
+ $family=if ($hostContext.Role -eq 'Client') {'Client'} else {'Server'}
+ if ($Pack.roles -notcontains $hostContext.Role -or $Catalog.buildFamilies.$family -notcontains $hostContext.Build) { $reasons.Add('Role/build outside reviewed families; no configuration allowed.') }
+ } catch { $reasons.Add("Role/build unknown: $_") }
+ if ($Pack.requiredService) {
+ $service=Get-WelaNativeService -Name $Pack.requiredService
+ if ($service.State -notin @('Running','Stopped','Paused','StartPending','StopPending','ContinuePending','PausePending')) { $reasons.Add('Required DNS Server service is absent or unreadable; a DC role alone does not prove DNS is installed.') }
+ }
+ $schema=Get-WelaProviderPackSchema -Pack $Pack
+ if ($schema.State -ne 'Observed') { $reasons.Add("Provider schema unknown: $($schema.Diagnostic)") }
+ if ($schema.ChannelType -notin @('Administrative','Operational')) { $reasons.Add('Only observed Administrative/Operational channels can be configured; Analytical/Debug channels remain manual.') }
+ foreach ($expected in $Pack.events) {
+ $events=@($schema.Events | Where-Object Id -eq $expected.id)
+ if ($events.Count -eq 0) { $reasons.Add("Expected event $($expected.id) is absent from the exact provider/channel manifest."); continue }
+ foreach ($event in $events) {
+ foreach ($name in $expected.requiredFields) {
+ $fields=@($event.Fields | Where-Object Name -ceq $name)
+ if ($fields.Count -ne 1 -or $fields[0].InType -notin @('win:UnicodeString','win:AnsiString')) { $reasons.Add("Event $($event.Id) version $($event.Version) lacks the required string field $name.") }
+ }
+ }
+ }
+ if ($Pack.mode -ne 'Configure') { $reasons.Add('Inventory/manual review only; this pack never enables its channel.') }
+ # Within-run manifest identity, not cross-host rule identity or detection proof.
+ $fingerprint=@($hostContext.Role,$hostContext.Build,$schema.Provider,$schema.ProviderGuid,$schema.ChannelType,$service.State)
+ foreach ($event in @($schema.Events | Sort-Object Id,Version)) { $fingerprint += "$($event.Id)/$($event.Version)/$($event.TemplateSha256)" }
+ [pscustomobject]@{ CanConfigure=($reasons.Count -eq 0); Reasons=@($reasons.ToArray()); HostContext=$hostContext; Service=$service; Schema=$schema; Fingerprint=($fingerprint -join '|') }
+}
+
+function Get-WelaProviderPackPlan {
+ param($Catalog, [string[]]$Names)
+ if (-not $Names -or $Names.Count -eq 0) { throw 'Select one or more explicit -ProviderPack names; no default pack is applied.' }
+ $selected=@{}
+ foreach ($name in $Names) {
+ if ($selected.ContainsKey($name)) { throw "Duplicate provider pack: $name" }; $selected[$name]=$true
+ if (@($Catalog.packs | Where-Object id -eq $name).Count -ne 1) { throw "Unknown provider pack: $name" }
+ }
+ foreach ($name in $Names) {
+ $pack=@($Catalog.packs | Where-Object id -eq $name)[0]
+ $observation=Get-WelaProviderPackObservation -Pack $pack -Catalog $Catalog
+ if ($pack.id -eq 'capi2') { $control=@((Get-WelaNativeChannelProfile).controls | Where-Object channel -eq $pack.channel)[0] }
+ else { $control=[pscustomobject]@{ channel=$pack.channel; enabled=$true; sourceExampleBytes=[long]$pack.minimumBytes; readerSid=$null; readerMask=$null } }
+ if (-not $control) { throw 'CAPI2 shared channel control is missing.' }
+ $plan=@(Get-WelaNativeChannelPlan -Profile ([pscustomobject]@{controls=@($control)}))[0]
+ $plan | Add-Member NoteProperty Pack $pack
+ $plan | Add-Member NoteProperty Catalog $Catalog
+ $plan | Add-Member NoteProperty ProviderEvidence $observation
+ $plan | Add-Member NoteProperty PrerequisiteDiagnostic ($observation.Reasons -join ' ')
+ $reviews=@($Catalog.ruleReviews | Where-Object { $pack.ruleIds -contains $_.id } | ForEach-Object {
+ [pscustomobject]@{ Id=$_.id; Title=$_.title; Source=($Catalog.ruleRepository+'/blob/'+$Catalog.ruleCommit+'/'+$_.path); SourceSha256=$_.sha256; DefinitionPath=$_.localPath; RuleChannels=$_.ruleChannels; ObservedTargetChannel=$pack.channel; ChannelMismatch=(@($_.ruleChannels | Where-Object { $_ -cne $pack.channel }).Count -gt 0); RequiredEventFields=$_.requiredEventFields; Operators=$_.operators; Condition=$_.condition; Eligibility='Conditional'; Reason='Full native event, backend field mapping/translation and repeatable matching evidence remain unverified.' }
+ })
+ $plan | Add-Member NoteProperty RuleReviews $reviews
+ if (-not $observation.CanConfigure) { $plan.Status='ManualReview' }
+ $plan
+ }
+}
+
+function Invoke-WelaProviderPackCommand {
+ param([ValidateSet('List','Audit','Plan','Configure')][string]$Action='List', [string[]]$Names,
+ [switch]$Auto, [switch]$DryRun, [string]$BackupPath, [string]$ResultsPath)
+ if ($DryRun -and $Action -ne 'Configure') { throw '-DryRun requires ProviderAction Configure.' }
+ $catalog=Get-WelaProviderPackCatalog
+ if ($Action -eq 'List') {
+ if ($Names) { throw 'List inventories all packs; select -ProviderPack with Audit, Plan or Configure.' }
+ $report=[pscustomobject]@{ Scope='native-provider-pack-inventory'; ExitCode=0; Catalog=$catalog; ReadyRules=0; Evidence='Definitions only; no host observations or event/backend evidence.' }
+ if ($ResultsPath) { $report | ConvertTo-Json -Depth 24 | Set-Content -LiteralPath $ResultsPath -Encoding UTF8 -ErrorAction Stop }
+ return $report
+ }
+ if ($env:OS -ne 'Windows_NT') { throw 'Provider pack observations/configuration require Windows.' }
+ $plan=@(Get-WelaProviderPackPlan -Catalog $catalog -Names $Names)
+ if ($Action -eq 'Configure') {
+ $context=New-WelaConfigurationContext -Auto:$Auto -DryRun:$DryRun -BackupPath $BackupPath
+ $guard={ param($entry)
+ $fresh=Get-WelaProviderPackObservation -Pack $entry.Pack -Catalog $entry.Catalog
+ if (-not $fresh.CanConfigure -or $fresh.Fingerprint -cne $entry.ProviderEvidence.Fingerprint) { throw 'Provider role/service/channel type or event schema changed or became unknown; no channel write allowed.' }
+ }
+ Set-WelaNativeChannelControls -Context $context -Plan $plan -Profile $catalog.id -ValidatePrerequisites $guard
+ $report=Complete-WelaConfiguration -Context $context -Scope 'native-channel-settings-only' -SuccessMessage 'Requested provider channel settings verified. Event generation, identity access and backend detection remain unverified.'
+ } else { $report=[pscustomobject]@{ Scope='native-provider-pack-inventory'; ExitCode=$(if (@($plan | Where-Object Status -in @('Unknown','NotInstalled','ManualReview')).Count) {1} else {0}) } }
+ # Configuration results contain verified after-state; Controls retain the reviewed
+ # pre-write plan explicitly, never masquerading as current observation.
+ $report | Add-Member NoteProperty Action $Action
+ $report | Add-Member NoteProperty ControlsPlan @($plan | Select-Object Definition,Before,Status,Access,Desired,Prerequisites,Pack,ProviderEvidence,RuleReviews)
+ $report | Add-Member NoteProperty CorpusSha256 $catalog.corpusSha256
+ $report | Add-Member NoteProperty RuleCommit $catalog.ruleCommit
+ $report | Add-Member NoteProperty ReadyRules 0
+ $report | Add-Member NoteProperty UnverifiedEvidence @('Effective event-reader identity access','Representative emitted event XML and required field values','Backend translation, ingestion and matching result','Generic-category adapters and event volume')
+ if ($ResultsPath) { try { $report | ConvertTo-Json -Depth 24 | Set-Content -LiteralPath $ResultsPath -Encoding UTF8 -ErrorAction Stop } catch { $report.ExitCode=1; Write-Warning "Provider report export failed: $_" } }
+ return $report
+}
diff --git a/tests/NativeProviderPacks.Tests.ps1 b/tests/NativeProviderPacks.Tests.ps1
new file mode 100644
index 00000000..84cc23c7
--- /dev/null
+++ b/tests/NativeProviderPacks.Tests.ps1
@@ -0,0 +1,150 @@
+# Synthetic provider manifests and shared native writer boundary; no Windows changes.
+$ErrorActionPreference='Stop'
+$repo=Split-Path $PSScriptRoot -Parent
+Import-Module (Join-Path $repo 'modules/EventLogSettings.psm1') -Force
+Import-Module (Join-Path $repo 'modules/NativeProviders.psm1') -Force
+Import-Module (Join-Path $repo 'modules/NativeChannelAccess.psm1') -Force
+. (Join-Path $repo 'scripts/Configuration.ps1')
+. (Join-Path $repo 'scripts/NativeChannelConfiguration.ps1')
+. (Join-Path $repo 'scripts/NativeProviderPacks.ps1')
+$script:ScriptRoot=$repo
+$script:count=0;$script:cleanup=@()
+function Assert($Value,$Message) { if (-not $Value) {throw $Message};$script:count++ }
+function Throws($Action,$Message) { $failed=$false;try {& $Action | Out-Null}catch {$failed=$true};Assert $failed $Message }
+function Reset {
+ $script:f=@{}
+ $script:catalog=Get-WelaProviderPackCatalog
+ $script:f=@{States=@{};Writes=@();Role='Client';Build=26100;Service='Running';Type='Operational';TemplateMode='good';NativeFailure='';Prompt='Y';PromptSchemaDrift=$false;ProviderReads=0;DriftAt=0}
+ foreach($pack in $catalog.packs){$f.States[$pack.channel]=[pscustomobject]@{Name=$pack.channel;State='Disabled';IsEnabled=$false;MaximumSizeInBytes=[long]1048576;LogMode='Retain';SecurityDescriptor='unchanged';ProviderNames=@($pack.provider);MetadataErrors=@{};Error=$null}}
+ $script:backup=Join-Path ([IO.Path]::GetTempPath()) ('wela-packs-'+[guid]::NewGuid().ToString('N'));$script:cleanup+=,$backup
+}
+function Get-WelaHostContext { if($f.Role -eq 'Unknown'){throw 'denied'};[pscustomobject]@{Role=$f.Role;Build=$f.Build} }
+function Get-WelaNativeService { param($Name) [pscustomobject]@{Name=$Name;State=$f.Service;Error=$null} }
+function Get-WelaNativeChannel { param($Name) $f.States[$Name].PSObject.Copy() }
+function Get-FileHash {
+ param($LiteralPath,$Algorithm)
+ if(($f.BadPin -eq 'corpus' -and $LiteralPath -like '*security_rules.json') -or ($f.BadPin -eq 'rule' -and $LiteralPath -like '*.yml')){return [pscustomobject]@{Hash=('0'*64)}}
+ Microsoft.PowerShell.Utility\Get-FileHash -LiteralPath $LiteralPath -Algorithm $Algorithm
+}
+function Test-WelaChannelDescriptorEqual {param($First,$Second) $First -ceq $Second}
+function Get-WelaChannelAccessPlan {param($SecurityDescriptor) [pscustomobject]@{State='GrantRequired';ProposedDescriptor='must-not-write';Diagnostic='Fixture only';EffectiveReadAccess='Not tested'}}
+function Get-WinEvent {
+ param($ListLog,$ListProvider,$ErrorAction)
+ if($ListLog){$p=@($catalog.packs|Where-Object channel -eq $ListLog)[0];return [pscustomobject]@{LogName=$ListLog;LogType=$f.Type;ProviderNames=@($p.provider)}}
+ $f.ProviderReads++
+ if($f.DriftAt -eq $f.ProviderReads){$f.TemplateMode='missing'}
+ if($f.TemplateMode -eq 'denied'){throw 'Provider access denied'}
+ $p=@($catalog.packs|Where-Object provider -eq $ListProvider)[0]
+ $events=@()
+ foreach($e in $p.events){
+ $template=''
+ if($f.TemplateMode -eq 'missing'){$template=''}
+ if($f.TemplateMode -eq 'wrongtype'){$template=$template.Replace('win:UnicodeString','win:UInt32')}
+ $channel=if($f.TemplateMode -eq 'wrongchannel'){'Other/Operational'}else{$p.channel}
+ $events+= [pscustomobject]@{Id=$e.id;Version=0;LogLink=[pscustomobject]@{LogName=$channel};Template=$template}
+ }
+ [pscustomobject]@{Name=$ListProvider;Id='11111111-1111-1111-1111-111111111111';LogLinks=@([pscustomobject]@{LogName=$p.channel});Events=$events}
+}
+function Read-Host {param($Prompt) if($f.PromptSchemaDrift){$f.TemplateMode='missing'};$f.Prompt}
+function Invoke-WelaNative {
+ param($FilePath,$Arguments)
+ Assert ($FilePath -eq 'wevtutil.exe' -and $Arguments[0] -eq 'sl') 'Only existing native channel settings may change.'
+ Assert (Test-Path (Join-Path $backup 'before.jsonl')) 'Recovery journal precedes every native write.'
+ Assert (($Arguments -join ' ') -notmatch '/ca:|/rt:|/ab:') 'Provider packs never change permissions or retention.'
+ $f.Writes+=,@($Arguments)
+ if($f.NativeFailure -eq 'throw'){throw 'fixture native error'}
+ if($f.NativeFailure -eq 'nochange'){return}
+ foreach($a in $Arguments){if($a -eq '/e:true'){$f.States[$Arguments[1]].IsEnabled=$true;$f.States[$Arguments[1]].State='Enabled'};if($a -like '/ms:*'){$f.States[$Arguments[1]].MaximumSizeInBytes=[long]$a.Substring(4)}}
+}
+$oldOS=$env:OS
+try {
+ $env:OS='Windows_NT';Reset
+ # Exercise the real import boundary: a same-named test stub must not hide a
+ # missing export used by the public provider-pack script.
+ $nativeModule=Get-Module NativeProviders
+ Assert ($nativeModule.ExportedCommands.ContainsKey('Get-WelaNativeService')) 'Service observations required by packs are exported to the calling script.'
+ & $nativeModule {
+ $script:packServiceFixture='Running'
+ function script:Get-Service {
+ [CmdletBinding()]param($Name)
+ if($script:packServiceFixture -eq 'Absent'){$PSCmdlet.ThrowTerminatingError([Management.Automation.ErrorRecord]::new([Exception]::new('No such service'),'NoServiceFoundForGivenName','ObjectNotFound',$Name))}
+ if($script:packServiceFixture -eq 'Denied'){throw [UnauthorizedAccessException]::new('Service read denied')}
+ [pscustomobject]@{Status=$script:packServiceFixture}
+ }
+ }
+ try {
+ foreach($pair in @(@('Running','Running'),@('Absent','Not installed'),@('Denied','Unknown'))) {
+ & $nativeModule {param($value) $script:packServiceFixture=$value} $pair[0]
+ $service=NativeProviders\Get-WelaNativeService -Name DNS
+ Assert ($service.Name -eq 'DNS' -and $service.State -eq $pair[1]) 'Public service reader distinguishes installed, absent and denied observations without leaking an error.'
+ }
+ } finally {& $nativeModule {Remove-Item Function:\Get-Service}}
+ Assert ($catalog.packs.Count -eq 7 -and $catalog.ruleReviews.Count -eq 15) 'Seven explicit packs retain fifteen pinned full native rule definitions.'
+ $list=Invoke-WelaProviderPackCommand
+ Assert ($list.ReadyRules -eq 0 -and $f.ProviderReads -eq 0) 'List is definitions only, with no host reads or detection credit.'
+ foreach($pin in @('corpus','rule')){Reset;$f.BadPin=$pin;Throws {Invoke-WelaProviderPackCommand -Action Configure -Names dns-client -Auto -BackupPath $backup} 'Changed pinned corpus/full-rule bytes block configuration before planning.';Assert ($f.Writes.Count -eq 0 -and -not(Test-Path $backup)) 'Pin failure cannot write channels or create a journal.'}
+ Reset
+ Throws {Invoke-WelaProviderPackCommand -Action Plan} 'No default selection can activate all packs.'
+ Throws {Invoke-WelaProviderPackCommand -Action Plan -Names '*' } 'Wildcard pack selection is rejected.'
+ Throws {Invoke-WelaProviderPackCommand -Action Plan -Names @('dns-client','dns-client')} 'Duplicate selection is rejected.'
+ Throws {Invoke-WelaProviderPackCommand -Action Audit -Names dns-client -DryRun} 'DryRun is valid only for configuration.'
+ $report=Invoke-WelaProviderPackCommand -Action Plan -Names dns-client
+ $entry=$report.ControlsPlan[0]
+ Assert ($entry.Status -eq 'ChangeRequired' -and $entry.ProviderEvidence.CanConfigure) 'Exact local manifest and required string fields can support channel configuration.'
+ Assert ($entry.RuleReviews.Count -eq 6 -and @($entry.RuleReviews|Where-Object {-not $_.ChannelMismatch}).Count -eq 0) 'All six DNS rules retain the upstream channel mismatch, without silent aliasing.'
+ Assert (@($entry.RuleReviews|Where-Object Eligibility -ne 'Conditional').Count -eq 0 -and $report.ReadyRules -eq 0) 'Provider settings never convert incomplete rule evidence into Ready.'
+ Assert ($entry.ProviderEvidence.Schema.Events[0].Fields[0].InType -eq 'win:UnicodeString' -and $entry.ProviderEvidence.Schema.Events[0].TemplateSha256.Length -eq 64) 'Report retains runtime version, native field types and template fingerprint.'
+ Assert ($f.Writes.Count -eq 0 -and -not(Test-Path $backup)) 'Read-only plan creates no journal and makes no channel changes.'
+ Reset;$f.States['Microsoft-Windows-DNS-Client/Operational'].State='Not installed';$f.States['Microsoft-Windows-DNS-Client/Operational'].IsEnabled=$null
+ $r=Invoke-WelaProviderPackCommand -Action Configure -Names dns-client -Auto -BackupPath $backup
+ Assert ($r.ExitCode -eq 1 -and $f.Writes.Count -eq 0) 'Missing actual channel metadata cannot be replaced by provider-manifest availability.'
+ foreach($mode in @('missing','wrongtype','wrongchannel','denied')){
+ Reset;$f.TemplateMode=$mode;$r=Invoke-WelaProviderPackCommand -Action Configure -Names dns-client -Auto -BackupPath $backup
+ Assert ($r.ExitCode -eq 1 -and $f.Writes.Count -eq 0) "Schema $mode cannot be configured."
+ }
+ foreach($type in @('Analytical','Debug','Unknown')){
+ Reset;$f.Type=$type;$r=Invoke-WelaProviderPackCommand -Action Configure -Names dns-client -Auto -BackupPath $backup
+ Assert ($r.ExitCode -eq 1 -and $f.Writes.Count -eq 0) "Runtime channel type $type blocks writes."
+ }
+ foreach($role in @('Unknown','Client')){
+ Reset;$f.Role=$role;$f.Build=99999;$r=Invoke-WelaProviderPackCommand -Action Plan -Names dns-client
+ Assert ($r.ExitCode -eq 1 -and -not $r.ControlsPlan[0].ProviderEvidence.CanConfigure) 'Unknown roles/builds cannot be assumed supported.'
+ }
+ Reset;$f.Role='DomainController';$f.Service='Not installed';$r=Invoke-WelaProviderPackCommand -Action Plan -Names dns-server-audit
+ Assert ($r.ExitCode -eq 1) 'DC membership does not substitute for an installed DNS Server role.'
+ foreach($name in @('dns-server-classic','dns-server-analytical')){
+ Reset;$f.Role='MemberServer';$r=Invoke-WelaProviderPackCommand -Action Configure -Names $name -Auto -BackupPath $backup
+ Assert ($r.ExitCode -eq 1 -and $f.Writes.Count -eq 0) 'Classic and Analytical DNS packs remain manual-only even with a matching fixture registration.'
+ }
+ Reset;$r=Invoke-WelaProviderPackCommand -Action Configure -Names dns-client -DryRun -BackupPath $backup
+ Assert ($r.DryRun -and $f.Writes.Count -eq 0 -and -not(Test-Path $backup)) 'DryRun rechecks prerequisites but never changes channels or creates a recovery journal.'
+ Reset;$r=Invoke-WelaProviderPackCommand -Action Configure -Names dns-client -Auto -BackupPath $backup
+ Assert ($r.ExitCode -eq 0 -and $r.Results[0].Status -eq 'Applied' -and $f.Writes.Count -eq 1) 'Explicit selected channel is journaled and verified by the shared runner.'
+ Assert ($r.Results[0].After.IsEnabled -and $r.ReadyRules -eq 0) 'Verified channel enablement remains separate from telemetry readiness.'
+ $again=$backup+'-again';$cleanup+=,$again;$r=Invoke-WelaProviderPackCommand -Action Configure -Names dns-client -Auto -BackupPath $again
+ Assert ($r.Results[0].Status -eq 'AlreadyCompliant' -and $f.Writes.Count -eq 1) 'Repeated configuration is idempotent.'
+ Reset;$f.Role='MemberServer';$r=Invoke-WelaProviderPackCommand -Action Configure -Names @('dns-client','dns-server-classic') -Auto -BackupPath $backup
+ Assert ($r.ExitCode -eq 1 -and $f.Writes.Count -eq 1 -and @($r.Results|Where-Object Status -eq 'Failed').Count -eq 1) 'A manual-only selection stays failed while an independent supported selection completes.'
+ Reset;$f.States['Microsoft-Windows-DNS-Client/Operational'].MaximumSizeInBytes=[long]4294967296
+ $r=Invoke-WelaProviderPackCommand -Action Configure -Names dns-client -Auto -BackupPath $backup
+ Assert ($r.Results[0].After.MaximumSizeInBytes -eq 4294967296 -and $r.Results[0].After.LogMode -eq 'Retain') 'Larger buffers and retention survive an enablement request.'
+ Reset;$r=Invoke-WelaProviderPackCommand -Action Configure -Names capi2 -Auto -BackupPath $backup
+ Assert ($r.ControlsPlan[0].Definition.sourceExampleBytes -eq 102432768 -and -not $r.ControlsPlan[0].Desired.AccessChangeRequested) 'CAPI2 reuses the exact existing profile and leaves reader ACL changes for channel-settings.'
+ foreach($failure in @('throw','nochange')){Reset;$f.NativeFailure=$failure;$r=Invoke-WelaProviderPackCommand -Action Configure -Names dns-client -Auto -BackupPath $backup;Assert ($r.ExitCode -eq 1) 'Native failure or false success cannot produce a verified configuration.'}
+ Reset;$f.Prompt='n';$r=Invoke-WelaProviderPackCommand -Action Configure -Names dns-client -BackupPath $backup
+ Assert ($r.Skipped -eq 1 -and $f.Writes.Count -eq 0) 'Operator decline is preserved.'
+ Reset;$f.PromptSchemaDrift=$true;$r=Invoke-WelaProviderPackCommand -Action Configure -Names dns-client -BackupPath $backup
+ Assert ($r.ExitCode -eq 1 -and $f.Writes.Count -eq 0) 'Schema changes after the prompt are refused before the native write.'
+ Reset;$f.DriftAt=5;$r=Invoke-WelaProviderPackCommand -Action Configure -Names dns-client -Auto -BackupPath $backup
+ Assert ($r.ExitCode -eq 1 -and $r.Results[0].Diagnostic -like '*Final verification*') 'Final provider-schema drift changes the overall outcome to failure.'
+ Throws {Get-WelaProviderTemplateFields ']>&y;'} 'Native template parser refuses DTD/entity expansion.'
+ Throws {Get-WelaProviderTemplateFields ''} 'Ambiguous template field names are refused.'
+ $tokens=$null;$errors=$null;$ast=[Management.Automation.Language.Parser]::ParseFile((Join-Path $repo 'WELA.ps1'),[ref]$tokens,[ref]$errors)
+ Assert ($errors.Count -eq 0) 'Combined public CLI parses.'
+ $nodes=@($ast.EndBlock.Statements|Where-Object {$_ -is [Management.Automation.Language.IfStatementAst] -and ($_.Extent.Text -match 'Provider options require' -or $_.Extent.Text -match 'Invoke-WelaProfileCommand -Command')})
+ Assert ($nodes.Count -eq 2) 'Provider option guard and profile dispatch are both retained.'
+ $dispatch=[scriptblock]::Create('param($Cmd,$Profile,$ProviderAction,$ProviderPack)'+[Environment]::NewLine+(($nodes|ForEach-Object {$_.Extent.Text})-join [Environment]::NewLine))
+ function Invoke-WelaProfileCommand {throw 'UNSAFE: profile dispatcher was reached'}
+ foreach($option in @('ProviderAction','ProviderPack')) { $args=@{Cmd='configure';Profile='wela'};$args[$option]='fixture';$caught=$null;try{& $dispatch @args}catch{$caught=$_.ToString()};Assert ($caught -like '*Provider options require*') 'Dedicated options are rejected before an unrelated profile could change policy.' }
+ Write-Host "PASS: $count native provider pack assertions; synthetic manifests only, no Windows changes."
+} finally {$env:OS=$oldOS;foreach($path in $cleanup){if(Test-Path -LiteralPath $path){Remove-Item -LiteralPath $path -Recurse -Force}}}
diff --git a/tests/NativeProviderPacks.Windows.Tests.ps1 b/tests/NativeProviderPacks.Windows.Tests.ps1
new file mode 100644
index 00000000..f5adcd4c
--- /dev/null
+++ b/tests/NativeProviderPacks.Windows.Tests.ps1
@@ -0,0 +1,44 @@
+# Real provider/channel metadata only. No DNS requests, service/channel or policy changes.
+param([string]$OutputDirectory)
+$ErrorActionPreference='Stop'
+$repo=Split-Path $PSScriptRoot -Parent
+Import-Module (Join-Path $repo 'modules/NativeProviders.psm1') -Force
+. (Join-Path $repo 'scripts/NativeProviderPacks.ps1')
+$catalog=Get-WelaProviderPackCatalog
+$count=0
+function Assert($Value,$Message){if(-not $Value){throw $Message};$script:count++}
+$before=@{}
+foreach($pack in $catalog.packs){$before[$pack.channel]=Get-WelaNativeChannel -Name $pack.channel}
+if(-not $OutputDirectory){$OutputDirectory=Join-Path ([IO.Path]::GetTempPath()) ('wela-provider-packs-'+[guid]::NewGuid().ToString('N'))}
+$null=New-Item -ItemType Directory -Path $OutputDirectory -Force
+$path=Join-Path $OutputDirectory 'provider-plan.json'
+$shell=(Get-Process -Id $PID).Path
+# PowerShell -File cannot reliably bind comma-separated native arguments to a
+# string[] in every edition; invoke from a temporary PowerShell script instead.
+$invoker=Join-Path $OutputDirectory 'invoke-read-only.ps1'
+$escapedRepo=$repo.Replace("'","''");$escapedPath=$path.Replace("'","''")
+@"
+`$ErrorActionPreference='Stop'
+`$global:LASTEXITCODE=0
+& '$escapedRepo/WELA.ps1' provider-packs -ProviderAction Plan -ProviderPack @('dns-client','dns-server-audit','dns-server-analytical','dns-server-classic','capi2','winrm','rdp-client') -ResultsPath '$escapedPath'
+exit `$global:LASTEXITCODE
+"@ | Set-Content -LiteralPath $invoker -Encoding UTF8
+$oldPreference=$ErrorActionPreference;$ErrorActionPreference='Continue'
+& $shell -NoProfile -File $invoker
+$code=$LASTEXITCODE;$ErrorActionPreference=$oldPreference
+$r=Get-Content -LiteralPath $path -Raw -ErrorAction Stop|ConvertFrom-Json
+Assert ($code -eq $r.ExitCode -and $code -in @(0,1)) "Real public CLI exit ($code) agrees with reported unavailable/manual prerequisites ($($r.ExitCode))."
+Assert ($r.Action -eq 'Plan' -and $r.ControlsPlan.Count -eq 7 -and $r.ReadyRules -eq 0) 'Actual plan retains all selected packs and no readiness credit.'
+Assert (@($r.ControlsPlan|Where-Object {$_.ProviderEvidence.Schema.State -eq 'Observed'}).Count -gt 0) 'At least one real Windows provider manifest must be read successfully.'
+$dns=@($r.ControlsPlan|Where-Object {$_.Pack.id -eq 'dns-client'})[0]
+Assert ($dns.RuleReviews.Count -eq 6 -and @($dns.RuleReviews|Where-Object {-not $_.ChannelMismatch}).Count -eq 0) 'Live report keeps the six full-definition DNS channel mismatches.'
+foreach($entry in $r.ControlsPlan){
+ $b=$before[$entry.Pack.channel];$a=Get-WelaNativeChannel -Name $entry.Pack.channel
+ Assert ($b.State -eq $a.State -and $b.IsEnabled -eq $a.IsEnabled -and $b.MaximumSizeInBytes -eq $a.MaximumSizeInBytes -and $b.LogMode -eq $a.LogMode -and $b.SecurityDescriptor -ceq $a.SecurityDescriptor) 'Read-only smoke preserves each observed channel state, buffer, retention and ACL.'
+ if($entry.ProviderEvidence.CanConfigure){
+ Assert ($entry.ProviderEvidence.Schema.ChannelType -in @('Administrative','Operational')) 'A configurable pack has an actual safe channel type.'
+ foreach($e in $entry.Pack.events){Assert (@($entry.ProviderEvidence.Schema.Events|Where-Object Id -eq $e.id).Count -gt 0) 'Actual event metadata belongs to the expected source/channel.'}
+ }
+}
+Write-Host "PASS: $count real Windows provider-manifest/read-only CLI assertions. No native events were generated; field values/backend matching remain untested."
+$global:LASTEXITCODE=0
diff --git a/website/docs/resources/changelog.ja.md b/website/docs/resources/changelog.ja.md
index d9bdf110..3aae6b0d 100644
--- a/website/docs/resources/changelog.ja.md
+++ b/website/docs/resources/changelog.ja.md
@@ -7,6 +7,7 @@
**改善:**
+- Windows標準のDNS Client/Server、CAPI2、WinRM、RDP Clientについて、明示的に選択するprovider-packsの監査・計画とチャネル設定を追加しました。固定した完全なルール定義と実際のプロバイダー・チャネル・イベントスキーマを確認し、DNSのチャネル名不一致や不明な前提条件を保持します。復旧記録付きの変更では大きいバッファ・保持方式・ACLを維持し、Analyticalと従来のDNSログは手動確認のみとします。イベント生成・バックエンド検証や検知範囲の向上は未確認です。 (#411) (@Shirofune-Security)
- 任意実行の`audit-notifications`を追加し、OneSettings監査とSecurityログ警告しきい値の監査・計画・設定に対応しました。対象とチャネル変更の明示指定、OS・ADMX確認、型付き復旧記録と変更検出を行い、既存の低いしきい値とチャネルACL・保存方式を保持します。ポリシー一致と実イベント生成を分け、Windowsラボの証拠とSigma利用可能性は未検証と表示します。 (#408) (@Shirofune-Security)
- 読み取り専用の`rule-eligibility`を追加し、ルール・対応表のハッシュ、ルールごとの判定理由、対象外の理由、分子・分母を明示します。任意で取り込んだラボ資料を、対応範囲を限定した完全なルール定義、ネイティブXML、設定、収集・クエリ実行の証拠と照合し、未対応・未確認の項目はConditionalとします。監査のCSV/JSON/HTMLとNavigator出力では、設定が有効なだけでルールを利用可能と判定しません。取り込んだReady判定は記録された環境・時点に限られ、実環境での一連の検証を保証しません。 (#407) (@Shirofune-Security)
diff --git a/website/docs/resources/changelog.md b/website/docs/resources/changelog.md
index 2273998a..1978b99a 100644
--- a/website/docs/resources/changelog.md
+++ b/website/docs/resources/changelog.md
@@ -7,6 +7,7 @@
**Improvements:**
+- Added explicit native DNS Client/Server, CAPI2, WinRM and RDP Client provider-pack inventory and selective channel configuration. Pinned full rule definitions and live provider/channel/event schemas retain DNS channel mismatches and unknown prerequisites; journaled opt-in changes preserve larger buffers, retention and ACLs. Analytical/classic DNS remain manual-only, and no event/backend readiness uplift is claimed. (#411) (@Shirofune-Security)
- Added opt-in `audit-notifications` audit/plan/configure for OneSettings auditing and Security log warning thresholds, with explicit control/channel selections, reviewed host and ADMX gates, typed recovery journals and drift checks. Earlier warning thresholds and channel ACL/retention are preserved. Reports separate policy matches from warning/event generation; Windows lab evidence and Sigma eligibility remain unverified. (#408) (@Shirofune-Security)
- Added read-only `rule-eligibility` reports with pinned corpus/mapping hashes, per-rule reasons, explicit scope exclusions and numerator/denominator totals. Optional imported lab artifacts are checked against a narrow complete-rule parser, native XML, configuration, ingestion and query evidence; unsupported or incomplete cases stay Conditional. Audit CSV/JSON/HTML and Navigator outputs no longer treat enabled settings as proven usable rules. Imported Ready results apply only to their recorded context/time; no live end-to-end validation is implied. (#407) (@Shirofune-Security)