/// <summary> /// Locate a certificate in the User/My store by thumbprint, marshal the certificate into a CERT_CREDENTIAL_INFO /// struct, and then perform a LogonUser call with the certificate credential struct /// </summary> /// <param name="thumbprint">The thumbprint of a certificate to marshal into a CERT_CREDENTIAL_INFO struct</param> static void MarshalFlow(string thumbprint) { // // Set up the data struct // NativeMethods.CERT_CREDENTIAL_INFO certInfo = new NativeMethods.CERT_CREDENTIAL_INFO(); certInfo.cbSize = (uint)Marshal.SizeOf(typeof(NativeMethods.CERT_CREDENTIAL_INFO)); // // Locate the certificate in the certificate store // X509Certificate2 certCredential = new X509Certificate2(); X509Store userMyStore = new X509Store(StoreName.My, StoreLocation.CurrentUser); userMyStore.Open(OpenFlags.ReadOnly); X509Certificate2Collection certsReturned = userMyStore.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, false); userMyStore.Close(); if (certsReturned.Count == 0) { Console.WriteLine("Could not find the cert you want, aborting"); return; } // // Marshal the certificate // certCredential = certsReturned[0]; certInfo.rgbHashOfCert = certCredential.GetCertHash(); int size = Marshal.SizeOf(certInfo); IntPtr pCertInfo = Marshal.AllocHGlobal(size); Marshal.StructureToPtr(certInfo, pCertInfo, false); IntPtr marshaledCredential = IntPtr.Zero; bool result = NativeMethods.CredMarshalCredential(NativeMethods.CRED_MARSHAL_TYPE.CertCredential, pCertInfo, out marshaledCredential); string certBlobForUsername = null; PSCredential psCreds = null; if (result) { certBlobForUsername = Marshal.PtrToStringUni(marshaledCredential); psCreds = new PSCredential(certBlobForUsername, new SecureString()); } Marshal.FreeHGlobal(pCertInfo); if (marshaledCredential != IntPtr.Zero) { NativeMethods.CredFree(marshaledCredential); } Console.WriteLine("Certificate Credential Data: " + certBlobForUsername); CertFlow(certBlobForUsername); }
/// <summary> /// Reverse marshal a CERT_CREDENTIAL_INFO struct, and locate the original certificate /// </summary> /// <param name="data">A string of the encoded CERT_CREDENTIAL_INFO struct</param> static void ReverseMarshal(string data) { IntPtr credData = IntPtr.Zero; IntPtr credInfo = IntPtr.Zero; NativeMethods.CRED_MARSHAL_TYPE credType = 0; X509Store userMyStore = null; try { credData = Marshal.StringToHGlobalUni(data); bool success = NativeMethods.CredUnmarshalCredential(credData, out credType, out credInfo); if (success) { NativeMethods.CERT_CREDENTIAL_INFO certStruct = (NativeMethods.CERT_CREDENTIAL_INFO)(Marshal.PtrToStructure(credInfo, typeof(NativeMethods.CERT_CREDENTIAL_INFO))); byte[] data2 = certStruct.rgbHashOfCert; string hex = BitConverter.ToString(data2).Replace("-", string.Empty); X509Certificate2 certCredential = new X509Certificate2(); userMyStore = new X509Store(StoreName.My, StoreLocation.CurrentUser); userMyStore.Open(OpenFlags.ReadOnly); X509Certificate2Collection certsReturned = userMyStore.Certificates.Find(X509FindType.FindByThumbprint, hex, false); if (certsReturned.Count == 0) { Console.WriteLine("Could not find the cert you want, aborting"); return; } certCredential = certsReturned[0]; Console.WriteLine("Located certificate"); Console.WriteLine("Subject: " + certCredential.Subject); Console.WriteLine("SubjectName: " + certCredential.SubjectName); foreach (X509Extension extension in certCredential.Extensions) { Console.WriteLine(extension.Oid.FriendlyName + "(" + extension.Oid.Value + ")"); AsnEncodedData asndata = new AsnEncodedData(extension.Oid, extension.RawData); Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("Extension type: {0}", extension.Oid.FriendlyName); Console.WriteLine("Oid value: {0}", asndata.Oid.Value); Console.WriteLine("Raw data length: {0} {1}", asndata.RawData.Length, Environment.NewLine); Console.ResetColor(); Console.WriteLine(asndata.Format(true)); Console.WriteLine(Environment.NewLine); } } } catch (Exception e) { Console.WriteLine("An error occured: " + e.Message + e.StackTrace); } finally { Marshal.FreeHGlobal(credData); Marshal.FreeHGlobal(credInfo); if (userMyStore != null) { userMyStore.Close(); } } }