[CmdletBinding()] param( [ValidateSet("Check", "Apply")][string]$Mode = "Check", [Parameter(Mandatory = $true)][ValidatePattern("^[A-Za-z0-9][A-Za-z0-9._:@+-]{0,127}$")][string]$TraceId, [Parameter(Mandatory = $true)][ValidatePattern("^[0-9a-f-]{36}$")][string]$RunId, [Parameter(Mandatory = $true)][ValidatePattern("^[A-Za-z0-9][A-Za-z0-9._:@+-]{0,127}$")][string]$WorkItemId, [Parameter(Mandatory = $true)][ValidatePattern("^[0-9a-f]{40}$")][string]$SourceRevision, [string]$AgentRoot = "C:\Wooo\Agent99" ) Set-StrictMode -Version Latest $ErrorActionPreference = "Stop" $ProgressPreference = "SilentlyContinue" [Console]::InputEncoding = [System.Text.UTF8Encoding]::new($false) [Console]::OutputEncoding = [System.Text.UTF8Encoding]::new($false) $global:OutputEncoding = [System.Text.UTF8Encoding]::new($false) $SchemaVersion = "agent99_windows_control_baseline_v1" $CanonicalAsset = "host:192.168.0.99/windows-control-baseline" $ExpectedComputerName = "WOOO-SUPER" $ExpectedUserName = "Administrator" $PreservedCulture = "zh-TW" $PreservedChineseLanguage = "zh-Hant-TW" $FallbackLanguage = "en-US" $FallbackInputTip = "0409:00000409" $ConsoleRegistryPath = "HKCU:\Console" $EvidenceRoot = [System.IO.Path]::GetFullPath((Join-Path $AgentRoot "evidence\")) $EvidencePath = [System.IO.Path]::GetFullPath((Join-Path $EvidenceRoot "agent99-WindowsControlBaseline-$RunId.json")) $startedAt = Get-Date $actions = @() $errorCode = $null $errorClass = $null $independentReadback = $null $rollbackAttempted = $false $rollbackVerified = $false $writeAttempted = $false $before = $null $after = $null $beforeLanguageList = $null $beforeOverride = $null $beforeConsoleValueExists = $false $beforeConsoleCodePage = $null $beforeSshdStartMode = "" if (-not $EvidencePath.StartsWith($EvidenceRoot, [System.StringComparison]::OrdinalIgnoreCase)) { throw "evidence_path_outside_agent_root" } function Write-AtomicJson { param([string]$Path, [object]$Value) [System.IO.Directory]::CreateDirectory((Split-Path -Parent $Path)) | Out-Null $temporaryPath = "$Path.tmp" [System.IO.File]::WriteAllText($temporaryPath, ($Value | ConvertTo-Json -Depth 20), [System.Text.UTF8Encoding]::new($false)) Move-Item -LiteralPath $temporaryPath -Destination $Path -Force } function Get-ConsoleCodePageState { if (-not (Test-Path -LiteralPath $ConsoleRegistryPath -PathType Container)) { return [pscustomobject]@{ valueExists = $false; value = $null } } $properties = Get-ItemProperty -LiteralPath $ConsoleRegistryPath -ErrorAction Stop $property = $properties.PSObject.Properties["CodePage"] if (-not $property) { return [pscustomobject]@{ valueExists = $false; value = $null } } return [pscustomobject]@{ valueExists = $true; value = [int]$property.Value } } function Get-DefaultInputMethodTip { $override = Get-WinDefaultInputMethodOverride if (-not $override) { return $null } $property = $override.PSObject.Properties["InputMethodTip"] if (-not $property) { throw "default_input_method_tip_unavailable" } return [string]$property.Value } function Get-WindowsControlSnapshot { $languageList = Get-WinUserLanguageList $languageRows = @( foreach ($language in $languageList) { [pscustomobject]@{ languageTag = [string]$language.LanguageTag inputMethodTips = @($language.InputMethodTips | ForEach-Object { [string]$_ }) } } ) $overrideTip = Get-DefaultInputMethodTip $consoleState = Get-ConsoleCodePageState $sshdService = Get-Service -Name "sshd" -ErrorAction Stop $sshdCim = Get-CimInstance -ClassName Win32_Service -Filter "Name='sshd'" -ErrorAction Stop [pscustomobject]@{ computerName = [string]$env:COMPUTERNAME userName = [string]$env:USERNAME culture = [string](Get-Culture).Name uiCulture = [string](Get-UICulture).Name systemLocale = [string](Get-WinSystemLocale).Name languages = $languageRows defaultInputMethodOverride = $overrideTip consoleCodePageValueExists = [bool]$consoleState.valueExists consoleCodePage = if ($consoleState.valueExists) { [int]$consoleState.value } else { $null } sshdStatus = [string]$sshdService.Status sshdStartMode = [string]$sshdCim.StartMode } } function Get-LanguageSignatures { param([object[]]$Languages) $signatures = @() foreach ($language in @($Languages)) { if (@($language.inputMethodTips).Count -eq 0) { $signatures += "$([string]$language.languageTag)|" continue } foreach ($tip in @($language.inputMethodTips)) { $signatures += "$([string]$language.languageTag)|$([string]$tip)" } } return @($signatures | Sort-Object -Unique) } function Test-WindowsControlSnapshot { param( [object]$Snapshot, [object]$PreserveFrom, [switch]$IndependentProcess ) $languageTags = @($Snapshot.languages | ForEach-Object { [string]$_.languageTag }) $languageSignatures = @(Get-LanguageSignatures $Snapshot.languages) $preservedSignatures = @(Get-LanguageSignatures $PreserveFrom.languages) $missingPreserved = @($preservedSignatures | Where-Object { $_ -notin $languageSignatures }) $fallbackSignature = "$FallbackLanguage|$FallbackInputTip" $checks = [ordered]@{ canonicalComputer = [string]$Snapshot.computerName -eq $ExpectedComputerName canonicalUser = [string]$Snapshot.userName -ieq $ExpectedUserName culturePreserved = [string]$Snapshot.culture -eq $PreservedCulture uiCulturePreserved = if ($IndependentProcess) { $PreservedChineseLanguage -in $languageTags -and [string]$Snapshot.systemLocale -eq $PreservedCulture } else { [string]$Snapshot.uiCulture -eq $PreservedCulture } systemLocalePreserved = [string]$Snapshot.systemLocale -eq $PreservedCulture chineseLanguagePreserved = $PreservedChineseLanguage -in $languageTags priorInputMethodsPreserved = $missingPreserved.Count -eq 0 englishFallbackPresent = $fallbackSignature -in $languageSignatures defaultInputIsUsKeyboard = [string]$Snapshot.defaultInputMethodOverride -eq $FallbackInputTip consoleUtf8 = [bool]$Snapshot.consoleCodePageValueExists -and [int]$Snapshot.consoleCodePage -eq 65001 sshdRunning = [string]$Snapshot.sshdStatus -eq "Running" sshdAutomatic = [string]$Snapshot.sshdStartMode -eq "Auto" } [pscustomobject]@{ passed = @($checks.GetEnumerator() | Where-Object { -not $_.Value }).Count -eq 0 checks = [pscustomobject]$checks missingPreservedLanguageSignatures = $missingPreserved } } function Get-SnapshotSignature { param([object]$Snapshot) # Process UI culture and user-name casing differ in a no-profile verifier. $normalized = [ordered]@{ computerName = ([string]$Snapshot.computerName).ToLowerInvariant() userName = ([string]$Snapshot.userName).ToLowerInvariant() culture = [string]$Snapshot.culture systemLocale = [string]$Snapshot.systemLocale languages = @(Get-LanguageSignatures $Snapshot.languages) defaultInputMethodOverride = [string]$Snapshot.defaultInputMethodOverride consoleCodePageValueExists = [bool]$Snapshot.consoleCodePageValueExists consoleCodePage = if ($null -ne $Snapshot.consoleCodePage) { [int]$Snapshot.consoleCodePage } else { $null } sshdStatus = [string]$Snapshot.sshdStatus sshdStartMode = [string]$Snapshot.sshdStartMode } return ($normalized | ConvertTo-Json -Depth 8 -Compress) } function Invoke-IndependentSnapshot { $verifierScript = @' $ErrorActionPreference = "Stop" $ProgressPreference = "SilentlyContinue" [Console]::OutputEncoding = [System.Text.UTF8Encoding]::new($false) $languageList = Get-WinUserLanguageList $languages = @(foreach ($language in $languageList) { [pscustomobject]@{ languageTag = [string]$language.LanguageTag; inputMethodTips = @($language.InputMethodTips | ForEach-Object { [string]$_ }) } }) $override = Get-WinDefaultInputMethodOverride $overrideTip = if ($override -and $override.PSObject.Properties["InputMethodTip"]) { [string]$override.InputMethodTip } else { $null } $consolePath = "HKCU:\Console" $consoleExists = $false $consoleCodePage = $null if (Test-Path -LiteralPath $consolePath -PathType Container) { $properties = Get-ItemProperty -LiteralPath $consolePath -ErrorAction Stop $property = $properties.PSObject.Properties["CodePage"] if ($property) { $consoleExists = $true; $consoleCodePage = [int]$property.Value } } $sshd = Get-Service -Name "sshd" -ErrorAction Stop $sshdCim = Get-CimInstance -ClassName Win32_Service -Filter "Name='sshd'" -ErrorAction Stop [ordered]@{ processId = $PID snapshot = [ordered]@{ computerName = [string]$env:COMPUTERNAME userName = [string]$env:USERNAME culture = [string](Get-Culture).Name uiCulture = [string](Get-UICulture).Name systemLocale = [string](Get-WinSystemLocale).Name languages = $languages defaultInputMethodOverride = $overrideTip consoleCodePageValueExists = $consoleExists consoleCodePage = $consoleCodePage sshdStatus = [string]$sshd.Status sshdStartMode = [string]$sshdCim.StartMode } } | ConvertTo-Json -Depth 10 -Compress '@ $encoded = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($verifierScript)) $token = [Guid]::NewGuid().ToString("N") $stdoutPath = Join-Path $env:TEMP "agent99-windows-baseline-$token.out" $stderrPath = Join-Path $env:TEMP "agent99-windows-baseline-$token.err" try { $process = Start-Process -FilePath "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" ` -ArgumentList @("-NoLogo", "-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-EncodedCommand", $encoded) ` -NoNewWindow -RedirectStandardOutput $stdoutPath -RedirectStandardError $stderrPath -PassThru if (-not $process.WaitForExit(120 * 1000)) { try { & taskkill.exe /PID $process.Id /T /F 2>&1 | Out-Null } catch {} throw "independent_verifier_timeout" } $process.WaitForExit() | Out-Null $process.Refresh() if ([int]$process.ExitCode -ne 0) { throw "independent_verifier_failed" } try { return (Get-Content -LiteralPath $stdoutPath -Raw | ConvertFrom-Json) } catch { throw "independent_verifier_receipt_invalid" } } finally { Remove-Item -LiteralPath $stdoutPath, $stderrPath -Force -ErrorAction SilentlyContinue } } function Set-WindowsControlBaseline { $languageList = Get-WinUserLanguageList $languageTags = @(foreach ($language in $languageList) { [string]$language.LanguageTag }) if ($FallbackLanguage -notin $languageTags) { $fallback = New-WinUserLanguageList $FallbackLanguage $languageList.Add($fallback[0]) | Out-Null Set-WinUserLanguageList -LanguageList $languageList -Force $script:actions += "added_en_us_keyboard_fallback" $script:writeAttempted = $true } if ([string](Get-DefaultInputMethodTip) -ne $FallbackInputTip) { Set-WinDefaultInputMethodOverride -InputTip $FallbackInputTip $script:actions += "set_default_input_method_us_keyboard" $script:writeAttempted = $true } $consoleState = Get-ConsoleCodePageState if (-not $consoleState.valueExists -or [int]$consoleState.value -ne 65001) { New-Item -Path $ConsoleRegistryPath -Force | Out-Null New-ItemProperty -Path $ConsoleRegistryPath -Name "CodePage" -Value 65001 -PropertyType DWord -Force | Out-Null $script:actions += "set_future_console_code_page_utf8" $script:writeAttempted = $true } $sshd = Get-Service -Name "sshd" -ErrorAction Stop $sshdCim = Get-CimInstance -ClassName Win32_Service -Filter "Name='sshd'" -ErrorAction Stop if ([string]$sshdCim.StartMode -ne "Auto") { Set-Service -Name "sshd" -StartupType Automatic $script:actions += "set_sshd_automatic" $script:writeAttempted = $true } if ([string]$sshd.Status -ne "Running") { Start-Service -Name "sshd" $script:actions += "start_sshd" $script:writeAttempted = $true } } function Restore-WindowsControlBaseline { Set-WinUserLanguageList -LanguageList $beforeLanguageList -Force if ($beforeOverride) { Set-WinDefaultInputMethodOverride -InputTip ([string]$beforeOverride) } else { Set-WinDefaultInputMethodOverride } if ($beforeConsoleValueExists) { New-Item -Path $ConsoleRegistryPath -Force | Out-Null New-ItemProperty -Path $ConsoleRegistryPath -Name "CodePage" -Value ([int]$beforeConsoleCodePage) -PropertyType DWord -Force | Out-Null } else { Remove-ItemProperty -LiteralPath $ConsoleRegistryPath -Name "CodePage" -ErrorAction SilentlyContinue } $startupType = switch ($beforeSshdStartMode) { "Auto" { "Automatic" } "Manual" { "Manual" } "Disabled" { "Disabled" } default { "Automatic" } } Set-Service -Name "sshd" -StartupType $startupType } try { $beforeLanguageList = Get-WinUserLanguageList $beforeOverride = Get-DefaultInputMethodTip $beforeConsoleState = Get-ConsoleCodePageState $beforeConsoleValueExists = [bool]$beforeConsoleState.valueExists $beforeConsoleCodePage = $beforeConsoleState.value $beforeSshdStartMode = [string](Get-CimInstance -ClassName Win32_Service -Filter "Name='sshd'" -ErrorAction Stop).StartMode $before = Get-WindowsControlSnapshot if ([string]$before.computerName -ne $ExpectedComputerName) { throw "canonical_computer_mismatch" } if ([string]$before.userName -ine $ExpectedUserName) { throw "canonical_user_mismatch" } if ($Mode -eq "Apply") { Set-WindowsControlBaseline } $after = Get-WindowsControlSnapshot $independentReadback = Invoke-IndependentSnapshot } catch { $errorClass = $_.Exception.GetType().Name $candidateCode = [string]$_.Exception.Message $errorCode = if ($candidateCode -match "^[A-Za-z0-9_:-]{1,96}$") { $candidateCode } else { "windows_control_baseline_failed" } } $postCondition = if ($after -and $before) { Test-WindowsControlSnapshot $after $before } else { $null } $independentPostCondition = if ($independentReadback -and $before) { Test-WindowsControlSnapshot $independentReadback.snapshot $before -IndependentProcess } else { $null } $independentAgreement = [bool]( $after -and $independentReadback -and (Get-SnapshotSignature $after) -eq (Get-SnapshotSignature $independentReadback.snapshot) ) $runtimeVerified = [bool]( -not $errorCode -and $postCondition -and $independentPostCondition -and $postCondition.passed -and $independentPostCondition.passed -and $independentAgreement ) if ($Mode -eq "Apply" -and $writeAttempted -and -not $runtimeVerified) { $rollbackAttempted = $true try { Restore-WindowsControlBaseline $rollbackSnapshot = Get-WindowsControlSnapshot $rollbackVerified = (Get-SnapshotSignature $rollbackSnapshot) -eq (Get-SnapshotSignature $before) } catch { $rollbackVerified = $false } } $finishedAt = Get-Date $terminal = if ($Mode -eq "Check" -and $runtimeVerified) { "verified_check_no_write" } elseif ($runtimeVerified -and $writeAttempted) { "runtime_verified_controlled_apply" } elseif ($runtimeVerified) { "runtime_verified_healthy_no_write" } elseif ($rollbackAttempted -and $rollbackVerified) { "rolled_back_verified" } else { "degraded_with_safe_next_action" } $passed = [bool]( ($Mode -eq "Check" -and $runtimeVerified) -or ($Mode -eq "Apply" -and $runtimeVerified) ) $receipt = [ordered]@{ schemaVersion = $SchemaVersion traceId = $TraceId runId = $RunId workItemId = $WorkItemId generatedAt = $finishedAt.ToString("o") sourceRevision = $SourceRevision executor = "host:192.168.0.99" target = $CanonicalAsset mode = $Mode risk = [ordered]@{ level = if ($Mode -eq "Apply") { "medium" } else { "low" }; hostReboot = $false; userLogoff = $false; guiInteraction = $false; clipboardUsed = $false; secretValueRead = $false } desired = [ordered]@{ preservedCulture = $PreservedCulture; preservedLanguage = $PreservedChineseLanguage; fallbackLanguage = $FallbackLanguage; fallbackInputTip = $FallbackInputTip; consoleCodePage = 65001; sshd = "Running/Auto" } check = [ordered]@{ before = $before; postCondition = $postCondition } execution = [ordered]@{ performed = $writeAttempted; actions = @($actions); errorCode = $errorCode; errorClass = $errorClass; elapsedMs = [math]::Round(($finishedAt - $startedAt).TotalMilliseconds) } verifier = [ordered]@{ independentProcessId = if ($independentReadback) { [int]$independentReadback.processId } else { $null }; readback = if ($independentReadback) { $independentReadback.snapshot } else { $null }; postCondition = $independentPostCondition; exactAgreement = $independentAgreement; passed = $runtimeVerified } rollback = [ordered]@{ attempted = $rollbackAttempted; verified = $rollbackVerified; sshdStopAllowed = $false } transport = [ordered]@{ encodedCommandCompatible = $true; interactiveInputRequired = $false; inputMethodIndependent = $true; utf8Output = $true } telegramNotificationSent = $false kmRagWritebackPerformed = $false terminal = $terminal } Write-AtomicJson -Path $EvidencePath -Value $receipt [ordered]@{ evidencePath = $EvidencePath evidenceSha256 = (Get-FileHash -LiteralPath $EvidencePath -Algorithm SHA256).Hash.ToLowerInvariant() terminal = $terminal mode = $Mode writePerformed = $writeAttempted ready = if ($postCondition) { [bool]$postCondition.passed } else { $false } independentVerifier = $independentAgreement rollbackAttempted = $rollbackAttempted rollbackVerified = $rollbackVerified errorCode = $errorCode } | ConvertTo-Json -Compress -Depth 8 if (-not $passed) { exit 3 } exit 0