diff --git a/SMBLibrary/Authentication/AuthenticateMessage/AuthenticationMessageUtils.cs b/SMBLibrary/Authentication/AuthenticateMessage/AuthenticationMessageUtils.cs
index 1b463f1..1c83103 100644
--- a/SMBLibrary/Authentication/AuthenticateMessage/AuthenticationMessageUtils.cs
+++ b/SMBLibrary/Authentication/AuthenticateMessage/AuthenticationMessageUtils.cs
@@ -58,6 +58,36 @@ namespace SMBLibrary.Authentication
return (signature == AuthenticateMessage.ValidSignature);
}
+ ///
+ /// If NTLM v1 Extended Security is used, LMResponse starts with 8-byte challenge, followed by 16 bytes of padding (set to zero).
+ ///
+ ///
+ /// LMResponse is 24 bytes for NTLM v1, NTLM v1 Extended Security and NTLM v2.
+ ///
+ public static bool IsNTLMv1ExtendedSecurity(byte[] lmResponse)
+ {
+ if (lmResponse.Length == 24)
+ {
+ if (ByteUtils.AreByteArraysEqual(ByteReader.ReadBytes(lmResponse, 0, 8), new byte[8]))
+ {
+ // Challenge not present, cannot be NTLM v1 Extended Security
+ return false;
+ }
+ return ByteUtils.AreByteArraysEqual(ByteReader.ReadBytes(lmResponse, 8, 16), new byte[16]);
+ }
+ return false;
+ }
+
+ ///
+ /// NTLM v1 / NTLM v1 Extended Security NTResponse is 24 bytes.
+ ///
+ public static bool IsNTLMv2NTResponse(byte[] ntResponse)
+ {
+ return (ntResponse.Length >= 48 &&
+ ntResponse[16] == NTLMv2ClientChallenge.StructureVersion &&
+ ntResponse[17] == NTLMv2ClientChallenge.StructureVersion);
+ }
+
public static MessageTypeName GetMessageType(byte[] messageBytes)
{
return (MessageTypeName)LittleEndianConverter.ToUInt32(messageBytes, 8);
diff --git a/SMBLibrary/Server/IndependentUserCollection.cs b/SMBLibrary/Server/IndependentUserCollection.cs
index 89202a0..cd3b153 100644
--- a/SMBLibrary/Server/IndependentUserCollection.cs
+++ b/SMBLibrary/Server/IndependentUserCollection.cs
@@ -96,7 +96,7 @@ namespace SMBLibrary.Server
return this[index];
}
- if (ntResponse.Length >= 48)
+ if (AuthenticationMessageUtils.IsNTLMv2NTResponse(ntResponse))
{
byte[] clientNTProof = ByteReader.ReadBytes(ntResponse, 0, 16);
byte[] clientChallengeStructurePadded = ByteReader.ReadBytes(ntResponse, 16, ntResponse.Length - 16);
@@ -161,8 +161,12 @@ namespace SMBLibrary.Server
User user;
if ((message.NegotiateFlags & NegotiateFlags.ExtendedSecurity) > 0)
{
- user = AuthenticateV1Extended(message.UserName, m_serverChallenge, message.LmChallengeResponse, message.NtChallengeResponse);
- if (user == null)
+ if (AuthenticationMessageUtils.IsNTLMv1ExtendedSecurity(message.LmChallengeResponse))
+ {
+ // NTLM v1 Extended Security:
+ user = AuthenticateV1Extended(message.UserName, m_serverChallenge, message.LmChallengeResponse, message.NtChallengeResponse);
+ }
+ else
{
// NTLM v2:
user = AuthenticateV2(message.DomainName, message.UserName, m_serverChallenge, message.LmChallengeResponse, message.NtChallengeResponse);
diff --git a/SMBLibrary/Server/SMB1/SessionSetupHelper.cs b/SMBLibrary/Server/SMB1/SessionSetupHelper.cs
index bd808d0..47eebf1 100644
--- a/SMBLibrary/Server/SMB1/SessionSetupHelper.cs
+++ b/SMBLibrary/Server/SMB1/SessionSetupHelper.cs
@@ -183,7 +183,8 @@ namespace SMBLibrary.Server.SMB1
NegotiateFlags.Version |
NegotiateFlags.Use128BitEncryption |
NegotiateFlags.Use56BitEncryption;
- if (ntChallengeResponse.Length >= 48)
+ if (AuthenticationMessageUtils.IsNTLMv1ExtendedSecurity(lmChallengeResponse) ||
+ AuthenticationMessageUtils.IsNTLMv2NTResponse(ntChallengeResponse))
{
authenticateMessage.NegotiateFlags |= NegotiateFlags.ExtendedSecurity;
}
diff --git a/SMBLibrary/Win32/Win32UserCollection.cs b/SMBLibrary/Win32/Win32UserCollection.cs
index 8a8f6b0..3f122d5 100644
--- a/SMBLibrary/Win32/Win32UserCollection.cs
+++ b/SMBLibrary/Win32/Win32UserCollection.cs
@@ -82,32 +82,37 @@ namespace SMBLibrary.Server.Win32
if ((message.NegotiateFlags & NegotiateFlags.ExtendedSecurity) > 0)
{
- // NTLM v1 extended security:
- byte[] clientChallenge = ByteReader.ReadBytes(message.LmChallengeResponse, 0, 8);
- byte[] emptyPasswordNTLMv1Response = NTAuthentication.ComputeNTLMv1ExtendedSecurityResponse(m_serverChallenge, clientChallenge, String.Empty);
- if (ByteUtils.AreByteArraysEqual(emptyPasswordNTLMv1Response, message.NtChallengeResponse))
+ if (AuthenticationMessageUtils.IsNTLMv1ExtendedSecurity(message.LmChallengeResponse))
{
- return true;
- }
-
- // NTLM v2:
- byte[] _LMv2ClientChallenge = ByteReader.ReadBytes(message.LmChallengeResponse, 16, 8);
- byte[] emptyPasswordLMv2Response = NTAuthentication.ComputeLMv2Response(m_serverChallenge, _LMv2ClientChallenge, String.Empty, message.UserName, message.DomainName);
- if (ByteUtils.AreByteArraysEqual(emptyPasswordLMv2Response, message.LmChallengeResponse))
- {
- return true;
- }
-
- if (message.NtChallengeResponse.Length >= 48)
- {
- byte[] clientNTProof = ByteReader.ReadBytes(message.NtChallengeResponse, 0, 16);
- byte[] clientChallengeStructurePadded = ByteReader.ReadBytes(message.NtChallengeResponse, 16, message.NtChallengeResponse.Length - 16);
- byte[] emptyPasswordNTProof = NTAuthentication.ComputeNTLMv2Proof(m_serverChallenge, clientChallengeStructurePadded, String.Empty, message.UserName, message.DomainName);
- if (ByteUtils.AreByteArraysEqual(clientNTProof, emptyPasswordNTProof))
+ // NTLM v1 extended security:
+ byte[] clientChallenge = ByteReader.ReadBytes(message.LmChallengeResponse, 0, 8);
+ byte[] emptyPasswordNTLMv1Response = NTAuthentication.ComputeNTLMv1ExtendedSecurityResponse(m_serverChallenge, clientChallenge, String.Empty);
+ if (ByteUtils.AreByteArraysEqual(emptyPasswordNTLMv1Response, message.NtChallengeResponse))
{
return true;
}
}
+ else
+ {
+ // NTLM v2:
+ byte[] _LMv2ClientChallenge = ByteReader.ReadBytes(message.LmChallengeResponse, 16, 8);
+ byte[] emptyPasswordLMv2Response = NTAuthentication.ComputeLMv2Response(m_serverChallenge, _LMv2ClientChallenge, String.Empty, message.UserName, message.DomainName);
+ if (ByteUtils.AreByteArraysEqual(emptyPasswordLMv2Response, message.LmChallengeResponse))
+ {
+ return true;
+ }
+
+ if (AuthenticationMessageUtils.IsNTLMv2NTResponse(message.NtChallengeResponse))
+ {
+ byte[] clientNTProof = ByteReader.ReadBytes(message.NtChallengeResponse, 0, 16);
+ byte[] clientChallengeStructurePadded = ByteReader.ReadBytes(message.NtChallengeResponse, 16, message.NtChallengeResponse.Length - 16);
+ byte[] emptyPasswordNTProof = NTAuthentication.ComputeNTLMv2Proof(m_serverChallenge, clientChallengeStructurePadded, String.Empty, message.UserName, message.DomainName);
+ if (ByteUtils.AreByteArraysEqual(clientNTProof, emptyPasswordNTProof))
+ {
+ return true;
+ }
+ }
+ }
}
else
{