Reserve registry probe capacity and isolate exact-value cleanup

This commit is contained in:
Shirofune-Security committed 2026-09-22 14:59:21 +09:00
1 parent 9575c8204d
commit d72bf939a7
4 files changed
+39 -3

No files matched your search

+15 -1
View File
@@ -7,7 +7,7 @@ function Reject([scriptblock]$Action){$threw=$false;try{& $Action|Out-Null}catch
function Copy-Value($Value){ConvertFrom-WelaArrivalJson (Get-WelaFileProbeKey $Value)}
function Fixture {
$script:token=[pscustomobject]@{Sid='S-1-5-21-1-2-3-1001';Name='FIXTURE\Reader';AuthenticationId='0x1234';AuthenticationType='Negotiate';ImpersonationLevel='None';TokenSource='Process';Groups=@([pscustomobject]@{Sid='S-1-1-0';Attributes=7});Privileges=@([pscustomobject]@{Luid='0x8';Attributes=0})}
$script:state=[pscustomobject]@{Computer='FIXTURE';Host=[pscustomobject]@{ProductType=3;Build=20348;DomainJoined=$false;Domain='WORKGROUP'};Services=@([pscustomobject]@{Name='EventLog';Status='Running'},[pscustomobject]@{Name='RpcSs';Status='Running'},[pscustomobject]@{Name='Winmgmt';Status='Running'});Reader=[pscustomobject]@{UserSid=$script:token.Sid;ElevatedAdministrator=$true;TokenType='Primary';Impersonation='Absent'};Token=Copy-Value $script:token;Registry=[pscustomobject]@{Path=('HKEY_USERS\'+$script:token.Sid+'\Software\WELA\AuditProbe');Kind='Registry';IsDirectory=$false;Identity='fixed:123';DescriptorBase64='AA==';SecurityInformation=511;Values=@();Aces=@([pscustomobject]@{Ordinary=$true;Type=2;Flags=64;Mask=2;Sid='S-1-1-0';Binary='AA=='})};AuditPolicies=[pscustomobject]@{'0CCE921E-69AE-11D9-BED3-505054503030'=1};Precedence=[pscustomobject]@{ValueExists=$true;Type='DWord';Value=1};Channel=[pscustomobject]@{Name='Security';Enabled=$true;SecurityDescriptor='O:SYG:SYD:'};Engine='C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe';EngineHash=('b'*64);Sources=[pscustomobject]@{Source=('c'*64)}}
$script:state=[pscustomobject]@{Computer='FIXTURE';Host=[pscustomobject]@{ProductType=3;Build=20348;DomainRole=2;DomainJoined=$false;Domain='WORKGROUP'};Services=@([pscustomobject]@{Name='EventLog';Status='Running'},[pscustomobject]@{Name='RpcSs';Status='Running'},[pscustomobject]@{Name='Winmgmt';Status='Running'});Reader=[pscustomobject]@{UserSid=$script:token.Sid;ElevatedAdministrator=$true;TokenType='Primary';Impersonation='Absent'};Token=Copy-Value $script:token;Registry=[pscustomobject]@{Path=('HKEY_USERS\'+$script:token.Sid+'\Software\WELA\AuditProbe');Kind='Registry';IsDirectory=$false;Identity='fixed:123';DescriptorBase64='AA==';SecurityInformation=511;Values=@();Aces=@([pscustomobject]@{Ordinary=$true;Type=2;Flags=64;Mask=2;Sid='S-1-1-0';Binary='AA=='})};AuditPolicies=[pscustomobject]@{'0CCE921E-69AE-11D9-BED3-505054503030'=1};Precedence=[pscustomobject]@{ValueExists=$true;Type='DWord';Value=1};Channel=[pscustomobject]@{Name='Security';Enabled=$true;SecurityDescriptor='O:SYG:SYD:'};Engine='C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe';EngineHash=('b'*64);Sources=[pscustomobject]@{Source=('c'*64)}}
$n='d'*32;$script:operation=[pscustomobject]@{Kind='WelaOwnedRegistryValueModification';Nonce=$n;ProcessId=1234;Executable=$script:state.Engine;RecordIdBefore=10;BeforeToken=Copy-Value $script:token;AfterToken=Copy-Value $script:token;LaunchedUtc='2026-09-21T00:00:00.0000000Z';ObservedUtc='2026-09-21T00:00:01.0000000Z';Native=[pscustomobject]@{Succeeded=$true;CleanupComplete=$true;Nonce=$n;Name=('WELA_Probe_'+$n);BeforeValue=('WELA_BEFORE_'+$n);AfterValue=('WELA_AFTER_'+$n);HandleId='0x888';Before=Copy-Value $script:state.Registry;After=Copy-Value $script:state.Registry;StartedUtc='2026-09-21T00:00:00.0001000Z';WriteReturnedUtc='2026-09-21T00:00:00.0001600Z';CompletedUtc='2026-09-21T00:00:00.0002000Z';Diagnostic=''}}
$script:stateReads=0;$script:attempts=0;$script:batchMode='match';$script:failArtifact=$null;$script:afterDrift=$false
}
@@ -22,6 +22,9 @@ foreach($bad in @('path','mask','precedence','channel','role','group','inherit-o
switch($bad){'path'{$script:state.Registry.Path='HKEY_LOCAL_MACHINE\Software\WELA\AuditProbe'};'mask'{$script:state.AuditPolicies.'0CCE921E-69AE-11D9-BED3-505054503030'=0};'precedence'{$script:state.Precedence.Value=$true};'channel'{$script:state.Channel.Enabled='true'};'role'{$script:state.Host.ProductType=$true};'group'{$script:state.Token.Groups[0].Attributes=16};'inherit-only'{$script:state.Registry.Aces[0].Flags=72};'failure'{$script:state.Registry.Aces[0].Flags=128};'callback'{$script:state.Registry.Aces[0].Ordinary=$false};'right'{$script:state.Registry.Aces[0].Mask=1};'descriptor'{$script:state.Registry.DescriptorBase64=$null};'sources'{$script:state.Sources.Source='bad'};'token'{$script:state.Token.TokenSource='Thread'}}
Reject {Get-WelaRegistryValueProbeStateKey $script:state}
}
foreach($badRole in @($null,$true,0,4)) {Fixture;$script:state.Host.DomainRole=$badRole;Reject {Get-WelaRegistryValueProbeStateKey $script:state}}
Fixture;$script:state.Host.DomainJoined=$true;Reject {Get-WelaRegistryValueProbeStateKey $script:state}
Fixture;$script:state.Host.Build=22631;Reject {Get-WelaRegistryValueProbeStateKey $script:state}
foreach($bad in @('nonce','success','cleanup','key','values','before','after','reverse','handle','token')){
Fixture
switch($bad){'nonce'{$script:operation.Nonce='invalid'};'success'{$script:operation.Native.Succeeded='true'};'cleanup'{$script:operation.Native.CleanupComplete=$false};'key'{$script:operation.Native.After.Path='wrong'};'values'{$script:operation.Native.After.Values=@('new')};'before'{$script:operation.Native.StartedUtc='2026-09-20T00:00:00Z'};'after'{$script:operation.Native.CompletedUtc='2026-09-22T00:00:00Z'};'reverse'{$script:operation.Native.WriteReturnedUtc='2026-09-21T00:00:00Z'};'handle'{$script:operation.Native.HandleId='0x0'};'token'{$script:operation.AfterToken.Privileges[0].Attributes=2}}
@@ -34,6 +37,17 @@ foreach($badXml in @($xml.Replace('</EventData>','<Data Name="OldValue">duplicat
function Initialize-WelaWmiProbeNative {}
Initialize-WelaRegistryValueProbe
Assert ([Wela.RegistryValueProbe.Descriptor]::SourceSha256 -ceq (Get-FileHash (Join-Path $script:ScriptRoot 'scripts/RegistryValueProbeNative.cs')).Hash.ToLowerInvariant()) 'Exact native source hash is bound.'
# The temporary value must fit the same inventory bounds used for final readback.
$small=[Wela.RegistryValueProbe.Value]::new();$small.Name='small';$small.Type=3;$small.DataBase64='AA=='
[Wela.RegistryValueProbe.Descriptor]::AssertProbeCapacity([Wela.RegistryValueProbe.Value[]]@((1..127|ForEach-Object{$small})))
Assert $true '127 original values leave room for exactly one owned marker.'
Reject {[Wela.RegistryValueProbe.Descriptor]::AssertProbeCapacity([Wela.RegistryValueProbe.Value[]]@((1..128|ForEach-Object{$small})))}
$large=[Wela.RegistryValueProbe.Value]::new();$large.Type=3;$large.DataBase64=[Convert]::ToBase64String([byte[]]::new(65536))
Reject {[Wela.RegistryValueProbe.Descriptor]::AssertProbeCapacity([Wela.RegistryValueProbe.Value[]]@((1..16|ForEach-Object{$large})))}
$reserved=[Text.Encoding]::Unicode.GetByteCount('WELA_BEFORE_'+('0'*32)+[char]0)
$tail=[Wela.RegistryValueProbe.Value]::new();$tail.Type=3;$tail.DataBase64=[Convert]::ToBase64String([byte[]]::new(65536-$reserved))
[Wela.RegistryValueProbe.Descriptor]::AssertProbeCapacity([Wela.RegistryValueProbe.Value[]](@((1..15|ForEach-Object{$large}))+@($tail)))
Assert $true 'Exactly reserved byte capacity is accepted.'
$writer=(Get-Command Write-WelaFileProbeArtifact).ScriptBlock
function Get-WelaFileProbeOutputKey {param($Path) 'private-fixture'}
function Write-WelaFileProbeArtifact {param($Root,$OutputKey,$Name,$Text) if($Name -eq $script:failArtifact){throw 'Injected artifact failure'};& $script:writer $Root $OutputKey $Name $Text}