From 7184918f660442201f12ac8b321a232b6b93e1a5 Mon Sep 17 00:00:00 2001 From: Shirofune-Security <43838376+Shirofune-Security@users.noreply.github.com> Date: Mon, 21 Sep 2026 17:53:39 +0900 Subject: [PATCH] Create an unnamed CNG key through typed native helper --- scripts/Capi2ProbeNative.cs | 8 ++++++++ scripts/Capi2ProbeWorker.ps1 | 5 +---- tests/Capi2Probe.Tests.ps1 | 2 +- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/scripts/Capi2ProbeNative.cs b/scripts/Capi2ProbeNative.cs index 43874bc8..bfb93f64 100644 --- a/scripts/Capi2ProbeNative.cs +++ b/scripts/Capi2ProbeNative.cs @@ -2,9 +2,17 @@ using System; using System.ComponentModel; using System.Runtime.InteropServices; +using System.Security.Cryptography; namespace Wela.Capi2Probe { public sealed class ChainResult { public uint Flags, ErrorStatus, InfoStatus, Chains, Elements; } public static class Native { + public static CngKey CreateEphemeralRsa() { + CngKeyCreationParameters parameters=new CngKeyCreationParameters(); + parameters.Provider=CngProvider.MicrosoftSoftwareKeyStorageProvider; + parameters.Parameters.Add(new CngProperty("Length",BitConverter.GetBytes(2048),CngPropertyOptions.None)); + // Literal null is essential: PowerShell converts a null string argument to empty. + return CngKey.Create(CngAlgorithm.Rsa,null,parameters); + } public const uint OfflineFlags=0x80002104; // cache-only URL/revocation, no AIA, no auth-root auto-update [StructLayout(LayoutKind.Sequential)] struct Usage { public uint Count; public IntPtr Oids; } [StructLayout(LayoutKind.Sequential)] struct Match { public uint Type; public Usage Usage; } diff --git a/scripts/Capi2ProbeWorker.ps1 b/scripts/Capi2ProbeWorker.ps1 index 0e79352d..a99ae510 100644 --- a/scripts/Capi2ProbeWorker.ps1 +++ b/scripts/Capi2ProbeWorker.ps1 @@ -8,10 +8,7 @@ Initialize-WelaCapi2ProbeNative $before=[Wela.WmiProbe.Native]::Snapshot() $key=$null;$rsa=$null;$certificate=$null try { - $parameters=[Security.Cryptography.CngKeyCreationParameters]::new() - $parameters.Provider=[Security.Cryptography.CngProvider]::MicrosoftSoftwareKeyStorageProvider - $parameters.Parameters.Add([Security.Cryptography.CngProperty]::new('Length',[BitConverter]::GetBytes([int]2048),[Security.Cryptography.CngPropertyOptions]::None)) - $key=[Security.Cryptography.CngKey]::Create([Security.Cryptography.CngAlgorithm]::Rsa,$null,$parameters) + $key=[Wela.Capi2Probe.Native]::CreateEphemeralRsa() if(-not $key.IsEphemeral -or $key.KeyName){throw 'The generated CNG key is not ephemeral.'} $rsa=[Security.Cryptography.RSACng]::new($key) $request=[Security.Cryptography.X509Certificates.CertificateRequest]::new(('CN=WelaCapi2Probe_'+$Nonce),$rsa,[Security.Cryptography.HashAlgorithmName]::SHA256,[Security.Cryptography.RSASignaturePadding]::Pkcs1) diff --git a/tests/Capi2Probe.Tests.ps1 b/tests/Capi2Probe.Tests.ps1 index a4f394e1..e59d4343 100644 --- a/tests/Capi2Probe.Tests.ps1 +++ b/tests/Capi2Probe.Tests.ps1 @@ -10,7 +10,7 @@ function Clone($Value){ConvertFrom-WelaArrivalJson ($Value|ConvertTo-Json -Depth $nonce='0123456789abcdef0123456789abcdef';$now=[DateTime]::UtcNow $token=[pscustomobject]@{Sid='S-1-5-21-1-2-3-1001';Name='HOST\user';AuthenticationId='0x1234';AuthenticationType='NTLM';Groups=@([pscustomobject]@{Sid='S-1-5-32-545';Attributes=7});Privileges=@()} $state=[pscustomobject]@{Computer='HOST';Host=[pscustomobject]@{Computer='HOST';Build=20348;UBR=1;ProductType=3;DomainJoined=$false;Domain='WORKGROUP'};Token=$token;Channel=[pscustomobject]@{Name='Microsoft-Windows-CAPI2/Operational';Enabled=$true;SecurityDescriptor='O:SYG:SYD:(A;;1;;;SY)';Type='Operational';Provider='Microsoft-Windows-CAPI2'};Provider=[pscustomobject]@{Name='Microsoft-Windows-CAPI2';Guid='5bbca4a8-b209-48dc-a8c7-b23d3e5216fb';Event11Versions=@(0);LogNames=@('Microsoft-Windows-CAPI2/Operational')}} -$rsa=[Security.Cryptography.RSA]::Create();$rsa.KeySize=2048;$cert=$null +if([Environment]::OSVersion.Platform -eq [PlatformID]::Win32NT){$rsa=[Security.Cryptography.RSACng]::new(2048)}else{$rsa=[Security.Cryptography.RSA]::Create();$rsa.KeySize=2048};$cert=$null try{ $request=[Security.Cryptography.X509Certificates.CertificateRequest]::new(('CN=WelaCapi2Probe_'+$nonce),$rsa,[Security.Cryptography.HashAlgorithmName]::SHA256,[Security.Cryptography.RSASignaturePadding]::Pkcs1) $cert=$request.CreateSelfSigned(([DateTimeOffset]$now).AddMinutes(-5),([DateTimeOffset]$now).AddMinutes(5))