public static string KerberosPasswordHash(Interop.KERB_ETYPE etype, string password, string salt = "", int count = 4096) { // use the internal KERB_ECRYPT HashPassword() function to calculate a password hash of a given etype // adapted from @gentilkiwi's Mimikatz "kerberos::hash" implementation Interop.KERB_ECRYPT pCSystem; IntPtr pCSystemPtr; // locate the crypto system for the hash type we want int status = Interop.CDLocateCSystem(etype, out pCSystemPtr); pCSystem = (Interop.KERB_ECRYPT)System.Runtime.InteropServices.Marshal.PtrToStructure(pCSystemPtr, typeof(Interop.KERB_ECRYPT)); if (status != 0) { throw new System.ComponentModel.Win32Exception(status, "Error on CDLocateCSystem"); } // get the delegate for the password hash function Interop.KERB_ECRYPT_HashPassword pCSystemHashPassword = (Interop.KERB_ECRYPT_HashPassword)System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(pCSystem.HashPassword, typeof(Interop.KERB_ECRYPT_HashPassword)); Interop.UNICODE_STRING passwordUnicode = new Interop.UNICODE_STRING(password); Interop.UNICODE_STRING saltUnicode = new Interop.UNICODE_STRING(salt); byte[] output = new byte[pCSystem.KeySize]; int success = pCSystemHashPassword(passwordUnicode, saltUnicode, count, output); if (status != 0) { throw new Win32Exception(status); } return(System.BitConverter.ToString(output).Replace("-", "")); }
internal static void AppendUnicodeString <T>(IntPtr nativeBuffer, Interop.UNICODE_STRING data, string fieldName) { Type targetType = typeof(T); // Set pointer to end of T structure IntPtr nativeDataBuffer = (IntPtr)(nativeBuffer.ToInt64() + Marshal.SizeOf(targetType)); // Copy unicode chars to the new location Interop.CopyMemory(nativeDataBuffer, data.Buffer, data.MaximumLength); // Update the target name buffer ptr Marshal.WriteIntPtr(nativeBuffer, Marshal.OffsetOf(targetType, fieldName).ToInt32() + Marshal.OffsetOf(typeof(Interop.UNICODE_STRING), "Buffer").ToInt32(), nativeDataBuffer); }