Decrypt my World

Cryptography, Security, Debugging and more!

How to enumerate all certificates on a smart card (PowerShell)

How to enumerate all certificates on a smart card (PowerShell)

  • Comments 3

Hi all,

 

Some time ago I assisted my colleague Jeff Bowles with the development of a PowerShell script which enumerates all certificates on a smart card. Basically the replacement to CAPICOM.Store.Open CAPICOM_SMART_CARD_USER_STORE.

He developed a sample that returns System.Security.Cryptography.X509Certificates.X509Store object with the certificates in the card. The sample tries to emulate what logonUI.exe does during smart card logon as documented at Certificate Enumeration

Note that this code is also a great example that shows how we can use PowerShell to call Win32 API the same way we do it with any .NET application through P/Invoke mechanism:

 

function Get-SCUserStore {

[string]$providerName ="Microsoft Base Smart Card Crypto Provider"

# import CrytoAPI from advapi32.dll
$signature = @"
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
[return : MarshalAs(UnmanagedType.Bool)]
public static extern bool CryptGetProvParam(
IntPtr hProv,
uint dwParam,
byte[] pbProvData,
ref uint pdwProvDataLen,
uint dwFlags);

[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
[return : MarshalAs(UnmanagedType.Bool)]
public static extern bool CryptDestroyKey(
IntPtr hKey);

[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
[return : MarshalAs(UnmanagedType.Bool)]
public static extern bool CryptAcquireContext(
ref IntPtr hProv,
string pszContainer,
string pszProvider,
uint dwProvType,
long dwFlags);

[DllImport("advapi32.dll", CharSet=CharSet.Auto)]
[return : MarshalAs(UnmanagedType.Bool)]
public static extern bool CryptGetUserKey(
IntPtr hProv,
uint dwKeySpec,
ref IntPtr phUserKey);

[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CryptGetKeyParam(
IntPtr hKey,
uint dwParam,
byte[] pbData,
ref uint pdwDataLen,
uint dwFlags);

[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
[return : MarshalAs(UnmanagedType.Bool)]
public static extern bool CryptReleaseContext(
IntPtr hProv,
uint dwFlags);
"@

$CryptoAPI = Add-Type -member $signature -name advapiUtils -Namespace CryptoAPI -passthru

# set some constants for CryptoAPI
$AT_KEYEXCHANGE = 1
$AT_SIGNATURE = 2
$PROV_RSA_FULL = 1
$KP_CERTIFICATE = 26
$PP_ENUMCONTAINERS = 2
$PP_CONTAINER = 6
$PP_USER_CERTSTORE = 42
$CRYPT_FIRST = 1
$CRYPT_NEXT = 2
$CRYPT_VERIFYCONTEXT = 0xF0000000

[System.IntPtr]$hProvParent=0
$contextRet = $CryptoAPI::CryptAcquireContext([ref]$hprovParent,$null,$providerName,$PROV_RSA_FULL,$CRYPT_VERIFYCONTEXT)

[Uint32]$pdwProvDataLen = 0
[byte[]]$pbProvData = $null
$GetProvParamRet = $CryptoAPI::CryptGetProvParam($hprovParent,$PP_CONTAINER,$pbProvData,[ref]$pdwProvDataLen,0)

if($pdwProvDataLen -gt 0)
{
$ProvData = new-Object byte[] $pdwProvDataLen
$GetKeyParamRet = $CryptoAPI::CryptGetProvParam($hprovParent,$PP_CONTAINER,$ProvData,[ref]$pdwProvDataLen,0)
}

$enc = new-object System.Text.UTF8Encoding($null)
$keyContainer = $enc.GetString($ProvData)

write-host " The Default User Key Container:" $keyContainer

[Uint32]$pdwProvDataLen = 0
[byte[]]$pbProvData = $null
$GetProvParamRet = $CryptoAPI::CryptGetProvParam($hprovParent,$PP_USER_CERTSTORE,$pbProvData,[ref]$pdwProvDataLen,0)

if($pdwProvDataLen -gt 0)
{
$ProvData = new-Object byte[] $pdwProvDataLen
$GetKeyParamRet = $CryptoAPI::CryptGetProvParam($hprovParent,$PP_USER_CERTSTORE,$ProvData,[ref]$pdwProvDataLen,0)
[uint32]$provdataInt = [System.BitConverter]::ToUInt32($provdata,0)
[System.IntPtr]$hwStore = $provdataInt
}

$store = new-object System.Security.Cryptography.X509Certificates.X509Store($hwStore)

# release smart card
$ReleaseContextRet = $CryptoAPI::CryptReleaseContext($hprovParent,0)

return $store
}

write-host ((get-WmiObject win32_PnPSignedDriver|where{$_.deviceID -like "*smartcard*"}).devicename) "reports the following certificates;"

# returns System.Security.Cryptography.X509Certificates.X509Store object representing PP_USER_CERTSTORE on Smart Card
$SCcertStore = Get-SCuserSTore

# enumerate certificates
$SCcertStore.certificates

 

 

 

I hope this helps. And THANKS A LOT JEFF for sharing the final sample with me and the community!!! Kudos!!!

Regards,

 

Alex (Alejandro Campos Magencio)

  • Awesome!

    I would love to see more examples on accessing CryptoAPI unmanaged APIs via Windows PowerShell.

    p.s. As always enjoy the automation of tools within the Windows-based, .NET aware, WPF accessible, multi-processes on the same IP/Port usage, admin's automation tools, PowerShell! © Flowering Weeds

  • HOw could i get the thumbprint from these?

  • Great Script, works like a charm if you type the proper CSP provider of your card.

    If you avoid using a function it's really fast otherwise it takes a couple of seconds to show the certificate.

Page 1 of 1 (3 items)
Leave a Comment
  • Please add 5 and 3 and type the answer here:
  • Post
Translate This Page