从PowerShell访问Windows凭据管理器
我正在Windows Server 2008 R2上使用PowerShell 2.0(因SP2010而必需)。我需要从Windows凭据管理器检索进程的凭据。我似乎无法让它工作 我得到了这段代码:从PowerShell访问Windows凭据管理器,powershell,credential-manager,Powershell,Credential Manager,我正在Windows Server 2008 R2上使用PowerShell 2.0(因SP2010而必需)。我需要从Windows凭据管理器检索进程的凭据。我似乎无法让它工作 我得到了这段代码: [Windows.Security.Credentials.PasswordVault,Windows.Security.Credentials,ContentType=WindowsRuntime] (new-object Windows.Security.Credentials.PasswordV
[Windows.Security.Credentials.PasswordVault,Windows.Security.Credentials,ContentType=WindowsRuntime]
(new-object Windows.Security.Credentials.PasswordVault).RetrieveAll() | % { $_.RetrievePassword(); $_ }
两行代码都会抛出错误
Windows.Security.Credentials.PasswordVault,Windows.Security.Credentials,ContentType=WindowsRuntime : Unable to find type [Windows.Security.Credentials.PasswordVault,Windows.Security.Credentials,ContentType=WindowsRuntime]: make sure that the assembly containing this type is loaded.
及
分别。我一直在尝试以某种方式导入PasswordVault类。到目前为止,谷歌让我失望了,我甚至还没有找到它所在的程序集。我缺少什么?根据文档,Windows Server 2008 R2不支持PasswordVault类 支持的最低服务器数Windows server 2012
您需要访问Win32 API才能与凭据管理器交互 很好地证明了这一点 对于更简单的使用模式,如仅列出主体或添加新凭据,您还可以使用内置的Windows命令行实用程序进行凭据管理 为了重用PowerShell中存储的凭据,这家伙似乎找到了一种方法,使用与powershell5中的CredMan.ps1:类似的技术,从凭据存储库中的通用凭据句柄构建
PSCredential
:
Install-Module CredentialManager -force
然后
后来
Get-StoredCredential -Target ....
模块的源代码是这些powershell模块刚刚获得完整版本:。秘密可以是凭证
Install-Module Microsoft.PowerShell.SecretManagement
Install-Module SecretManagement.JustinGrote.CredMan # windows credential manager
Register-SecretVault SecretManagement.JustinGrote.CredMan
Set-Secret -Name TestSecret -Secret "TestSecret"
Get-Secret -Name TestSecret -AsPlainText
我发现了一个非常好的帖子,这段代码将打印所有用户名、资源和密码
[Windows.Security.Credentials.PasswordVault,Windows.Security.Credentials,ContentType=WindowsRuntime]
$vault=新对象Windows.Security.Credentials.PasswordVault
$vault.RetrieveAll()|%{$|.RetrievePassword();$|}
如果任何人只需要一段代码片段,这样他们就可以分发脚本,而无需指示最终用户安装模块或包含DLL文件,这应该可以做到
$code = @"
using System.Text;
using System;
using System.Runtime.InteropServices;
namespace CredManager {
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct CredentialMem
{
public int flags;
public int type;
public string targetName;
public string comment;
public System.Runtime.InteropServices.ComTypes.FILETIME lastWritten; // .NET 2.0
public int credentialBlobSize;
public IntPtr credentialBlob;
public int persist;
public int attributeCount;
public IntPtr credAttribute;
public string targetAlias;
public string userName;
}
public class Credential {
public string target;
public string username;
public string password;
public Credential(string target, string username, string password) {
this.target = target;
this.username = username;
this.password = password;
}
}
public class Util
{
[DllImport("advapi32.dll", EntryPoint = "CredReadW", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern bool CredRead(string target, int type, int reservedFlag, out IntPtr credentialPtr);
public static Credential GetUserCredential(string target)
{
CredentialMem credMem;
IntPtr credPtr;
if (CredRead(target, 1, 0, out credPtr))
{
credMem = Marshal.PtrToStructure<CredentialMem>(credPtr);
byte[] passwordBytes = new byte[credMem.credentialBlobSize];
Marshal.Copy(credMem.credentialBlob, passwordBytes, 0, credMem.credentialBlobSize);
Credential cred = new Credential(credMem.targetName, credMem.userName, Encoding.Unicode.GetString(passwordBytes));
return cred;
} else {
throw new Exception("Failed to retrieve credentials");
}
}
[DllImport("Advapi32.dll", SetLastError = true, EntryPoint = "CredWriteW", CharSet = CharSet.Unicode)]
private static extern bool CredWrite([In] ref CredentialMem userCredential, [In] int flags);
public static void SetUserCredential(string target, string userName, string password)
{
CredentialMem userCredential = new CredentialMem();
userCredential.targetName = target;
userCredential.type = 1;
userCredential.userName = userName;
userCredential.attributeCount = 0;
userCredential.persist = 3;
byte[] bpassword = Encoding.Unicode.GetBytes(password);
userCredential.credentialBlobSize = (int)bpassword.Length;
userCredential.credentialBlob = Marshal.StringToCoTaskMemUni(password);
if (!CredWrite(ref userCredential, 0))
{
throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
}
}
}
}
"@
Add-Type -TypeDefinition $code -Language CSharp
# How to store credentials
[CredManager.Util]::SetUserCredential("Application Name", "Username", "Password")
# How to retrieve credentials
[CredManager.Util]::GetUserCredential("Application Name")
# How to just get the password
[CredManager.Util]::GetUserCredential("Application Name").password
$code=@”
使用系统文本;
使用制度;
使用System.Runtime.InteropServices;
命名空间CredManager{
[StructLayout(LayoutKind.Sequential,CharSet=CharSet.Unicode)]
公共结构证书
{
公共国旗;
公共int类型;
公共字符串targetName;
公共字符串评论;
public System.Runtime.InteropServices.ComTypes.FILETIME LastWrite;//.NET 2.0
公共int-credentialBlobSize;
公共IntPtr证书blob;
公众参与;
公共int属性计数;
公共国际信托财产;
公共字符串targetAlias;
公共字符串用户名;
}
公共类凭证{
公共字符串目标;
公共字符串用户名;
公共字符串密码;
公共凭据(字符串目标、字符串用户名、字符串密码){
this.target=目标;
this.username=用户名;
this.password=密码;
}
}
公共类Util
{
[DllImport(“advapi32.dll”,EntryPoint=“crederaw”,CharSet=CharSet.Unicode,SetLastError=true)]
私有静态外部布尔凭证(字符串目标、int类型、int reservedFlag、out IntPtr凭证tr);
公共静态凭据GetUserCredential(字符串目标)
{
CredentialMem CredentialMem;
IntPtr credPtr;
if(CredRead(目标,1,0,出credPtr))
{
credMem=Marshal.ptr结构(credPtr);
byte[]passwordBytes=新字节[credMem.credentialBlobSize];
Marshal.Copy(credMem.credentialBlob,passwordBytes,0,credMem.credentialBlobSize);
Credential cred=新凭证(credMem.targetName、credMem.userName、Encoding.Unicode.GetString(passwordBytes));
回信;
}否则{
抛出新异常(“检索凭据失败”);
}
}
[DllImport(“Advapi32.dll”,SetLastError=true,EntryPoint=“CredWriteW”,CharSet=CharSet.Unicode)]
私有静态外部bool CredWrite([In]ref-CredentialMem-userCredential,[In]int标志);
公共静态void SetUserCredential(字符串目标、字符串用户名、字符串密码)
{
CredentialMem userCredential=新的CredentialMem();
userCredential.targetName=目标;
userCredential.type=1;
userCredential.userName=用户名;
userCredential.attributeCount=0;
userCredential.persist=3;
byte[]bpassword=Encoding.Unicode.GetBytes(密码);
userCredential.credentialBlobSize=(int)bpassword.Length;
userCredential.credentialBlob=Marshal.StringToCoTaskMemUni(密码);
如果(!CredWrite(ref userCredential,0))
{
抛出新的System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
}
}
}
}
"@
添加Type-TypeDefinition$code-Language CSharp
#如何存储凭据
[CredManager.Util]::SetUserCredential(“应用程序名”、“用户名”、“密码”)
#如何检索凭据
[CredManager.Util]::GetUserCredential(“应用程序名称”)
#如何获取密码
[CredManager.Util]::GetUserCredential(“应用程序名称”).密码
上面的代码是在PowerShell 7和PowerShell 5上测试的,不过如果您使用的是.Net framework,则可能需要.Net framework的最新版本。好的,重点放在这里。因此,我的问题是,如何在Windows Server 2008上访问凭据管理器?一定有办法。谢谢,只是为了确保,在我花时间研究它之前,它会允许我检索密码,对吗?不,至少
cmdkey
不会。为什么要检索密码?因为我需要使用存储在凭据管理器中的凭据远程调用进程。我认为这一部分是不言而喻的,如果不使用存储在其中的凭据,为什么我需要访问凭据管理器?在没有实施此类解决方案的任何实际经验的情况下,我认为这样做的“正确”方式是通过SSPI或类似方式导出令牌或安全上下文,我使用的是System.Managemens实例,而不是直接在纯文本中修改密码
Install-Module Microsoft.PowerShell.SecretManagement
Install-Module SecretManagement.JustinGrote.CredMan # windows credential manager
Register-SecretVault SecretManagement.JustinGrote.CredMan
Set-Secret -Name TestSecret -Secret "TestSecret"
Get-Secret -Name TestSecret -AsPlainText
TestSecret
$code = @"
using System.Text;
using System;
using System.Runtime.InteropServices;
namespace CredManager {
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct CredentialMem
{
public int flags;
public int type;
public string targetName;
public string comment;
public System.Runtime.InteropServices.ComTypes.FILETIME lastWritten; // .NET 2.0
public int credentialBlobSize;
public IntPtr credentialBlob;
public int persist;
public int attributeCount;
public IntPtr credAttribute;
public string targetAlias;
public string userName;
}
public class Credential {
public string target;
public string username;
public string password;
public Credential(string target, string username, string password) {
this.target = target;
this.username = username;
this.password = password;
}
}
public class Util
{
[DllImport("advapi32.dll", EntryPoint = "CredReadW", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern bool CredRead(string target, int type, int reservedFlag, out IntPtr credentialPtr);
public static Credential GetUserCredential(string target)
{
CredentialMem credMem;
IntPtr credPtr;
if (CredRead(target, 1, 0, out credPtr))
{
credMem = Marshal.PtrToStructure<CredentialMem>(credPtr);
byte[] passwordBytes = new byte[credMem.credentialBlobSize];
Marshal.Copy(credMem.credentialBlob, passwordBytes, 0, credMem.credentialBlobSize);
Credential cred = new Credential(credMem.targetName, credMem.userName, Encoding.Unicode.GetString(passwordBytes));
return cred;
} else {
throw new Exception("Failed to retrieve credentials");
}
}
[DllImport("Advapi32.dll", SetLastError = true, EntryPoint = "CredWriteW", CharSet = CharSet.Unicode)]
private static extern bool CredWrite([In] ref CredentialMem userCredential, [In] int flags);
public static void SetUserCredential(string target, string userName, string password)
{
CredentialMem userCredential = new CredentialMem();
userCredential.targetName = target;
userCredential.type = 1;
userCredential.userName = userName;
userCredential.attributeCount = 0;
userCredential.persist = 3;
byte[] bpassword = Encoding.Unicode.GetBytes(password);
userCredential.credentialBlobSize = (int)bpassword.Length;
userCredential.credentialBlob = Marshal.StringToCoTaskMemUni(password);
if (!CredWrite(ref userCredential, 0))
{
throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
}
}
}
}
"@
Add-Type -TypeDefinition $code -Language CSharp
# How to store credentials
[CredManager.Util]::SetUserCredential("Application Name", "Username", "Password")
# How to retrieve credentials
[CredManager.Util]::GetUserCredential("Application Name")
# How to just get the password
[CredManager.Util]::GetUserCredential("Application Name").password