Preserve bounded worker diagnostics and PS5 fixture encoding

This commit is contained in:
Shirofune-Security committed 2026-09-21 09:45:55 +09:00
1 parent 480ddea0b4
commit 49727ea482
7 files changed
+12 -10

No files matched your search

+1 -1
View File
@@ -4,7 +4,7 @@
**改善:**
- 既に有効なローカル保存先で、現在の実行ユーザーによる固定 Windows PowerShell 5.1 子プロセスの完了した自動トランスクリプトを検証する `transcript-probe` を追加しました。実トークン・ログオン、標準ヘッダー/フッター、nonce・PID・時刻、件数を制限したファイル識別と出典確認により不明な結果を保持し、ポリシーやACLの変更・明示的トランスクリプト開始・Sigma/EVTX加算は行いません。Server 2022/2025と両WELA実行エンジン向けに、使い捨て標準ユーザーの成功・拒否テストを追加しました。 (@Shirofune-Security)
- 既に有効なローカル保存先で、現在の実行ユーザーによる固定 Windows PowerShell 5.1 子プロセスの完了した自動トランスクリプトを検証する `transcript-probe` を追加しました。実トークン・ログオン、標準ヘッダー/フッター、nonce・PID・時刻、件数を制限したファイル識別と出典確認により不明な結果を保持し、ポリシーやACLの変更・明示的トランスクリプト開始・Sigma/EVTX加算は行いません。Server 2022/2025と両WELA実行エンジン向けに、使い捨て標準ユーザーの成功・拒否テストを追加しました。 (#436) (@Shirofune-Security)
- 読み取り専用の `channel-read` を追加し、実際の実行トークンで選択したWindows標準ローカルログを確認します。メタデータやACLとは独立して拒否・不在・空・イベント読取を区別し、トークンと環境の変化を検出して保護された限定レポートに記録します。Windows設定の変更やSigma利用可能数への加算は行いません。使い捨て標準ユーザーでServer 2022/2025・PowerShell 5.1/7の拒否と読取を検証します。 (#432) (@Shirofune-Security)
+1 -1
View File
@@ -4,7 +4,7 @@
**Improvements:**
- Added opt-in `transcript-probe` to verify a fixed current-account Windows PowerShell 5.1 child produces its own completed automatic transcript in an already enabled local destination. Actual token/logon, native header/footer, nonce/PID/time, bounded file identity and source checks preserve unverified outcomes without changing policy or ACLs, invoking explicit transcription or granting Sigma/EVTX credit. Added disposable standard-writer success/denial tests for Server 2022/2025 under both WELA host engines. (@Shirofune-Security)
- Added opt-in `transcript-probe` to verify a fixed current-account Windows PowerShell 5.1 child produces its own completed automatic transcript in an already enabled local destination. Actual token/logon, native header/footer, nonce/PID/time, bounded file identity and source checks preserve unverified outcomes without changing policy or ACLs, invoking explicit transcription or granting Sigma/EVTX credit. Added disposable standard-writer success/denial tests for Server 2022/2025 under both WELA host engines. (#436) (@Shirofune-Security)
- Added read-only `channel-read` to test actual current-token access to selected built-in local logs. Native query outcomes distinguish denied, missing, empty and observed-event reads independently of metadata/ACL inspection; token/context checks and bounded private reports preserve uncertainty without changing Windows settings or granting Sigma credit. Disposable standard-user denial/read tests cover Server 2022/2025 and PowerShell 5.1/7. (#432) (@Shirofune-Security)
+1 -1
View File
@@ -46,7 +46,7 @@ The inventory covers only the previous, current and next local calendar-date fol
The worker has a 30-second deadline. Each redirected output stream retains at most 64 KiB, with bounded pipe-drain and termination waits. The report includes explicit diagnostics for refusal and incomplete evidence; no fallback obtains a positive result.
A completed Run writes `result.json`, `worker.json` and the exact matching `transcript.txt` bytes into the protected output. Failed runs that reached output preparation keep diagnostic artifacts and exit nonzero. Prerequisite failures can occur before an output directory exists. Source transcripts are retained in their configured destination; WELA never removes them.
A completed Run writes `result.json`, `worker.json` and the exact matching `transcript.txt` bytes into the protected output. The result also retains bounded fixed-worker stdout/stderr and launch/exit observations, including when worker validation fails. Failed runs that reached output preparation keep diagnostic artifacts and exit nonzero. Prerequisite failures can occur before an output directory exists. Source transcripts are retained in their configured destination; WELA never removes them.
## Validation
+6 -4
View File
@@ -81,7 +81,7 @@ function Assert-WelaTranscriptProbeInventory {
}
}
function Start-WelaTranscriptProbeWorker {
param($State,[string]$Nonce,$ParentToken)
param($State,[string]$Nonce,$ParentToken,$LaunchEvidence)
$worker=Join-Path $PSScriptRoot 'TranscriptProbeWorker.ps1'
$arguments=@('-NoLogo','-NoProfile','-NonInteractive','-ExecutionPolicy','Bypass','-File',$worker,'-Nonce',$Nonce)
$info=[Diagnostics.ProcessStartInfo]::new();$info.FileName=$State.Engine
@@ -91,10 +91,12 @@ function Start-WelaTranscriptProbeWorker {
$process=[Diagnostics.Process]::new();$process.StartInfo=$info;$started=$false;$launched=[DateTime]::UtcNow
try{
if(-not $process.Start()){throw 'Fixed transcript worker did not start.'};$started=$true
$LaunchEvidence.ProcessId=$process.Id;$LaunchEvidence.LaunchedUtc=$launched.ToString('o')
$stdout=[Wela.TranscriptProbe.Item]::Drain($process.StandardOutput,65536);$stderr=[Wela.TranscriptProbe.Item]::Drain($process.StandardError,65536)
if(-not $process.WaitForExit(30000)){throw 'Fixed transcript worker exceeded thirty seconds.'}
$exited=[DateTime]::UtcNow
$exited=[DateTime]::UtcNow;$LaunchEvidence.ExitedUtc=$exited.ToString('o');$LaunchEvidence.ExitCode=$process.ExitCode
if(-not [Threading.Tasks.Task]::WaitAll([Threading.Tasks.Task[]]@($stdout,$stderr),3000)){throw 'Worker output pipes did not close within their bound.'}
$LaunchEvidence.Stdout=$stdout.Result;$LaunchEvidence.Stderr=$stderr.Result
if($stdout.Result.Exceeded -or $stderr.Result.Exceeded -or $stdout.Result.Error -or $stderr.Result.Error){throw 'Worker output is oversized or incomplete.'}
if($process.ExitCode -ne 0 -or $stderr.Result.Text){throw ('Fixed native5.1 worker failed; exit '+$process.ExitCode+'. No transcript fallback was attempted.')}
$lines=@(($stdout.Result.Text -replace "`r`n","`n").TrimEnd("`r","`n") -split "`n")
@@ -169,7 +171,7 @@ function Invoke-WelaTranscriptProbe {
$before=Get-WelaTranscriptProbeInventory $directoryPath $dates
if($Action -eq 'Plan'){return [pscustomobject]@{SchemaVersion=1;Kind='WelaAutomaticTranscriptPlan';Action='Plan';ExitCode=0;Status='ReadyToProbe';State=$state;Inventory=$before;Token=[Wela.WmiProbe.Native]::Snapshot();ReadyRuleCredit=0;SigmaEvtxCredit=0;WriterAuthorization='Unverified';Scope='One new native Windows PowerShell5.1 automatic transcript under this local current identity only'}}
$output=New-WelaArrivalOutput $OutputPath $directoryPath
$report=[pscustomobject][ordered]@{SchemaVersion=1;Kind='WelaAutomaticTranscriptProbe';Action='Run';Status='Unverified';ExitCode=1;RecordedUtc=[DateTime]::UtcNow.ToString('o');Before=$state;After=$null;InventoryBefore=$before;InventoryAfter=$null;ParentBefore=$null;ParentAfter=$null;Worker=$null;Transcript=$null;Artifacts=@();Diagnostic='';OutputPath=$output;ReadyRuleCredit=0;SigmaEvtxCredit=0;ConfigurationChanges=0;WriterAuthorization='Unverified';PowerShell7Sessions='Not assessed';Collection='Not verified';Scope='One fixed native5.1 completed automatic text transcript; no retention, immutable-storage or EVTX/Sigma claim'}
$report=[pscustomobject][ordered]@{SchemaVersion=1;Kind='WelaAutomaticTranscriptProbe';Action='Run';Status='Unverified';ExitCode=1;RecordedUtc=[DateTime]::UtcNow.ToString('o');Before=$state;After=$null;InventoryBefore=$before;InventoryAfter=$null;ParentBefore=$null;ParentAfter=$null;Worker=$null;WorkerLaunch=[pscustomobject]@{ProcessId=$null;LaunchedUtc=$null;ExitedUtc=$null;ExitCode=$null;Stdout=$null;Stderr=$null};Transcript=$null;Artifacts=@();Diagnostic='';OutputPath=$output;ReadyRuleCredit=0;SigmaEvtxCredit=0;ConfigurationChanges=0;WriterAuthorization='Unverified';PowerShell7Sessions='Not assessed';Collection='Not verified';Scope='One fixed native5.1 completed automatic text transcript; no retention, immutable-storage or EVTX/Sigma claim'}
try{
# Prepare metadata and evidence storage before capturing the actual process-token interval.
foreach($folder in $before.Folders|Where-Object Exists){$held=[Wela.TranscriptProbe.Item]::Directory($folder.Observation.Path);$heldFolders+= $held;if((Get-WelaTranscriptProbeObjectKey $held.Snapshot() -Directory) -cne (Get-WelaTranscriptProbeObjectKey $folder.Observation -Directory)){throw 'Date-directory changed before worker.'}}
@@ -179,7 +181,7 @@ function Invoke-WelaTranscriptProbe {
# Newly created unrelated files during preparation become baseline, never candidate evidence.
$before=$inventory;$report.InventoryBefore=$before
$token=[Wela.WmiProbe.Native]::Snapshot();$report.ParentBefore=$token
$operation=Start-WelaTranscriptProbeWorker $state ([guid]::NewGuid().ToString('N')) $token;$report.Worker=$operation
$operation=Start-WelaTranscriptProbeWorker $state ([guid]::NewGuid().ToString('N')) $token $report.WorkerLaunch;$report.Worker=$operation
$after=Get-WelaTranscriptProbeInventory $directoryPath $dates;$report.InventoryAfter=$after;Assert-WelaTranscriptProbeInventory $before $after
foreach($folder in $after.Folders|Where-Object Exists){$held=[Wela.TranscriptProbe.Item]::Directory($folder.Observation.Path);$heldFolders+=$held;if((Get-WelaTranscriptProbeObjectKey $held.Snapshot() -Directory) -cne (Get-WelaTranscriptProbeObjectKey $folder.Observation -Directory)){throw 'Date directory changed after worker.'}}
$candidates=@($after.Files|Where-Object{$_.Identity -cnotin @($before.Files.Identity)})
+1 -1
View File
@@ -1,4 +1,4 @@
$ErrorActionPreference='Stop';$script:ScriptRoot=Split-Path $PSScriptRoot -Parent
$ErrorActionPreference='Stop';$script:ScriptRoot=Split-Path $PSScriptRoot -Parent
. (Join-Path $script:ScriptRoot 'scripts/WefArrival.ps1')
. (Join-Path $script:ScriptRoot 'scripts/PowerShellTranscription.ps1')
. (Join-Path $script:ScriptRoot 'scripts/TranscriptProbe.ps1')
+1 -1
View File
@@ -7,7 +7,7 @@
**改善:**
- 既に有効なローカル保存先で、現在の実行ユーザーによる固定 Windows PowerShell 5.1 子プロセスの完了した自動トランスクリプトを検証する `transcript-probe` を追加しました。実トークン・ログオン、標準ヘッダー/フッター、nonce・PID・時刻、件数を制限したファイル識別と出典確認により不明な結果を保持し、ポリシーやACLの変更・明示的トランスクリプト開始・Sigma/EVTX加算は行いません。Server 2022/2025と両WELA実行エンジン向けに、使い捨て標準ユーザーの成功・拒否テストを追加しました。 (@Shirofune-Security)
- 既に有効なローカル保存先で、現在の実行ユーザーによる固定 Windows PowerShell 5.1 子プロセスの完了した自動トランスクリプトを検証する `transcript-probe` を追加しました。実トークン・ログオン、標準ヘッダー/フッター、nonce・PID・時刻、件数を制限したファイル識別と出典確認により不明な結果を保持し、ポリシーやACLの変更・明示的トランスクリプト開始・Sigma/EVTX加算は行いません。Server 2022/2025と両WELA実行エンジン向けに、使い捨て標準ユーザーの成功・拒否テストを追加しました。 (#436) (@Shirofune-Security)
- 読み取り専用の `channel-read` を追加し、実際の実行トークンで選択したWindows標準ローカルログを確認します。メタデータやACLとは独立して拒否・不在・空・イベント読取を区別し、トークンと環境の変化を検出して保護された限定レポートに記録します。Windows設定の変更やSigma利用可能数への加算は行いません。使い捨て標準ユーザーでServer 2022/2025・PowerShell 5.1/7の拒否と読取を検証します。 (#432) (@Shirofune-Security)
+1 -1
View File
@@ -7,7 +7,7 @@
**Improvements:**
- Added opt-in `transcript-probe` to verify a fixed current-account Windows PowerShell 5.1 child produces its own completed automatic transcript in an already enabled local destination. Actual token/logon, native header/footer, nonce/PID/time, bounded file identity and source checks preserve unverified outcomes without changing policy or ACLs, invoking explicit transcription or granting Sigma/EVTX credit. Added disposable standard-writer success/denial tests for Server 2022/2025 under both WELA host engines. (@Shirofune-Security)
- Added opt-in `transcript-probe` to verify a fixed current-account Windows PowerShell 5.1 child produces its own completed automatic transcript in an already enabled local destination. Actual token/logon, native header/footer, nonce/PID/time, bounded file identity and source checks preserve unverified outcomes without changing policy or ACLs, invoking explicit transcription or granting Sigma/EVTX credit. Added disposable standard-writer success/denial tests for Server 2022/2025 under both WELA host engines. (#436) (@Shirofune-Security)
- Added read-only `channel-read` to test actual current-token access to selected built-in local logs. Native query outcomes distinguish denied, missing, empty and observed-event reads independently of metadata/ACL inspection; token/context checks and bounded private reports preserve uncertainty without changing Windows settings or granting Sigma credit. Disposable standard-user denial/read tests cover Server 2022/2025 and PowerShell 5.1/7. (#432) (@Shirofune-Security)