在模拟下调用时,CredWrite返回1312
本文关键字:CredWrite 返回 1312 模拟 调用 | 更新日期: 2023-09-27 18:29:36
我有一个应用程序,用户在其中输入凭据,我用它创建一个WindowsIdentity对象,然后用它模拟与输入凭据对应的用户并进行CredWrite调用。然而,它正在返回
ERROR_NO_SUCH_LOGON_SESSION1312(0x520)指定的登录会话不存在。它可能已经被终止。
当我取出模拟代码时,一切都如预期的那样工作。然而,即使我模拟自己(当前登录的用户),也会返回相同的1312错误。
我对自己做错了什么感到困惑。任何建议都将不胜感激。
IntPtr token = new IntPtr(0);
securityUtils = new Security.Utility();
string user = "someuser";
string pass = "somepassword";
token = securityUtils.GetToken(user, "somedomain", pass.ConvertToSecureString());
var newId = new WindowsIdentity(token);
string currentUser1 = WindowsIdentity.GetCurrent().Name;
Impersonation.Impersonate(newId);
string currentUser2 = WindowsIdentity.GetCurrent().Name;
int result = WriteCredential("dummykey", user.ConvertToSecureString(), pass.ConvertToSecureString());
Impersonation.UnImpersonate();
string currentUser3 = WindowsIdentity.GetCurrent().Name;
GetToken方法进行LogoUser调用。我已经通过查看currentUser1/2/3验证了模拟是否有效。
WriteCredential方法如下所示:
public static int WriteCredential(string key, SecureString userName, SecureString password)
{
if (string.IsNullOrEmpty(key))
{
throw new ArgumentNullException("key is null or empty");
}
if (userName == null || userName.Length == 0)
{
throw new ArgumentNullException("userName is null or empty");
}
if (password == null || password.Length == 0)
{
throw new ArgumentNullException("password is null or empty");
}
string passwordAsString = password.ConvertToUnsecureString();
byte[] byteArray = Encoding.Unicode.GetBytes(passwordAsString);
if (byteArray.Length > MaximumCredentialBlobSize)
{
throw new ArgumentOutOfRangeException(string.Format("The password message has exceeded {0} bytes.", MaximumCredentialBlobSize));
}
Credential cred = new Credential();
cred.TargetName = System.Runtime.InteropServices.Marshal.StringToCoTaskMemUni(key);
cred.CredentialBlob = System.Runtime.InteropServices.Marshal.StringToCoTaskMemUni(passwordAsString);
cred.CredentialBlobSize = (uint)Encoding.Unicode.GetBytes(passwordAsString).Length;
cred.AttributeCount = 0;
cred.Attributes = IntPtr.Zero;
cred.Comment = IntPtr.Zero;
cred.TargetAlias = System.Runtime.InteropServices.Marshal.StringToCoTaskMemUni(key);
cred.Type = CredentialType.CRED_TYPE_GENERIC;
cred.Persist = Persistance.CRED_PERSIST_ENTERPRISE;
cred.UserName = System.Runtime.InteropServices.Marshal.StringToCoTaskMemUni(userName.ConvertToUnsecureString());
bool written = CredWrite(ref cred, 0);
int lastError = Marshal.GetLastWin32Error();
if (!written)
{
return lastError;
}
return 0;
}
凭证结构:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private struct Credential
{
public uint Flags;
public CredentialType Type;
public IntPtr TargetName;
public IntPtr Comment;
public System.Runtime.InteropServices.ComTypes.FILETIME LastWritten;
public uint CredentialBlobSize;
public IntPtr CredentialBlob;
public Persistance Persist;
public uint AttributeCount;
public IntPtr Attributes;
public IntPtr TargetAlias;
public IntPtr UserName;
}
DllImport:
[DllImport("Advapi32.dll", EntryPoint = "CredWriteW", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern bool CredWrite([In] ref Credential userCredential, [In] uint flags);
解决方案是在进行WriteCredential调用之前显式加载要模拟的用户的配置文件。在模拟该用户之前进行LoadProfile调用非常重要。