gpt4 book ai didi

powershell - 查看智能卡上的所有证书

转载 作者:行者123 更新时间:2023-12-03 09:36:01 27 4
gpt4 key购买 nike

我正在尝试创建一个脚本,以从任何给定的智能卡(当时在 SC 阅读器中)删除除最新证书之外的所有证书。这是我打算能够分发给最终用户的东西,所以它应该是自给自足的。我的第一个问题是阅读卡上的证书。我不想影响任何不在智能卡上的证书,所以我寻找了直接从卡中读取的解决方案,我找到了这个 gem:

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

它很旧,但看起来它应该做我需要的。它似乎确实可以正常工作,但是当我到达线路时 PowerShell ISE 崩溃了:

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

我可以通过排除 ($hwStore) 创建一个默认为“我的”商店的通用商店。从那一行没有问题,但指定该商店可靠地崩溃了我的 PowerShell ISE。

这是该站点的功能,我遇到问题的那条线靠近底部。

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
}

我对 P/Invoke 没有任何经验(我想我说的是对的),所以我不确定如何对从这种方式导入的东西派生的命令进行故障排除。

编辑:certutil -scinfo -silent 列出的提供商是:

Microsoft Base Smart Card Crypto Provider
Microsoft Smart Card Key Storage Provider

我已经尝试了以下脚本中的两个,最终结果相同。当脚本告诉我我的默认用户 key 容器是什么时,第二个给了我 � 字符,所以我觉得它不正确。

我也按照 Vesper 的建议尝试了 x86 版本的 PowerShell。应用程序不会崩溃,并且会返回一个带有我的智能卡证书的有效存储。现在的问题是我无法将其发送给用户,因为期望他们能够导航到 x86 版本的 PowerShell 然后使用它运行脚本就像期望我的狗给我做华夫饼......我想它可能会发生,但更有可能出现问题,无论如何我最终不得不自己做。

编辑 2:好的,所以我想我会强制脚本的那部分在 x86 模式下运行。我会用我更新的代码发布答案并接受它。如果@Vesper 发布有关 64/32 位问题的答案(希望能提供更多信息),我将接受他的回答,以便他获得信任,因为他的评论是我找到解决方案的原因。

最佳答案

因此,主要问题实际上是您将 x86 DLL 链接到 x64 Powershell 进程。你可以检查你的Powershell进程是否是x64 like here (通过查询 (Get-Process -Id $PID).StartInfo.EnvironmentVariables["PROCESSOR_ARCHITECTURE"] ),如果检测到 x64 Powershell,手动启动位于 $env:windir\syswow64\WindowsPowerShell\v1.0\powershell.exe 的 Powershell (x86)使用相同的脚本。要获取脚本的全名,请使用 $MyInvocation.MyCommand.Definition .如果检测到 Powershell 为 x86,则继续导入类型并运行枚举。一个例子:

$Arch = (Get-Process -Id $PID).StartInfo.EnvironmentVariables["PROCESSOR_ARCHITECTURE"];
$Arch
if ($arch -eq "AMD64") {
$here=$myinvocation.mycommand.definition
"$here launched as $arch!"
start-process C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe -NoNewWindow -ArgumentList $here -wait
return
}
"now running under x86"

关于powershell - 查看智能卡上的所有证书,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30880793/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com