static byte[] ComputeNtlmV2(Type2Message type2, string username, string password, string domain) { var ntlm_hash = ComputeNtlmPassword(password); var ubytes = Encoding.Unicode.GetBytes(username.ToUpperInvariant()); var tbytes = Encoding.Unicode.GetBytes(domain); var bytes = new byte[ubytes.Length + tbytes.Length]; ubytes.CopyTo(bytes, 0); Array.Copy(tbytes, 0, bytes, ubytes.Length, tbytes.Length); byte[] ntlm_v2_hash; using (var md5 = new HMACMD5(ntlm_hash)) ntlm_v2_hash = md5.ComputeHash(bytes); Array.Clear(ntlm_hash, 0, ntlm_hash.Length); using (var md5 = new HMACMD5(ntlm_v2_hash)) { var timestamp = DateTime.Now.Ticks - 504911232000000000; var nonce = new byte[8]; using (var rng = RandomNumberGenerator.Create()) rng.GetBytes(nonce); var targetInfo = type2.EncodedTargetInfo; var blob = new byte[28 + targetInfo.Length]; blob[0] = 0x01; blob[1] = 0x01; Buffer.BlockCopy(BitConverterLE.GetBytes(timestamp), 0, blob, 8, 8); Buffer.BlockCopy(nonce, 0, blob, 16, 8); Buffer.BlockCopy(targetInfo, 0, blob, 28, targetInfo.Length); var challenge = type2.Nonce; var hashInput = new byte[challenge.Length + blob.Length]; challenge.CopyTo(hashInput, 0); blob.CopyTo(hashInput, challenge.Length); var blobHash = md5.ComputeHash(hashInput); var response = new byte[blob.Length + blobHash.Length]; blobHash.CopyTo(response, 0); blob.CopyTo(response, blobHash.Length); Array.Clear(ntlm_v2_hash, 0, ntlm_v2_hash.Length); Array.Clear(hashInput, 0, hashInput.Length); Array.Clear(blobHash, 0, blobHash.Length); Array.Clear(nonce, 0, nonce.Length); Array.Clear(blob, 0, blob.Length); return(response); } }
public Type3Message(Type2Message type2, Version osVersion, NtlmAuthLevel level, string userName, string password, string host, NtlmFixes fixes = NtlmFixes.None) : base(3) { this.type2 = type2; this.fixes = fixes; challenge = type2.Nonce; Domain = type2.TargetName; OSVersion = osVersion; Username = userName; Password = password; Level = level; Host = host; Flags = 0; if (osVersion != null) { Flags |= NtlmFlags.NegotiateVersion; } if ((type2.Flags & NtlmFlags.NegotiateUnicode) != 0) { Flags |= NtlmFlags.NegotiateUnicode; } else { Flags |= NtlmFlags.NegotiateOem; } if ((type2.Flags & NtlmFlags.NegotiateNtlm) != 0) { Flags |= NtlmFlags.NegotiateNtlm; } if ((type2.Flags & NtlmFlags.NegotiateNtlm2Key) != 0) { Flags |= NtlmFlags.NegotiateNtlm2Key; } if ((type2.Flags & NtlmFlags.NegotiateTargetInfo) != 0) { Flags |= NtlmFlags.NegotiateTargetInfo; } if ((type2.Flags & NtlmFlags.RequestTarget) != 0) { Flags |= NtlmFlags.RequestTarget; } }
public static void Compute(Type2Message type2, NtlmAuthLevel level, string username, string password, string domain, out byte[] lm, out byte[] ntlm) { lm = null; switch (level) { case NtlmAuthLevel.LM_and_NTLM: lm = ComputeLM(password, type2.Nonce); ntlm = ComputeNtlm(password, type2.Nonce); break; case NtlmAuthLevel.LM_and_NTLM_and_try_NTLMv2_Session: if ((type2.Flags & NtlmFlags.NegotiateNtlm2Key) == 0) { goto case NtlmAuthLevel.LM_and_NTLM; } ComputeNtlmV2Session(password, type2.Nonce, out lm, out ntlm); break; case NtlmAuthLevel.NTLM_only: if ((type2.Flags & NtlmFlags.NegotiateNtlm2Key) != 0) { ComputeNtlmV2Session(password, type2.Nonce, out lm, out ntlm); } else { ntlm = ComputeNtlm(password, type2.Nonce); } break; case NtlmAuthLevel.NTLMv2_only: ntlm = ComputeNtlmV2(type2, username, password, domain); if (type2.TargetInfo.Timestamp != 0) { lm = new byte[24]; } break; default: throw new InvalidOperationException(); } }
public Type3Message (Type2Message type2, string userName, string hostName) : base (3) { this.type2 = type2; Level = NtlmSettings.DefaultAuthLevel; challenge = (byte[]) type2.Nonce.Clone (); domain = type2.TargetName; Username = userName; host = hostName; Flags = (NtlmFlags) 0x8200; if ((type2.Flags & NtlmFlags.NegotiateUnicode) != 0) Flags |= NtlmFlags.NegotiateUnicode; else Flags |= NtlmFlags.NegotiateOem; if ((type2.Flags & NtlmFlags.NegotiateNtlm2Key) != 0) Flags |= NtlmFlags.NegotiateNtlm2Key; }
public Type3Message(Type2Message type2, NtlmAuthLevel level, string userName, string password, string host) : base(3) { this.type2 = type2; challenge = type2.Nonce; Domain = type2.TargetName; Username = userName; Password = password; Level = level; Host = host; Flags = 0; if ((type2.Flags & NtlmFlags.NegotiateUnicode) != 0) { Flags |= NtlmFlags.NegotiateUnicode; } else { Flags |= NtlmFlags.NegotiateOem; } if ((type2.Flags & NtlmFlags.NegotiateNtlm) != 0) { Flags |= NtlmFlags.NegotiateNtlm; } if ((type2.Flags & NtlmFlags.NegotiateNtlm2Key) != 0) { Flags |= NtlmFlags.NegotiateNtlm2Key; } if ((type2.Flags & NtlmFlags.NegotiateVersion) != 0) { Flags |= NtlmFlags.NegotiateVersion; } }
public Type3Message(byte[] message, int startIndex, int length) : base(3) { Decode(message, startIndex, length); type2 = null; }
public Type3Message (byte[] message, int startIndex, int length) : base (3) { Decode (message, startIndex, length); type2 = null; }
public void TestNtlmType2MessageDecode () { const string expectedTargetInfo = "02000c0044004f004d00410049004e0001000c005300450052005600450052000400140064006f006d00610069006e002e0063006f006d00030022007300650072007600650072002e0064006f006d00610069006e002e0063006f006d0000000000"; var flags = NtlmFlags.NegotiateUnicode | NtlmFlags.NegotiateNtlm | NtlmFlags.TargetTypeDomain | NtlmFlags.NegotiateTargetInfo; var type2 = new Type2Message (NtlmType2EncodedMessage, 0, NtlmType2EncodedMessage.Length); Assert.AreEqual (flags, type2.Flags, "The expected flags do not match."); Assert.AreEqual ("DOMAIN", type2.TargetName, "The expected TargetName does not match."); var nonce = HexEncode (type2.Nonce); Assert.AreEqual ("0123456789abcdef", nonce, "The expected nonce does not match."); var targetInfo = HexEncode (type2.EncodedTargetInfo); Assert.AreEqual (expectedTargetInfo, targetInfo, "The expected TargetInfo does not match."); Assert.AreEqual ("DOMAIN", type2.TargetInfo.DomainName, "The expected TargetInfo domain name does not match."); Assert.AreEqual ("SERVER", type2.TargetInfo.ServerName, "The expected TargetInfo server name does not match."); Assert.AreEqual ("domain.com", type2.TargetInfo.DnsDomainName, "The expected TargetInfo DNS domain name does not match."); Assert.AreEqual ("server.domain.com", type2.TargetInfo.DnsServerName, "The expected TargetInfo DNS server name does not match."); targetInfo = HexEncode (type2.TargetInfo.Encode (true)); Assert.AreEqual (expectedTargetInfo, targetInfo, "The expected re-encoded TargetInfo does not match."); }
static MessageBase GetChallengeResponse (string userName, string password, string domain, byte[] token, int startIndex, int length) { var type2 = new Type2Message (token, startIndex, length); var type3 = new Type3Message (type2, userName, string.Empty); type3.Password = password; type3.Domain = domain; return type3; }
public static void Compute (Type2Message type2, NtlmAuthLevel level, string username, string password, string domain, out byte[] lm, out byte[] ntlm) { lm = null; switch (level) { case NtlmAuthLevel.LM_and_NTLM: lm = ComputeLM (password, type2.Nonce); ntlm = ComputeNtlm (password, type2.Nonce); break; case NtlmAuthLevel.LM_and_NTLM_and_try_NTLMv2_Session: if ((type2.Flags & NtlmFlags.NegotiateNtlm2Key) == 0) goto case NtlmAuthLevel.LM_and_NTLM; ComputeNtlmV2Session (password, type2.Nonce, out lm, out ntlm); break; case NtlmAuthLevel.NTLM_only: if ((type2.Flags & NtlmFlags.NegotiateNtlm2Key) != 0) ComputeNtlmV2Session (password, type2.Nonce, out lm, out ntlm); else ntlm = ComputeNtlm (password, type2.Nonce); break; case NtlmAuthLevel.NTLMv2_only: ntlm = ComputeNtlmV2 (type2, username, password, domain); break; default: throw new InvalidOperationException (); } }
static byte[] ComputeNtlmV2 (Type2Message type2, string username, string password, string domain) { var ntlm_hash = ComputeNtlmPassword (password); var ubytes = Encoding.Unicode.GetBytes (username.ToUpperInvariant ()); var tbytes = Encoding.Unicode.GetBytes (domain); var bytes = new byte[ubytes.Length + tbytes.Length]; ubytes.CopyTo (bytes, 0); Array.Copy (tbytes, 0, bytes, ubytes.Length, tbytes.Length); byte[] ntlm_v2_hash; using (var md5 = new HMACMD5 (ntlm_hash)) ntlm_v2_hash = md5.ComputeHash (bytes); Array.Clear (ntlm_hash, 0, ntlm_hash.Length); using (var md5 = new HMACMD5 (ntlm_v2_hash)) { var now = DateTime.Now; var timestamp = now.Ticks - 504911232000000000; var nonce = new byte[8]; using (var rng = RandomNumberGenerator.Create ()) rng.GetBytes (nonce); var targetInfo = type2.EncodedTargetInfo; var blob = new byte[28 + targetInfo.Length]; blob[0] = 0x01; blob[1] = 0x01; Buffer.BlockCopy (BitConverterLE.GetBytes (timestamp), 0, blob, 8, 8); Buffer.BlockCopy (nonce, 0, blob, 16, 8); Buffer.BlockCopy (targetInfo, 0, blob, 28, targetInfo.Length); var challenge = type2.Nonce; var hashInput = new byte[challenge.Length + blob.Length]; challenge.CopyTo (hashInput, 0); blob.CopyTo (hashInput, challenge.Length); var blobHash = md5.ComputeHash (hashInput); var response = new byte[blob.Length + blobHash.Length]; blobHash.CopyTo (response, 0); blob.CopyTo (response, blobHash.Length); Array.Clear (ntlm_v2_hash, 0, ntlm_v2_hash.Length); Array.Clear (hashInput, 0, hashInput.Length); Array.Clear (blobHash, 0, blobHash.Length); Array.Clear (nonce, 0, nonce.Length); Array.Clear (blob, 0, blob.Length); return response; } }