From 4bd6bbd882097e9ccd9cdcc2290b1458acc3dbe6 Mon Sep 17 00:00:00 2001 From: Tal Aloni Date: Thu, 19 Jan 2017 00:44:50 +0200 Subject: [PATCH] NTAuthentication: Will use ComputeNTLMv2Proof (instead of ComputeNTLMv2Response) to improve compatibility with clients Xubuntu 16.04 will not add the necessary padding to ClientChallengeStructure --- SMBLibrary/Authentication/NTAuthentication.cs | 11 +++++------ SMBLibrary/Server/IndependentUserCollection.cs | 8 ++++---- SMBLibrary/Tests/AuthenticationTests.cs | 12 ++++++------ SMBLibrary/Win32/Win32UserCollection.cs | 8 ++++---- 4 files changed, 19 insertions(+), 20 deletions(-) diff --git a/SMBLibrary/Authentication/NTAuthentication.cs b/SMBLibrary/Authentication/NTAuthentication.cs index 50d5441..978c1d5 100644 --- a/SMBLibrary/Authentication/NTAuthentication.cs +++ b/SMBLibrary/Authentication/NTAuthentication.cs @@ -1,4 +1,4 @@ -/* Copyright (C) 2014 Tal Aloni . All rights reserved. +/* Copyright (C) 2014-2017 Tal Aloni . All rights reserved. * * You can redistribute this program and/or modify it under the terms of * the GNU Lesser Public License as published by the Free Software Foundation, @@ -48,18 +48,17 @@ namespace SMBLibrary.Authentication } /// - /// [MS-NLMP] page 60 - /// 'temp' is the same as ClientChallengeStructure with 4 zero bytes padding + /// [MS-NLMP] https://msdn.microsoft.com/en-us/library/cc236700.aspx /// - public static byte[] ComputeNTLMv2Response(byte[] serverChallenge, byte[] clientChallengeStructurePadded, string password, string user, string domain) + /// ClientChallengeStructure with 4 zero bytes padding, a.k.a. temp + public static byte[] ComputeNTLMv2Proof(byte[] serverChallenge, byte[] clientChallengeStructurePadded, string password, string user, string domain) { byte[] key = NTOWFv2(password, user, domain); byte[] temp = clientChallengeStructurePadded; HMACMD5 hmac = new HMACMD5(key); byte[] _NTProof = hmac.ComputeHash(ByteUtils.Concatenate(serverChallenge, temp), 0, serverChallenge.Length + temp.Length); - - return ByteUtils.Concatenate(_NTProof, temp); + return _NTProof; } /// diff --git a/SMBLibrary/Server/IndependentUserCollection.cs b/SMBLibrary/Server/IndependentUserCollection.cs index 48ffdba..ed5b9e7 100644 --- a/SMBLibrary/Server/IndependentUserCollection.cs +++ b/SMBLibrary/Server/IndependentUserCollection.cs @@ -98,11 +98,11 @@ namespace SMBLibrary.Server if (ntlmResponse.Length > 24) { - NTLMv2ClientChallengeStructure clientChallengeStructure = new NTLMv2ClientChallengeStructure(ntlmResponse, 16); - byte[] clientChallengeStructurePadded = clientChallengeStructure.GetBytesPadded(); - byte[] expectedNTLMv2Response = NTAuthentication.ComputeNTLMv2Response(serverChallenge, clientChallengeStructurePadded, password, accountName, domainNameToAuth); + byte[] clientNTProof = ByteReader.ReadBytes(ntlmResponse, 0, 16); + byte[] clientChallengeStructurePadded = ByteReader.ReadBytes(ntlmResponse, 16, ntlmResponse.Length - 16); + byte[] expectedNTProof = NTAuthentication.ComputeNTLMv2Proof(serverChallenge, clientChallengeStructurePadded, password, accountName, domainNameToAuth); - if (ByteUtils.AreByteArraysEqual(expectedNTLMv2Response, ntlmResponse)) + if (ByteUtils.AreByteArraysEqual(clientNTProof, expectedNTProof)) { return this[index]; } diff --git a/SMBLibrary/Tests/AuthenticationTests.cs b/SMBLibrary/Tests/AuthenticationTests.cs index fa3657f..7999f68 100644 --- a/SMBLibrary/Tests/AuthenticationTests.cs +++ b/SMBLibrary/Tests/AuthenticationTests.cs @@ -1,4 +1,4 @@ -/* Copyright (C) 2014 Tal Aloni . All rights reserved. +/* Copyright (C) 2014-2017 Tal Aloni . All rights reserved. * * You can redistribute this program and/or modify it under the terms of * the GNU Lesser Public License as published by the Free Software Foundation, @@ -76,11 +76,10 @@ namespace SMBLibrary DateTime time = DateTime.FromFileTimeUtc(0); // same as new byte[8] NTLMv2ClientChallengeStructure clientChallengeStructure = new NTLMv2ClientChallengeStructure(time, clientChallenge, "Domain", "Server"); byte[] clientChallengeStructurePadded = clientChallengeStructure.GetBytesPadded(); - byte[] response = NTAuthentication.ComputeNTLMv2Response(serverChallenge, clientChallengeStructurePadded, "Password", "User", "Domain"); + byte[] clientNTProof = NTAuthentication.ComputeNTLMv2Proof(serverChallenge, clientChallengeStructurePadded, "Password", "User", "Domain"); - byte[] expectedHash = new byte[] { 0x68, 0xcd, 0x0a, 0xb8, 0x51, 0xe5, 0x1c, 0x96, 0xaa, 0xbc, 0x92, 0x7b, 0xeb, 0xef, 0x6a, 0x1c }; - byte[] expected = ByteUtils.Concatenate(expectedHash, clientChallengeStructurePadded); - bool success = ByteUtils.AreByteArraysEqual(response, expected); + byte[] expectedNTProof = new byte[] { 0x68, 0xcd, 0x0a, 0xb8, 0x51, 0xe5, 0x1c, 0x96, 0xaa, 0xbc, 0x92, 0x7b, 0xeb, 0xef, 0x6a, 0x1c }; + bool success = ByteUtils.AreByteArraysEqual(clientNTProof, expectedNTProof); return success; } @@ -135,6 +134,7 @@ namespace SMBLibrary DateTime time = DateTime.FromFileTimeUtc(0); // same as new byte[8] NTLMv2ClientChallengeStructure clientChallengeStructure = new NTLMv2ClientChallengeStructure(time, clientChallenge, "Domain", "Server"); byte[] clientChallengeStructurePadded = clientChallengeStructure.GetBytesPadded(); + byte[] clientNTProof = NTAuthentication.ComputeNTLMv2Proof(serverChallenge, clientChallengeStructurePadded, "Password", "User", "Domain"); AuthenticateMessage message = new AuthenticateMessage(); message.EncryptedRandomSessionKey = sessionKey; @@ -144,7 +144,7 @@ namespace SMBLibrary message.WorkStation = "COMPUTER"; message.UserName = "User"; message.LmChallengeResponse = NTAuthentication.ComputeLMv2Response(serverChallenge, clientChallenge, "Password", "User", "Domain"); - message.NtChallengeResponse = NTAuthentication.ComputeNTLMv2Response(serverChallenge, clientChallengeStructurePadded, "Password", "User", "Domain"); + message.NtChallengeResponse = ByteUtils.Concatenate(clientNTProof, clientChallengeStructurePadded); byte[] messageBytes = message.GetBytes(); // The payload entries may be distributed differently so we use cmp.GetBytes() diff --git a/SMBLibrary/Win32/Win32UserCollection.cs b/SMBLibrary/Win32/Win32UserCollection.cs index 66e32a0..28e4531 100644 --- a/SMBLibrary/Win32/Win32UserCollection.cs +++ b/SMBLibrary/Win32/Win32UserCollection.cs @@ -100,10 +100,10 @@ namespace SMBLibrary.Server.Win32 if (message.NtChallengeResponse.Length > 24) { - NTLMv2ClientChallengeStructure clientChallengeStructure = new NTLMv2ClientChallengeStructure(message.NtChallengeResponse, 16); - byte[] clientChallengeStructurePadded = clientChallengeStructure.GetBytesPadded(); - byte[] emptyPasswordNTLMv2Response = NTAuthentication.ComputeNTLMv2Response(m_serverChallenge, clientChallengeStructurePadded, String.Empty, message.UserName, message.DomainName); - if (ByteUtils.AreByteArraysEqual(emptyPasswordNTLMv2Response, 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; }