C # Utilisation de CredWrite pour accéder à C $

J’essaie d’accéder au C $ d’un serveur avec un compte de domaine qui n’a pas les droits sur ce serveur. Je dois enregistrer les informations d’identification sous la forme d’une connexion locale pour ce serveur afin que le programme fonctionne correctement.

Comment enregistrer ces informations d’identification à l’aide de CredWrite

La classe Credential Manager que j’ai trouvée: (EDIT: le code ci-dessous fonctionne.)

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.InteropServices; using Microsoft.Win32.SafeHandles; namespace Test_Manager { public class Win32CredMan { [DllImport("Advapi32.dll", EntryPoint = "CredReadW", CharSet = CharSet.Unicode, SetLastError = true)] static extern bool CredRead(ssortingng target, CRED_TYPE type, int reservedFlag, out IntPtr CredentialPtr); [DllImport("Advapi32.dll", EntryPoint = "CredWriteW", CharSet = CharSet.Unicode, SetLastError = true)] static extern bool CredWrite([In] ref NativeCredential userCredential, [In] UInt32 flags); [DllImport("Advapi32.dll", EntryPoint = "CredFree", SetLastError = true)] static extern bool CredFree([In] IntPtr cred); public enum CRED_TYPE : uint { GENERIC = 1, DOMAIN_PASSWORD = 2, DOMAIN_CERTIFICATE = 3, DOMAIN_VISIBLE_PASSWORD = 4, GENERIC_CERTIFICATE = 5, DOMAIN_EXTENDED = 6, MAXIMUM = 7, // Maximum supported cred type MAXIMUM_EX = (MAXIMUM + 1000), // Allow new applications to run on old OSes } public enum CRED_PERSIST : uint { SESSION = 1, LOCAL_MACHINE = 2, ENTERPRISE = 3, } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] private struct NativeCredential { public UInt32 Flags; public CRED_TYPE Type; public IntPtr TargetName; public IntPtr Comment; public System.Runtime.InteropServices.ComTypes.FILETIME LastWritten; public UInt32 CredentialBlobSize; public IntPtr CredentialBlob; public UInt32 Persist; public UInt32 AtsortingbuteCount; public IntPtr Atsortingbutes; public IntPtr TargetAlias; public IntPtr UserName; ///  /// This method derives a NativeCredential instance from a given Credential instance. ///  /// The managed Credential counterpart containing data to be stored. /// A NativeCredential instance that is derived from the given Credential /// instance. internal static NativeCredential GetNativeCredential(Credential cred) { NativeCredential ncred = new NativeCredential(); ncred.AtsortingbuteCount = 0; ncred.Atsortingbutes = IntPtr.Zero; ncred.Comment = IntPtr.Zero; ncred.TargetAlias = IntPtr.Zero; ncred.Type = (CRED_TYPE)cred.Type; ncred.Persist = (UInt32)cred.Persist; ncred.CredentialBlobSize = (UInt32)cred.CredentialBlobSize; ncred.TargetName = Marshal.SsortingngToCoTaskMemUni(cred.TargetName); ncred.CredentialBlob = Marshal.SsortingngToCoTaskMemUni(cred.CredentialBlob); ncred.UserName = Marshal.SsortingngToCoTaskMemUni(cred.UserName); return ncred; } } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] private struct Credential { public UInt32 Flags; public CRED_TYPE Type; public ssortingng TargetName; public ssortingng Comment; public System.Runtime.InteropServices.ComTypes.FILETIME LastWritten; public UInt32 CredentialBlobSize; public ssortingng CredentialBlob; public CRED_PERSIST Persist; public UInt32 AtsortingbuteCount; public IntPtr Atsortingbutes; public ssortingng TargetAlias; public ssortingng UserName; } #region Critical Handle Type definition sealed class CriticalCredentialHandle : CriticalHandleZeroOrMinusOneIsInvalid { // Set the handle. internal CriticalCredentialHandle(IntPtr preexistingHandle) { SetHandle(preexistingHandle); } internal Credential GetCredential() { if (!IsInvalid) { // Get the Credential from the mem location NativeCredential ncred = (NativeCredential)Marshal.PtrToStructure(handle, typeof(NativeCredential)); // Create a managed Credential type and fill it with data from the native counterpart. Credential cred = new Credential(); cred.CredentialBlobSize = ncred.CredentialBlobSize; cred.CredentialBlob = Marshal.PtrToSsortingngUni(ncred.CredentialBlob, (int)ncred.CredentialBlobSize / 2); cred.UserName = Marshal.PtrToSsortingngUni(ncred.UserName); cred.TargetName = Marshal.PtrToSsortingngUni(ncred.TargetName); cred.TargetAlias = Marshal.PtrToSsortingngUni(ncred.TargetAlias); cred.Type = ncred.Type; cred.Flags = ncred.Flags; cred.Persist = (CRED_PERSIST)ncred.Persist; return cred; } else { throw new InvalidOperationException("Invalid CriticalHandle!"); } } // Perform any specific actions to release the handle in the ReleaseHandle method. // Often, you need to use Pinvoke to make a call into the Win32 API to release the // handle. In this case, however, we can use the Marshal class to release the unmanaged memory. override protected bool ReleaseHandle() { // If the handle was set, free it. Return success. if (!IsInvalid) { // NOTE: We should also ZERO out the memory allocated to the handle, before free'ing it // so there are no traces of the sensitive data left in memory. CredFree(handle); // Mark the handle as invalid for future users. SetHandleAsInvalid(); return true; } // Return false. return false; } } #endregion public int WriteCred(ssortingng key, ssortingng user, ssortingng secret) { // Validations. byte[] byteArray = Encoding.Unicode.GetBytes(secret); if (byteArray.Length > 512) throw new ArgumentOutOfRangeException("The secret message has exceeded 512 bytes."); // Go ahead with what we have are stuff it into the CredMan structures. Credential cred = new Credential(); cred.TargetName = key; cred.UserName = user; cred.CredentialBlob = secret; cred.CredentialBlobSize = (UInt32)Encoding.Unicode.GetBytes(secret).Length; cred.AtsortingbuteCount = 0; cred.Atsortingbutes = IntPtr.Zero; cred.Comment = null; cred.TargetAlias = null; cred.Type = CRED_TYPE.DOMAIN_PASSWORD; cred.Persist = CRED_PERSIST.ENTERPRISE; NativeCredential ncred = NativeCredential.GetNativeCredential(cred); // Write the info into the CredMan storage. bool written = CredWrite(ref ncred, 0); int lastError = Marshal.GetLastWin32Error(); if (written) { return 0; } else { ssortingng message = ssortingng.Format("CredWrite failed with the error code {0}.", lastError); throw new Exception(message); } } public static ssortingng ReadCred(ssortingng key) { // Validations. IntPtr nCredPtr; ssortingng readPasswordText = null; // Make the API call using the P/Invoke signature bool read = CredRead(key, CRED_TYPE.GENERIC, 0, out nCredPtr); int lastError = Marshal.GetLastWin32Error(); // If the API was successful then... if (read) { using (CriticalCredentialHandle critCred = new CriticalCredentialHandle(nCredPtr)) { Credential cred = critCred.GetCredential(); readPasswordText = cred.CredentialBlob; } } else { readPasswordText = ssortingng.Empty; //1168 is "element not found" -- ignore that one and return empty ssortingng: if (lastError != 1168) { ssortingng message = ssortingng.Format("ReadCred failed with the error code {0}.", lastError); throw new Exception(message); } } return readPasswordText; } } } 

En résumé, voici la méthode du code ci-dessus que j’essaie d’utiliser:

 public int WriteCred(ssortingng key, ssortingng user, ssortingng secret) { // Validations. byte[] byteArray = Encoding.Unicode.GetBytes(secret); if (byteArray.Length > 512) throw new ArgumentOutOfRangeException("The secret message has exceeded 512 bytes."); // Go ahead with what we have are stuff it into the CredMan structures. Credential cred = new Credential(); cred.TargetName = key; cred.UserName = user; cred.CredentialBlob = secret; cred.CredentialBlobSize = (UInt32)Encoding.Unicode.GetBytes(secret).Length; cred.AtsortingbuteCount = 0; cred.Atsortingbutes = IntPtr.Zero; cred.Comment = null; cred.TargetAlias = null; cred.Type = CRED_TYPE.DOMAIN_PASSWORD; cred.Persist = CRED_PERSIST.ENTERPRISE; NativeCredential ncred = NativeCredential.GetNativeCredential(cred); // Write the info into the CredMan storage. bool written = CredWrite(ref ncred, 0); int lastError = Marshal.GetLastWin32Error(); if (written) { return 0; } else { ssortingng message = ssortingng.Format("CredWrite failed with the error code {0}.", lastError); throw new Exception(message); } } 

Et voici ce que je fais dans le corps du programme:

 Win32CredMan cm = new Win32CredMan(); cm.WriteCred("TheServer-18", @"TheServer-18\Administrator", "P4SSw0rD!"); 

Je suppose que je n’ai pas access car les informations d’identification ne sont pas ajoutées correctement.

METTRE À JOUR:

Le processus que j’ai décrit consiste à append une référence générique à Windows Credential Manager. Cependant, si n’utilise pas le nom d’utilisateur spécifié dans la méthode WriteCred. Je ne comprends pas pourquoi.

Le problème est résolu et le code ci-dessus est maintenant pleinement fonctionnel. Le problème concernait GetNativeCredential: il n’utilisait pas les valeurs atsortingbuées à cred dans la méthode WriteCred, mais plutôt des valeurs statiques configurées.

En outre, la manière dont je saisissais les informations dans la méthode WriteCred était incorrecte. Le code ci-dessus a été corrigé afin qu’il fonctionne pleinement.