Last active
January 19, 2024 16:03
-
-
Save awakecoding/d19afb26788e7664fe3428214c2494ae to your computer and use it in GitHub Desktop.
Revisions
-
awakecoding revised this gist
Jan 19, 2024 . 1 changed file with 32 additions and 25 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -45,26 +45,26 @@ function ConvertTo-CertCredentialMarshaledString { ) if ($CertHash.Length -ne 40) { throw "Unexpected certificate hash string length: $($CertHash.Length) (SHA1 hex string is 40 characters or 20 bytes)" } $hashBytes = [System.Linq.Enumerable]::Range(0, $CertHash.Length / 2).ForEach({ [Byte]::Parse($CertHash.Substring($_ * 2, 2), [System.Globalization.NumberStyles]::HexNumber) }) $certCredential = [WinCred.CERT_CREDENTIAL_INFO]@{ cbSize = [System.Runtime.InteropServices.Marshal]::SizeOf([type][WinCred.CERT_CREDENTIAL_INFO]) rgbHashOfCert = $hashBytes } $marshaledCredentialPtr = [IntPtr]::Zero $result = [WinCred.pinvoke]::CredMarshalCredentialW([WinCred.CRED_MARSHAL_TYPE]::CertCredential, [ref]$certCredential, [ref]$marshaledCredentialPtr) if ($result) { $marshaledCredential = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($marshaledCredentialPtr) [System.Runtime.InteropServices.Marshal]::FreeCoTaskMem($marshaledCredentialPtr) return $marshaledCredential } } function ConvertFrom-CertCredentialMarshaledString { @@ -74,19 +74,19 @@ function ConvertFrom-CertCredentialMarshaledString { ) if (-Not ($MarshaledCredential.StartsWith('@@') -and $MarshaledCredential.Length -eq 30)) { throw "Unexpected certificate credential marshaled string format: 30 characters, starting with '@@'" } $credType = [WinCred.CRED_MARSHAL_TYPE]::CertCredential $unmarshaledCredentialPtrForUnmarshalling = [IntPtr]::Zero $unmarshalResult = [WinCred.pinvoke]::CredUnmarshalCredentialW($MarshaledCredential, [ref]$credType, [ref]$unmarshaledCredentialPtrForUnmarshalling) if ($unmarshalResult -and $credType -eq [WinCred.CRED_MARSHAL_TYPE]::CertCredential) { $unmarshaledCredential = [System.Runtime.InteropServices.Marshal]::PtrToStructure($unmarshaledCredentialPtrForUnmarshalling, [type][WinCred.CERT_CREDENTIAL_INFO]) $hashString = -join ($unmarshaledCredential.rgbHashOfCert | ForEach-Object { $_.ToString("X2") }) [System.Runtime.InteropServices.Marshal]::FreeCoTaskMem($unmarshaledCredentialPtrForUnmarshalling) return $hashString } } # @@ -112,4 +112,11 @@ function ConvertFrom-CertCredentialMarshaledString { # username:s:@@BSxT#CyQZRSTgS#0d1kbebRaZeiJ # # Alternatively, you can literally paste the "@@"-prefixed string in the mstsc username field before connecting. # # Since the "@@"-prefixed string corresponds to a certificate thumbprint in the current user certificate store, # you can use it to find and export the corresponding certificate for closer inspection: # # $Thumbprint = ConvertFrom-CertCredentialMarshaledString "@@BSxT#CyQZRSTgS#0d1kbebRaZeiJ" # $Certificate = Get-Item "cert:\CurrentUser\My\$Thumbprint" # Export-Certificate -Cert $Certificate -FilePath "${Thumbprint}.crt" # -
awakecoding created this gist
Aug 8, 2023 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,115 @@ Add-Type -TypeDefinition @" using System; using System.Runtime.InteropServices; namespace WinCred { public enum CRED_MARSHAL_TYPE { CertCredential = 1, UsernameTargetCredential, BinaryBlobCredential, UsernameForPackedCredentials, BinaryBlobForSystem } [StructLayout(LayoutKind.Sequential)] public struct CERT_CREDENTIAL_INFO { public uint cbSize; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] public byte[] rgbHashOfCert; } public static class pinvoke { [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)] public static extern bool CredMarshalCredentialW( CRED_MARSHAL_TYPE CredType, ref CERT_CREDENTIAL_INFO Credential, out IntPtr MarshaledCredential); [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)] public static extern bool CredUnmarshalCredentialW( string MarshaledCredential, out CRED_MARSHAL_TYPE CredType, out IntPtr Credential); } } "@ -Language CSharp function ConvertTo-CertCredentialMarshaledString { param( [Parameter(Mandatory=$true,Position=0,ValueFromPipeline=$true)] [string] $CertHash ) if ($CertHash.Length -ne 40) { throw "Unexpected certificate hash string length: $($CertHash.Length) (SHA1 hex string is 40 characters or 20 bytes)" } $hashBytes = [System.Linq.Enumerable]::Range(0, $CertHash.Length / 2).ForEach({ [Byte]::Parse($CertHash.Substring($_ * 2, 2), [System.Globalization.NumberStyles]::HexNumber) }) $certCredential = [WinCred.CERT_CREDENTIAL_INFO]@{ cbSize = [System.Runtime.InteropServices.Marshal]::SizeOf([type][WinCred.CERT_CREDENTIAL_INFO]) rgbHashOfCert = $hashBytes } $marshaledCredentialPtr = [IntPtr]::Zero $result = [WinCred.pinvoke]::CredMarshalCredentialW([WinCred.CRED_MARSHAL_TYPE]::CertCredential, [ref]$certCredential, [ref]$marshaledCredentialPtr) if ($result) { $marshaledCredential = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($marshaledCredentialPtr) [System.Runtime.InteropServices.Marshal]::FreeCoTaskMem($marshaledCredentialPtr) return $marshaledCredential } } function ConvertFrom-CertCredentialMarshaledString { param( [Parameter(Mandatory=$true,Position=0,ValueFromPipeline=$true)] [string] $MarshaledCredential ) if (-Not ($MarshaledCredential.StartsWith('@@') -and $MarshaledCredential.Length -eq 30)) { throw "Unexpected certificate credential marshaled string format: 30 characters, starting with '@@'" } $credType = [WinCred.CRED_MARSHAL_TYPE]::CertCredential $unmarshaledCredentialPtrForUnmarshalling = [IntPtr]::Zero $unmarshalResult = [WinCred.pinvoke]::CredUnmarshalCredentialW($MarshaledCredential, [ref]$credType, [ref]$unmarshaledCredentialPtrForUnmarshalling) if ($unmarshalResult -and $credType -eq [WinCred.CRED_MARSHAL_TYPE]::CertCredential) { $unmarshaledCredential = [System.Runtime.InteropServices.Marshal]::PtrToStructure($unmarshaledCredentialPtrForUnmarshalling, [type][WinCred.CERT_CREDENTIAL_INFO]) $hashString = -join ($unmarshaledCredential.rgbHashOfCert | ForEach-Object { $_.ToString("X2") }) [System.Runtime.InteropServices.Marshal]::FreeCoTaskMem($unmarshaledCredentialPtrForUnmarshalling) return $hashString } } # # Find all smartcard client authentication certificates in the current user store and convert the # thumbprint (SHA1) to a marshaled "username" credential string used in RDP for smartcard selection: # # Get-ChildItem -Path cert:\CurrentUser\My | Where-Object { # $_.EnhancedKeyUsageList.ObjectId -contains "1.3.6.1.5.5.7.3.2" -and # Client Authentication OID # $_.EnhancedKeyUsageList.ObjectId -contains "1.3.6.1.4.1.311.20.2.2" # Smart Card Logon OID # } | Select-Object -Property Thumbprint,Subject, # @{l='CertCredentialMarshaledString';e={ConvertTo-CertCredentialMarshaledString($_.Thumbprint)}} # # Thumbprint Subject CertCredentialMarshaledString # ---------- ------- ----------------------------- # 523CF9820C65913481924F7735B9795BA4659E98 CN=Administrator, CN=Users, DC=ad, DC=it-help, DC=ninja @@BSxT#CyQZRSTgS#0d1kbebRaZeiJ # # Sample values with the thumbprint and marshalled credential string equivalents: # # ConvertTo-CertCredentialMarshaledString "523CF9820C65913481924F7735B9795BA4659E98" # ConvertFrom-CertCredentialMarshaledString "@@BSxT#CyQZRSTgS#0d1kbebRaZeiJ" # # Use the "@@"-prefixed string in the .RDP file as the username like this to pre-select a smartcard certificate: # username:s:@@BSxT#CyQZRSTgS#0d1kbebRaZeiJ # # Alternatively, you can literally paste the "@@"-prefixed string in the mstsc username field before connecting. #