diff --git a/SMBLibrary.Tests/Components/Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll b/SMBLibrary.Tests/Components/Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll
new file mode 100644
index 0000000..387ad78
Binary files /dev/null and b/SMBLibrary.Tests/Components/Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll differ
diff --git a/SMBLibrary.Tests/NTLM/NTLMAuthenticationTests.cs b/SMBLibrary.Tests/NTLM/NTLMAuthenticationTests.cs
new file mode 100644
index 0000000..224da07
--- /dev/null
+++ b/SMBLibrary.Tests/NTLM/NTLMAuthenticationTests.cs
@@ -0,0 +1,168 @@
+/* Copyright (C) 2014-2019 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,
+ * either version 3 of the License, or (at your option) any later version.
+ */
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using SMBLibrary.Authentication.NTLM;
+using Utilities;
+
+namespace SMBLibrary.Tests
+{
+ ///
+ /// [MS-NLMP] Tests
+ ///
+ [TestClass]
+ public class NTLMAuthenticationTests
+ {
+ [TestMethod]
+ public void LMv1HashTest()
+ {
+ byte[] hash = NTLMCryptography.LMOWFv1("Password");
+ byte[] expected = new byte[] { 0xe5, 0x2c, 0xac, 0x67, 0x41, 0x9a, 0x9a, 0x22, 0x4a, 0x3b, 0x10, 0x8f, 0x3f, 0xa6, 0xcb, 0x6d };
+ Assert.IsTrue(ByteUtils.AreByteArraysEqual(hash, expected));
+ }
+
+ [TestMethod]
+ public void NTv1HashTest()
+ {
+ byte[] hash = NTLMCryptography.NTOWFv1("Password");
+ byte[] expected = new byte[] { 0xa4, 0xf4, 0x9c, 0x40, 0x65, 0x10, 0xbd, 0xca, 0xb6, 0x82, 0x4e, 0xe7, 0xc3, 0x0f, 0xd8, 0x52 };
+ Assert.IsTrue(ByteUtils.AreByteArraysEqual(hash, expected));
+ }
+
+ [TestMethod]
+ public void NTv2HashTest()
+ {
+ byte[] hash = NTLMCryptography.NTOWFv2("Password", "User", "Domain");
+ byte[] expected = new byte[] { 0x0c, 0x86, 0x8a, 0x40, 0x3b, 0xfd, 0x7a, 0x93, 0xa3, 0x00, 0x1e, 0xf2, 0x2e, 0xf0, 0x2e, 0x3f };
+ Assert.IsTrue(ByteUtils.AreByteArraysEqual(hash, expected));
+ }
+
+ [TestMethod]
+ public void LMv1ResponseTest()
+ {
+ byte[] challenge = new byte[] { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef };
+ byte[] response = NTLMCryptography.ComputeLMv1Response(challenge, "Password");
+ byte[] expected = { 0x98, 0xde, 0xf7, 0xb8, 0x7f, 0x88, 0xaa, 0x5d, 0xaf, 0xe2, 0xdf, 0x77, 0x96, 0x88, 0xa1, 0x72, 0xde, 0xf1, 0x1c, 0x7d, 0x5c, 0xcd, 0xef, 0x13 };
+ Assert.IsTrue(ByteUtils.AreByteArraysEqual(response, expected));
+ }
+
+ [TestMethod]
+ public void NTLMv1ResponseTest()
+ {
+ byte[] challenge = new byte[] { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef };
+ byte[] response = NTLMCryptography.ComputeNTLMv1Response(challenge, "Password");
+ byte[] expected = { 0x67, 0xc4, 0x30, 0x11, 0xf3, 0x02, 0x98, 0xa2, 0xad, 0x35, 0xec, 0xe6, 0x4f, 0x16, 0x33, 0x1c, 0x44, 0xbd, 0xbe, 0xd9, 0x27, 0x84, 0x1f, 0x94};
+ Assert.IsTrue(ByteUtils.AreByteArraysEqual(response, expected));
+ }
+
+ [TestMethod]
+ public void LMv2ResponseTest()
+ {
+ byte[] serverChallenge = new byte[] { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef };
+ byte[] clientChallenge = new byte[] { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa };
+ byte[] response = NTLMCryptography.ComputeLMv2Response(serverChallenge, clientChallenge, "Password", "User", "Domain");
+ byte[] expected = new byte[] { 0x86, 0xc3, 0x50, 0x97, 0xac, 0x9c, 0xec, 0x10, 0x25, 0x54, 0x76, 0x4a, 0x57, 0xcc, 0xcc, 0x19, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa};
+ Assert.IsTrue(ByteUtils.AreByteArraysEqual(response, expected));
+ }
+
+ [TestMethod]
+ public void NTLMv2ResponseTest()
+ {
+ byte[] serverChallenge = new byte[] { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef };
+ byte[] clientChallenge = new byte[] { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa };
+ DateTime time = DateTime.FromFileTimeUtc(0); // same as new byte[8]
+ NTLMv2ClientChallenge clientChallengeStructure = new NTLMv2ClientChallenge(time, clientChallenge, "Domain", "Server");
+ byte[] clientChallengeStructurePadded = clientChallengeStructure.GetBytesPadded();
+ byte[] clientNTProof = NTLMCryptography.ComputeNTLMv2Proof(serverChallenge, clientChallengeStructurePadded, "Password", "User", "Domain");
+
+ byte[] expectedNTProof = new byte[] { 0x68, 0xcd, 0x0a, 0xb8, 0x51, 0xe5, 0x1c, 0x96, 0xaa, 0xbc, 0x92, 0x7b, 0xeb, 0xef, 0x6a, 0x1c };
+ Assert.IsTrue(ByteUtils.AreByteArraysEqual(clientNTProof, expectedNTProof));
+ }
+
+ [TestMethod]
+ public void NTLMv2ChallengeMessageTest()
+ {
+ byte[] expected = new byte[]{0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00,
+ 0x38, 0x00, 0x00, 0x00, 0x37, 0x82, 0x8a, 0xe2, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x24, 0x00, 0x44, 0x00, 0x00, 0x00,
+ 0x06, 0x00, 0x70, 0x17, 0x00, 0x00, 0x00, 0x0f, 0x53, 0x00, 0x65, 0x00, 0x72, 0x00, 0x76, 0x00,
+ 0x65, 0x00, 0x72, 0x00, 0x02, 0x00, 0x0c, 0x00, 0x44, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x61, 0x00,
+ 0x69, 0x00, 0x6e, 0x00, 0x01, 0x00, 0x0c, 0x00, 0x53, 0x00, 0x65, 0x00, 0x72, 0x00, 0x76, 0x00,
+ 0x65, 0x00, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+ byte[] serverChallenge = new byte[] { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef };
+ ChallengeMessage message = new ChallengeMessage();
+ message.ServerChallenge = serverChallenge;
+ message.Version = new NTLMVersion(6, 0, 6000, NTLMVersion.NTLMSSP_REVISION_W2K3);
+ message.NegotiateFlags = NegotiateFlags.UnicodeEncoding | NegotiateFlags.OEMEncoding | NegotiateFlags.TargetNameSupplied | NegotiateFlags.Sign | NegotiateFlags.Seal | NegotiateFlags.NTLMSessionSecurity | NegotiateFlags.AlwaysSign | NegotiateFlags.TargetTypeServer | NegotiateFlags.ExtendedSessionSecurity | NegotiateFlags.TargetInfo | NegotiateFlags.Version | NegotiateFlags.Use128BitEncryption | NegotiateFlags.KeyExchange | NegotiateFlags.Use56BitEncryption;
+ message.TargetName = "Server";
+ message.TargetInfo = AVPairUtils.GetAVPairSequence("Domain", "Server");
+
+ byte[] messageBytes = message.GetBytes();
+ Assert.IsTrue(ByteUtils.AreByteArraysEqual(expected, messageBytes));
+ }
+
+ [TestMethod]
+ public void NTLMv2AuthenticateMessageTest()
+ {
+ byte[] expected = new byte[] { 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x03, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00,
+ 0x6c, 0x00, 0x00, 0x00, 0x54, 0x00, 0x54, 0x00, 0x84, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00,
+ 0x48, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x54, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00,
+ 0x5c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0xd8, 0x00, 0x00, 0x00, 0x35, 0x82, 0x88, 0xe2,
+ 0x05, 0x01, 0x28, 0x0a, 0x00, 0x00, 0x00, 0x0f, 0x44, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x61, 0x00,
+ 0x69, 0x00, 0x6e, 0x00, 0x55, 0x00, 0x73, 0x00, 0x65, 0x00, 0x72, 0x00, 0x43, 0x00, 0x4f, 0x00,
+ 0x4d, 0x00, 0x50, 0x00, 0x55, 0x00, 0x54, 0x00, 0x45, 0x00, 0x52, 0x00, 0x86, 0xc3, 0x50, 0x97,
+ 0xac, 0x9c, 0xec, 0x10, 0x25, 0x54, 0x76, 0x4a, 0x57, 0xcc, 0xcc, 0x19, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x68, 0xcd, 0x0a, 0xb8, 0x51, 0xe5, 0x1c, 0x96, 0xaa, 0xbc, 0x92, 0x7b,
+ 0xeb, 0xef, 0x6a, 0x1c, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x0c, 0x00, 0x44, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x69, 0x00, 0x6e, 0x00,
+ 0x01, 0x00, 0x0c, 0x00, 0x53, 0x00, 0x65, 0x00, 0x72, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc5, 0xda, 0xd2, 0x54, 0x4f, 0xc9, 0x79, 0x90,
+ 0x94, 0xce, 0x1c, 0xe9, 0x0b, 0xc9, 0xd0, 0x3e};
+
+ AuthenticateMessage cmp = new AuthenticateMessage(expected);
+
+ byte[] sessionKey = {0xc5, 0xda, 0xd2, 0x54, 0x4f, 0xc9, 0x79, 0x90, 0x94, 0xce, 0x1c, 0xe9, 0x0b, 0xc9, 0xd0, 0x3e};
+ byte[] serverChallenge = new byte[] { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef };
+ byte[] clientChallenge = new byte[] { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa };
+ DateTime time = DateTime.FromFileTimeUtc(0); // same as new byte[8]
+ NTLMv2ClientChallenge clientChallengeStructure = new NTLMv2ClientChallenge(time, clientChallenge, "Domain", "Server");
+ byte[] clientChallengeStructurePadded = clientChallengeStructure.GetBytesPadded();
+ byte[] clientNTProof = NTLMCryptography.ComputeNTLMv2Proof(serverChallenge, clientChallengeStructurePadded, "Password", "User", "Domain");
+
+ AuthenticateMessage message = new AuthenticateMessage();
+ message.EncryptedRandomSessionKey = sessionKey;
+ message.Version = new NTLMVersion(5, 1, 2600, NTLMVersion.NTLMSSP_REVISION_W2K3);
+ message.NegotiateFlags = NegotiateFlags.UnicodeEncoding | NegotiateFlags.TargetNameSupplied | NegotiateFlags.Sign | NegotiateFlags.Seal | NegotiateFlags.NTLMSessionSecurity | NegotiateFlags.AlwaysSign | NegotiateFlags.ExtendedSessionSecurity | NegotiateFlags.TargetInfo | NegotiateFlags.Version | NegotiateFlags.Use128BitEncryption | NegotiateFlags.KeyExchange | NegotiateFlags.Use56BitEncryption;
+ message.DomainName = "Domain";
+ message.WorkStation = "COMPUTER";
+ message.UserName = "User";
+ message.LmChallengeResponse = NTLMCryptography.ComputeLMv2Response(serverChallenge, clientChallenge, "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()
+ Assert.IsTrue(ByteUtils.AreByteArraysEqual(messageBytes, cmp.GetBytes()));
+ }
+
+ public void TestAll()
+ {
+ LMv1HashTest();
+ NTv1HashTest();
+ NTv2HashTest();
+ LMv1ResponseTest();
+ NTLMv1ResponseTest();
+ LMv2ResponseTest();
+ NTLMv2ResponseTest();
+ NTLMv2ChallengeMessageTest();
+ NTLMv2AuthenticateMessageTest();
+ }
+ }
+}
diff --git a/SMBLibrary.Tests/NTLM/NTLMSigningTests.cs b/SMBLibrary.Tests/NTLM/NTLMSigningTests.cs
new file mode 100644
index 0000000..50433d0
--- /dev/null
+++ b/SMBLibrary.Tests/NTLM/NTLMSigningTests.cs
@@ -0,0 +1,240 @@
+/* Copyright (C) 2017-2019 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,
+ * either version 3 of the License, or (at your option) any later version.
+ */
+using System;
+using System.Collections.Generic;
+using System.Security.Cryptography;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using SMBLibrary.Authentication.NTLM;
+using Utilities;
+
+namespace SMBLibrary.Tests
+{
+ [TestClass]
+ public class NTLMSigningTests
+ {
+ [TestMethod]
+ public void TestLMMIC()
+ {
+ string password = "Password";
+ byte[] type1 = new byte[] { 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x01, 0x00, 0x00, 0x00, 0x97, 0x82, 0x08, 0xe2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x06, 0x01, 0xb1, 0x1d, 0x00, 0x00, 0x00, 0x0f};
+ byte[] type2 = new byte[] { 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00,
+ 0x38, 0x00, 0x00, 0x00, 0x95, 0x00, 0x82, 0xa2, 0x28, 0x96, 0xe3, 0x6a, 0xd1, 0xb7, 0x74, 0xb8,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0x3e, 0x00, 0x00, 0x00,
+ 0x05, 0x02, 0xce, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x54, 0x00, 0x41, 0x00, 0x4c, 0x00, 0x02, 0x00,
+ 0x06, 0x00, 0x54, 0x00, 0x41, 0x00, 0x4c, 0x00, 0x01, 0x00, 0x06, 0x00, 0x54, 0x00, 0x41, 0x00,
+ 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00};
+ byte[] type3 = new byte[] { 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x03, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00,
+ 0x7c, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0x94, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x0e, 0x00,
+ 0x58, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x66, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x0e, 0x00,
+ 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, 0x95, 0x00, 0x80, 0xa2,
+ 0x06, 0x01, 0xb1, 0x1d, 0x00, 0x00, 0x00, 0x0f, 0x4e, 0x65, 0x54, 0xe6, 0xb3, 0xdc, 0xdc, 0x16,
+ 0xef, 0xc4, 0xd0, 0x03, 0x3b, 0x81, 0x61, 0x6f, 0x54, 0x00, 0x41, 0x00, 0x4c, 0x00, 0x2d, 0x00,
+ 0x56, 0x00, 0x4d, 0x00, 0x37, 0x00, 0x55, 0x00, 0x73, 0x00, 0x65, 0x00, 0x72, 0x00, 0x54, 0x00,
+ 0x41, 0x00, 0x4c, 0x00, 0x2d, 0x00, 0x56, 0x00, 0x4d, 0x00, 0x37, 0x00, 0xc1, 0xd1, 0x06, 0x56,
+ 0xa3, 0xa9, 0x64, 0x14, 0x0e, 0x7f, 0x43, 0x19, 0x3f, 0x29, 0xf3, 0x72, 0xa3, 0xc1, 0xbe, 0x02,
+ 0xd0, 0x6f, 0xff, 0x20, 0xc1, 0xd1, 0x06, 0x56, 0xa3, 0xa9, 0x64, 0x14, 0x0e, 0x7f, 0x43, 0x19,
+ 0x3f, 0x29, 0xf3, 0x72, 0xa3, 0xc1, 0xbe, 0x02, 0xd0, 0x6f, 0xff, 0x20};
+
+ byte[] serverChallenge = new ChallengeMessage(type2).ServerChallenge;
+ AuthenticateMessage authenticateMessage = new AuthenticateMessage(type3);
+ byte[] sessionBaseKey = new MD4().GetByteHashFromBytes(NTLMCryptography.NTOWFv1(password));
+ byte[] lmowf = NTLMCryptography.LMOWFv1(password);
+ byte[] exportedSessionKey = GetExportedSessionKey(sessionBaseKey, authenticateMessage, serverChallenge, lmowf);
+
+ // https://msdn.microsoft.com/en-us/library/cc236695.aspx
+ const int micFieldOffset = 72;
+ ByteWriter.WriteBytes(type3, micFieldOffset, new byte[16]);
+ byte[] temp = ByteUtils.Concatenate(ByteUtils.Concatenate(type1, type2), type3);
+ byte[] mic = new HMACMD5(exportedSessionKey).ComputeHash(temp);
+ byte[] expected = new byte[] { 0x4e, 0x65, 0x54, 0xe6, 0xb3, 0xdc, 0xdc, 0x16, 0xef, 0xc4, 0xd0, 0x03, 0x3b, 0x81, 0x61, 0x6f };
+
+ Assert.IsTrue(ByteUtils.AreByteArraysEqual(mic, expected));
+ }
+
+ [TestMethod]
+ public void TestNTLMv1MIC()
+ {
+ string password = "Password";
+ byte[] type1 = new byte[] { 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x01, 0x00, 0x00, 0x00, 0x97, 0x82, 0x08, 0xe2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x0a, 0x00, 0x39, 0x38, 0x00, 0x00, 0x00, 0x0f};
+ byte[] type2 = new byte[] { 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00,
+ 0x38, 0x00, 0x00, 0x00, 0x15, 0x02, 0x82, 0xa2, 0xe8, 0xbe, 0x2f, 0x5b, 0xc5, 0xe9, 0xf7, 0xa7,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0x3e, 0x00, 0x00, 0x00,
+ 0x05, 0x02, 0xce, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x54, 0x00, 0x41, 0x00, 0x4c, 0x00, 0x02, 0x00,
+ 0x06, 0x00, 0x54, 0x00, 0x41, 0x00, 0x4c, 0x00, 0x01, 0x00, 0x06, 0x00, 0x54, 0x00, 0x41, 0x00,
+ 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00};
+ byte[] type3 = new byte[] { 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x03, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00,
+ 0x7c, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0x94, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x0e, 0x00,
+ 0x58, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x66, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x0e, 0x00,
+ 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, 0x15, 0x02, 0x80, 0xa2,
+ 0x0a, 0x00, 0x39, 0x38, 0x00, 0x00, 0x00, 0x0f, 0xae, 0xa7, 0xba, 0x44, 0x4e, 0x93, 0xa7, 0xdb,
+ 0xb3, 0x0c, 0x85, 0x49, 0xc2, 0x2b, 0xba, 0x9a, 0x54, 0x00, 0x41, 0x00, 0x4c, 0x00, 0x2d, 0x00,
+ 0x56, 0x00, 0x4d, 0x00, 0x36, 0x00, 0x55, 0x00, 0x73, 0x00, 0x65, 0x00, 0x72, 0x00, 0x54, 0x00,
+ 0x41, 0x00, 0x4c, 0x00, 0x2d, 0x00, 0x56, 0x00, 0x4d, 0x00, 0x36, 0x00, 0xa6, 0x71, 0xbd, 0x94,
+ 0x78, 0x4f, 0x05, 0xf1, 0x3f, 0x3a, 0x7b, 0x41, 0xcf, 0x53, 0x2e, 0x36, 0x73, 0xe2, 0x14, 0x53,
+ 0xbd, 0x42, 0x5e, 0x8f, 0xa6, 0x71, 0xbd, 0x94, 0x78, 0x4f, 0x05, 0xf1, 0x3f, 0x3a, 0x7b, 0x41,
+ 0xcf, 0x53, 0x2e, 0x36, 0x73, 0xe2, 0x14, 0x53, 0xbd, 0x42, 0x5e, 0x8f};
+
+ byte[] serverChallenge = new ChallengeMessage(type2).ServerChallenge;
+ AuthenticateMessage authenticateMessage = new AuthenticateMessage(type3);
+ byte[] sessionBaseKey = new MD4().GetByteHashFromBytes(NTLMCryptography.NTOWFv1(password));
+ byte[] lmowf = NTLMCryptography.LMOWFv1(password);
+ byte[] exportedSessionKey = GetExportedSessionKey(sessionBaseKey, authenticateMessage, serverChallenge, lmowf);
+
+ // https://msdn.microsoft.com/en-us/library/cc236695.aspx
+ const int micFieldOffset = 72;
+ ByteWriter.WriteBytes(type3, micFieldOffset, new byte[16]);
+ byte[] temp = ByteUtils.Concatenate(ByteUtils.Concatenate(type1, type2), type3);
+ byte[] mic = new HMACMD5(exportedSessionKey).ComputeHash(temp);
+ byte[] expected = new byte[] { 0xae, 0xa7, 0xba, 0x44, 0x4e, 0x93, 0xa7, 0xdb, 0xb3, 0x0c, 0x85, 0x49, 0xc2, 0x2b, 0xba, 0x9a };
+
+ Assert.IsTrue(ByteUtils.AreByteArraysEqual(mic, expected));
+ }
+
+ [TestMethod]
+ public void TestNTLMv1ExtendedSessionSecurityKeyExchangeMIC()
+ {
+ string password = "Password";
+ byte[] type1 = new byte[] { 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x01, 0x00, 0x00, 0x00, 0x97, 0x82, 0x08, 0xe2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x0a, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x0f};
+ byte[] type2 = new byte[] { 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00,
+ 0x38, 0x00, 0x00, 0x00, 0x15, 0x82, 0x8a, 0xe2, 0x7a, 0x6d, 0x47, 0x52, 0x11, 0x8b, 0x9f, 0x37,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 0x48, 0x00, 0x00, 0x00,
+ 0x06, 0x00, 0x71, 0x17, 0x00, 0x00, 0x00, 0x0f, 0x54, 0x00, 0x41, 0x00, 0x4c, 0x00, 0x2d, 0x00,
+ 0x56, 0x00, 0x4d, 0x00, 0x31, 0x00, 0x30, 0x00, 0x02, 0x00, 0x10, 0x00, 0x54, 0x00, 0x41, 0x00,
+ 0x4c, 0x00, 0x2d, 0x00, 0x56, 0x00, 0x4d, 0x00, 0x31, 0x00, 0x30, 0x00, 0x01, 0x00, 0x10, 0x00,
+ 0x54, 0x00, 0x41, 0x00, 0x4c, 0x00, 0x2d, 0x00, 0x56, 0x00, 0x4d, 0x00, 0x31, 0x00, 0x30, 0x00,
+ 0x04, 0x00, 0x10, 0x00, 0x54, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x2d, 0x00, 0x56, 0x00, 0x4d, 0x00,
+ 0x31, 0x00, 0x30, 0x00, 0x03, 0x00, 0x10, 0x00, 0x54, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x2d, 0x00,
+ 0x56, 0x00, 0x4d, 0x00, 0x31, 0x00, 0x30, 0x00, 0x07, 0x00, 0x08, 0x00, 0x28, 0x9a, 0x19, 0xec,
+ 0x8d, 0x92, 0xd2, 0x01, 0x00, 0x00, 0x00, 0x00};
+ byte[] type3 = new byte[] { 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x03, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00,
+ 0x7c, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0x94, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x0e, 0x00,
+ 0x58, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x66, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x0e, 0x00,
+ 0x6e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0xac, 0x00, 0x00, 0x00, 0x15, 0x82, 0x88, 0xe2,
+ 0x0a, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x0f, 0xc6, 0x21, 0x82, 0x59, 0x83, 0xda, 0xc7, 0xe7,
+ 0xfa, 0x96, 0x44, 0x67, 0x16, 0xc3, 0xb3, 0x5b, 0x54, 0x00, 0x41, 0x00, 0x4c, 0x00, 0x2d, 0x00,
+ 0x56, 0x00, 0x4d, 0x00, 0x36, 0x00, 0x55, 0x00, 0x73, 0x00, 0x65, 0x00, 0x72, 0x00, 0x54, 0x00,
+ 0x41, 0x00, 0x4c, 0x00, 0x2d, 0x00, 0x56, 0x00, 0x4d, 0x00, 0x36, 0x00, 0x90, 0x13, 0xb0, 0x36,
+ 0xa4, 0xa5, 0xf0, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x5c, 0x46, 0xea, 0x77, 0x30, 0x44, 0xee, 0xa5, 0x98, 0x26, 0xa0, 0x93,
+ 0x71, 0x5c, 0x83, 0xff, 0x76, 0x70, 0x1d, 0xf0, 0xb8, 0xa0, 0xad, 0x4d, 0xac, 0xe9, 0xf4, 0x5c,
+ 0x3e, 0xb1, 0xb6, 0x48, 0x08, 0xa0, 0x46, 0x8c, 0x31, 0xe1, 0x2d, 0x60};
+
+ byte[] serverChallenge = new ChallengeMessage(type2).ServerChallenge;
+ AuthenticateMessage authenticateMessage = new AuthenticateMessage(type3);
+ byte[] sessionBaseKey = new MD4().GetByteHashFromBytes(NTLMCryptography.NTOWFv1(password));
+ byte[] lmowf = NTLMCryptography.LMOWFv1(password);
+ byte[] exportedSessionKey = GetExportedSessionKey(sessionBaseKey, authenticateMessage, serverChallenge, lmowf);
+
+ // https://msdn.microsoft.com/en-us/library/cc236695.aspx
+ const int micFieldOffset = 72;
+ ByteWriter.WriteBytes(type3, micFieldOffset, new byte[16]);
+ byte[] temp = ByteUtils.Concatenate(ByteUtils.Concatenate(type1, type2), type3);
+ byte[] mic = new HMACMD5(exportedSessionKey).ComputeHash(temp);
+ byte[] expected = new byte[] { 0xc6, 0x21, 0x82, 0x59, 0x83, 0xda, 0xc7, 0xe7, 0xfa, 0x96, 0x44, 0x67, 0x16, 0xc3, 0xb3, 0x5b };
+
+ Assert.IsTrue(ByteUtils.AreByteArraysEqual(mic, expected));
+ }
+
+ [TestMethod]
+ public void TestNTLMv2KeyExchangeMIC()
+ {
+ byte[] responseKeyNT = NTLMCryptography.NTOWFv2("Password", "User", "TAL-VM6");
+ byte[] type1 = new byte[] { 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x01, 0x00, 0x00, 0x00, 0x97, 0x82, 0x08, 0xe2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x0a, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x0f};
+ byte[] type2 = new byte[] { 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00,
+ 0x38, 0x00, 0x00, 0x00, 0x15, 0x82, 0x8a, 0xe2, 0x63, 0x74, 0x79, 0x77, 0xe1, 0xea, 0x35, 0x51,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 0x48, 0x00, 0x00, 0x00,
+ 0x06, 0x00, 0x71, 0x17, 0x00, 0x00, 0x00, 0x0f, 0x54, 0x00, 0x41, 0x00, 0x4c, 0x00, 0x2d, 0x00,
+ 0x56, 0x00, 0x4d, 0x00, 0x31, 0x00, 0x30, 0x00, 0x02, 0x00, 0x10, 0x00, 0x54, 0x00, 0x41, 0x00,
+ 0x4c, 0x00, 0x2d, 0x00, 0x56, 0x00, 0x4d, 0x00, 0x31, 0x00, 0x30, 0x00, 0x01, 0x00, 0x10, 0x00,
+ 0x54, 0x00, 0x41, 0x00, 0x4c, 0x00, 0x2d, 0x00, 0x56, 0x00, 0x4d, 0x00, 0x31, 0x00, 0x30, 0x00,
+ 0x04, 0x00, 0x10, 0x00, 0x54, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x2d, 0x00, 0x56, 0x00, 0x4d, 0x00,
+ 0x31, 0x00, 0x30, 0x00, 0x03, 0x00, 0x10, 0x00, 0x54, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x2d, 0x00,
+ 0x56, 0x00, 0x4d, 0x00, 0x31, 0x00, 0x30, 0x00, 0x07, 0x00, 0x08, 0x00, 0x1f, 0x8a, 0xd4, 0xff,
+ 0x01, 0x91, 0xd2, 0x01, 0x00, 0x00, 0x00, 0x00};
+ byte[] type3 = new byte[] { 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x03, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00,
+ 0x7c, 0x00, 0x00, 0x00, 0x02, 0x01, 0x02, 0x01, 0x94, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x0e, 0x00,
+ 0x58, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x66, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x0e, 0x00,
+ 0x6e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x96, 0x01, 0x00, 0x00, 0x15, 0x82, 0x88, 0xe2,
+ 0x0a, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x0f, 0x82, 0x3c, 0xff, 0x48, 0xa9, 0x03, 0x13, 0x4c,
+ 0x33, 0x3c, 0x09, 0x87, 0xf3, 0x16, 0x59, 0x89, 0x54, 0x00, 0x41, 0x00, 0x4c, 0x00, 0x2d, 0x00,
+ 0x56, 0x00, 0x4d, 0x00, 0x36, 0x00, 0x55, 0x00, 0x73, 0x00, 0x65, 0x00, 0x72, 0x00, 0x54, 0x00,
+ 0x41, 0x00, 0x4c, 0x00, 0x2d, 0x00, 0x56, 0x00, 0x4d, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xb3, 0x06, 0x65, 0xe3, 0x9f, 0x03, 0xe1, 0xc3, 0xd8, 0x28, 0x7c, 0x9c,
+ 0x35, 0x0d, 0x32, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x8a, 0xd4, 0xff,
+ 0x01, 0x91, 0xd2, 0x01, 0x77, 0x71, 0x91, 0x94, 0xb1, 0x6e, 0x66, 0x28, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x10, 0x00, 0x54, 0x00, 0x41, 0x00, 0x4c, 0x00, 0x2d, 0x00, 0x56, 0x00, 0x4d, 0x00,
+ 0x31, 0x00, 0x30, 0x00, 0x01, 0x00, 0x10, 0x00, 0x54, 0x00, 0x41, 0x00, 0x4c, 0x00, 0x2d, 0x00,
+ 0x56, 0x00, 0x4d, 0x00, 0x31, 0x00, 0x30, 0x00, 0x04, 0x00, 0x10, 0x00, 0x54, 0x00, 0x61, 0x00,
+ 0x6c, 0x00, 0x2d, 0x00, 0x56, 0x00, 0x4d, 0x00, 0x31, 0x00, 0x30, 0x00, 0x03, 0x00, 0x10, 0x00,
+ 0x54, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x2d, 0x00, 0x56, 0x00, 0x4d, 0x00, 0x31, 0x00, 0x30, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x1f, 0x8a, 0xd4, 0xff, 0x01, 0x91, 0xd2, 0x01, 0x06, 0x00, 0x04, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x19, 0x0d, 0x73, 0xca, 0x97, 0x30, 0x2a, 0xa7,
+ 0x7a, 0x1f, 0xb6, 0xad, 0xe2, 0xe5, 0x4a, 0x59, 0x4a, 0x93, 0x7e, 0x37, 0xcd, 0x0c, 0xd7, 0x90,
+ 0x25, 0xc4, 0xaf, 0x8a, 0x17, 0x99, 0x69, 0x56, 0x0a, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x1a, 0x00,
+ 0x63, 0x00, 0x69, 0x00, 0x66, 0x00, 0x73, 0x00, 0x2f, 0x00, 0x54, 0x00, 0x61, 0x00, 0x6c, 0x00,
+ 0x2d, 0x00, 0x56, 0x00, 0x4d, 0x00, 0x31, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x71, 0x7c, 0xce, 0x0b, 0x92, 0x46, 0x46, 0x0d, 0x5b, 0x3b,
+ 0x11, 0xb4, 0xde, 0x86, 0x28, 0x11};
+
+ byte[] serverChallenge = new ChallengeMessage(type2).ServerChallenge;
+ AuthenticateMessage authenticateMessage = new AuthenticateMessage(type3);
+ byte[] ntProofStr = ByteReader.ReadBytes(authenticateMessage.NtChallengeResponse, 0, 16);
+ byte[] sessionBaseKey = new HMACMD5(responseKeyNT).ComputeHash(ntProofStr);
+ byte[] exportedSessionKey = GetExportedSessionKey(sessionBaseKey, authenticateMessage, serverChallenge, null);
+
+ // https://msdn.microsoft.com/en-us/library/cc236695.aspx
+ const int micFieldOffset = 72;
+ ByteWriter.WriteBytes(type3, micFieldOffset, new byte[16]);
+ byte[] temp = ByteUtils.Concatenate(ByteUtils.Concatenate(type1, type2), type3);
+ byte[] mic = new HMACMD5(exportedSessionKey).ComputeHash(temp);
+ byte[] expected = new byte[] { 0x82, 0x3c, 0xff, 0x48, 0xa9, 0x03, 0x13, 0x4c, 0x33, 0x3c, 0x09, 0x87, 0xf3, 0x16, 0x59, 0x89 };
+
+ Assert.IsTrue(ByteUtils.AreByteArraysEqual(mic, expected));
+ }
+
+ public void TestAll()
+ {
+ TestLMMIC();
+ TestNTLMv1MIC();
+ TestNTLMv1ExtendedSessionSecurityKeyExchangeMIC();
+ TestNTLMv2KeyExchangeMIC();
+ }
+
+ private static byte[] GetExportedSessionKey(byte[] sessionBaseKey, AuthenticateMessage message, byte[] serverChallenge, byte[] lmowf)
+ {
+ byte[] keyExchangeKey;
+ if (AuthenticationMessageUtils.IsNTLMv2NTResponse(message.NtChallengeResponse))
+ {
+ keyExchangeKey = sessionBaseKey;
+ }
+ else
+ {
+ keyExchangeKey = NTLMCryptography.KXKey(sessionBaseKey, message.NegotiateFlags, message.LmChallengeResponse, serverChallenge, lmowf);
+ }
+
+ if ((message.NegotiateFlags & NegotiateFlags.KeyExchange) > 0)
+ {
+ return RC4.Decrypt(keyExchangeKey, message.EncryptedRandomSessionKey);
+ }
+ else
+ {
+ return keyExchangeKey;
+ }
+ }
+ }
+}
diff --git a/SMBLibrary.Tests/NTLM/RC4Tests.cs b/SMBLibrary.Tests/NTLM/RC4Tests.cs
new file mode 100644
index 0000000..4fa43b9
--- /dev/null
+++ b/SMBLibrary.Tests/NTLM/RC4Tests.cs
@@ -0,0 +1,136 @@
+/* Copyright (C) 2017-2019 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,
+ * either version 3 of the License, or (at your option) any later version.
+ */
+using System;
+using System.Collections.Generic;
+using System.Security.Cryptography;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Utilities;
+
+namespace SMBLibrary.Tests
+{
+ ///
+ /// https://tools.ietf.org/id/draft-kaukonen-cipher-arcfour-03.txt
+ /// Test Vectors from Appendix A
+ ///
+ [TestClass]
+ public class RC4Tests
+ {
+ [TestMethod]
+ public void Test1()
+ {
+ byte[] key = new byte[] { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF };
+ byte[] text = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ byte[] expectedCipher = new byte[] { 0x74, 0x94, 0xC2, 0xE7, 0x10, 0x4B, 0x08, 0x79 };
+ byte[] cipher = RC4.Encrypt(key, text);
+ Assert.IsTrue(ByteUtils.AreByteArraysEqual(cipher, expectedCipher));
+ }
+
+ [TestMethod]
+ public void Test2()
+ {
+ byte[] key = new byte[] { 0x61, 0x8A, 0x63, 0xD2, 0xFB };
+ byte[] text = new byte[] { 0xDC, 0xEE, 0x4C, 0xF9, 0x2C };
+ byte[] expectedCipher = new byte[] { 0xF1, 0x38, 0x29, 0xC9, 0xDE };
+ byte[] cipher = RC4.Encrypt(key, text);
+ Assert.IsTrue(ByteUtils.AreByteArraysEqual(cipher, expectedCipher));
+ }
+
+ [TestMethod]
+ public void Test3()
+ {
+ byte[] key = new byte[] { 0x29, 0x04, 0x19, 0x72, 0xFB, 0x42, 0xBA, 0x5F,
+ 0xC7, 0x12, 0x77, 0x12, 0xF1, 0x38, 0x29, 0xC9};
+ byte[] text = new byte[] { 0x52, 0x75, 0x69, 0x73, 0x6c, 0x69, 0x6e, 0x6e,
+ 0x75, 0x6e, 0x20, 0x6c, 0x61, 0x75, 0x6c, 0x75,
+ 0x20, 0x6b, 0x6f, 0x72, 0x76, 0x69, 0x73, 0x73,
+ 0x73, 0x61, 0x6e, 0x69, 0x2c, 0x20, 0x74, 0xe4,
+ 0x68, 0x6b, 0xe4, 0x70, 0xe4, 0x69, 0x64, 0x65,
+ 0x6e, 0x20, 0x70, 0xe4, 0xe4, 0x6c, 0x6c, 0xe4,
+ 0x20, 0x74, 0xe4, 0x79, 0x73, 0x69, 0x6b, 0x75,
+ 0x75, 0x2e, 0x20, 0x4b, 0x65, 0x73, 0xe4, 0x79,
+ 0xf6, 0x6e, 0x20, 0x6f, 0x6e, 0x20, 0x6f, 0x6e,
+ 0x6e, 0x69, 0x20, 0x6f, 0x6d, 0x61, 0x6e, 0x61,
+ 0x6e, 0x69, 0x2c, 0x20, 0x6b, 0x61, 0x73, 0x6b,
+ 0x69, 0x73, 0x61, 0x76, 0x75, 0x75, 0x6e, 0x20,
+ 0x6c, 0x61, 0x61, 0x6b, 0x73, 0x6f, 0x74, 0x20,
+ 0x76, 0x65, 0x72, 0x68, 0x6f, 0x75, 0x75, 0x2e,
+ 0x20, 0x45, 0x6e, 0x20, 0x6d, 0x61, 0x20, 0x69,
+ 0x6c, 0x6f, 0x69, 0x74, 0x73, 0x65, 0x2c, 0x20,
+ 0x73, 0x75, 0x72, 0x65, 0x20, 0x68, 0x75, 0x6f,
+ 0x6b, 0x61, 0x61, 0x2c, 0x20, 0x6d, 0x75, 0x74,
+ 0x74, 0x61, 0x20, 0x6d, 0x65, 0x74, 0x73, 0xe4,
+ 0x6e, 0x20, 0x74, 0x75, 0x6d, 0x6d, 0x75, 0x75,
+ 0x73, 0x20, 0x6d, 0x75, 0x6c, 0x6c, 0x65, 0x20,
+ 0x74, 0x75, 0x6f, 0x6b, 0x61, 0x61, 0x2e, 0x20,
+ 0x50, 0x75, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x70,
+ 0x69, 0x6c, 0x76, 0x65, 0x6e, 0x2c, 0x20, 0x6d,
+ 0x69, 0x20, 0x68, 0x75, 0x6b, 0x6b, 0x75, 0x75,
+ 0x2c, 0x20, 0x73, 0x69, 0x69, 0x6e, 0x74, 0x6f,
+ 0x20, 0x76, 0x61, 0x72, 0x61, 0x6e, 0x20, 0x74,
+ 0x75, 0x75, 0x6c, 0x69, 0x73, 0x65, 0x6e, 0x2c,
+ 0x20, 0x6d, 0x69, 0x20, 0x6e, 0x75, 0x6b, 0x6b,
+ 0x75, 0x75, 0x2e, 0x20, 0x54, 0x75, 0x6f, 0x6b,
+ 0x73, 0x75, 0x74, 0x20, 0x76, 0x61, 0x6e, 0x61,
+ 0x6d, 0x6f, 0x6e, 0x20, 0x6a, 0x61, 0x20, 0x76,
+ 0x61, 0x72, 0x6a, 0x6f, 0x74, 0x20, 0x76, 0x65,
+ 0x65, 0x6e, 0x2c, 0x20, 0x6e, 0x69, 0x69, 0x73,
+ 0x74, 0xe4, 0x20, 0x73, 0x79, 0x64, 0xe4, 0x6d,
+ 0x65, 0x6e, 0x69, 0x20, 0x6c, 0x61, 0x75, 0x6c,
+ 0x75, 0x6e, 0x20, 0x74, 0x65, 0x65, 0x6e, 0x2e,
+ 0x20, 0x2d, 0x20, 0x45, 0x69, 0x6e, 0x6f, 0x20,
+ 0x4c, 0x65, 0x69, 0x6e, 0x6f};
+ byte[] expectedCipher = new byte[] { 0x35, 0x81, 0x86, 0x99, 0x90, 0x01, 0xe6, 0xb5,
+ 0xda, 0xf0, 0x5e, 0xce, 0xeb, 0x7e, 0xee, 0x21,
+ 0xe0, 0x68, 0x9c, 0x1f, 0x00, 0xee, 0xa8, 0x1f,
+ 0x7d, 0xd2, 0xca, 0xae, 0xe1, 0xd2, 0x76, 0x3e,
+ 0x68, 0xaf, 0x0e, 0xad, 0x33, 0xd6, 0x6c, 0x26,
+ 0x8b, 0xc9, 0x46, 0xc4, 0x84, 0xfb, 0xe9, 0x4c,
+ 0x5f, 0x5e, 0x0b, 0x86, 0xa5, 0x92, 0x79, 0xe4,
+ 0xf8, 0x24, 0xe7, 0xa6, 0x40, 0xbd, 0x22, 0x32,
+ 0x10, 0xb0, 0xa6, 0x11, 0x60, 0xb7, 0xbc, 0xe9,
+ 0x86, 0xea, 0x65, 0x68, 0x80, 0x03, 0x59, 0x6b,
+ 0x63, 0x0a, 0x6b, 0x90, 0xf8, 0xe0, 0xca, 0xf6,
+ 0x91, 0x2a, 0x98, 0xeb, 0x87, 0x21, 0x76, 0xe8,
+ 0x3c, 0x20, 0x2c, 0xaa, 0x64, 0x16, 0x6d, 0x2c,
+ 0xce, 0x57, 0xff, 0x1b, 0xca, 0x57, 0xb2, 0x13,
+ 0xf0, 0xed, 0x1a, 0xa7, 0x2f, 0xb8, 0xea, 0x52,
+ 0xb0, 0xbe, 0x01, 0xcd, 0x1e, 0x41, 0x28, 0x67,
+ 0x72, 0x0b, 0x32, 0x6e, 0xb3, 0x89, 0xd0, 0x11,
+ 0xbd, 0x70, 0xd8, 0xaf, 0x03, 0x5f, 0xb0, 0xd8,
+ 0x58, 0x9d, 0xbc, 0xe3, 0xc6, 0x66, 0xf5, 0xea,
+ 0x8d, 0x4c, 0x79, 0x54, 0xc5, 0x0c, 0x3f, 0x34,
+ 0x0b, 0x04, 0x67, 0xf8, 0x1b, 0x42, 0x59, 0x61,
+ 0xc1, 0x18, 0x43, 0x07, 0x4d, 0xf6, 0x20, 0xf2,
+ 0x08, 0x40, 0x4b, 0x39, 0x4c, 0xf9, 0xd3, 0x7f,
+ 0xf5, 0x4b, 0x5f, 0x1a, 0xd8, 0xf6, 0xea, 0x7d,
+ 0xa3, 0xc5, 0x61, 0xdf, 0xa7, 0x28, 0x1f, 0x96,
+ 0x44, 0x63, 0xd2, 0xcc, 0x35, 0xa4, 0xd1, 0xb0,
+ 0x34, 0x90, 0xde, 0xc5, 0x1b, 0x07, 0x11, 0xfb,
+ 0xd6, 0xf5, 0x5f, 0x79, 0x23, 0x4d, 0x5b, 0x7c,
+ 0x76, 0x66, 0x22, 0xa6, 0x6d, 0xe9, 0x2b, 0xe9,
+ 0x96, 0x46, 0x1d, 0x5e, 0x4d, 0xc8, 0x78, 0xef,
+ 0x9b, 0xca, 0x03, 0x05, 0x21, 0xe8, 0x35, 0x1e,
+ 0x4b, 0xae, 0xd2, 0xfd, 0x04, 0xf9, 0x46, 0x73,
+ 0x68, 0xc4, 0xad, 0x6a, 0xc1, 0x86, 0xd0, 0x82,
+ 0x45, 0xb2, 0x63, 0xa2, 0x66, 0x6d, 0x1f, 0x6c,
+ 0x54, 0x20, 0xf1, 0x59, 0x9d, 0xfd, 0x9f, 0x43,
+ 0x89, 0x21, 0xc2, 0xf5, 0xa4, 0x63, 0x93, 0x8c,
+ 0xe0, 0x98, 0x22, 0x65, 0xee, 0xf7, 0x01, 0x79,
+ 0xbc, 0x55, 0x3f, 0x33, 0x9e, 0xb1, 0xa4, 0xc1,
+ 0xaf, 0x5f, 0x6a, 0x54, 0x7f};
+ byte[] cipher = RC4.Encrypt(key, text);
+ Assert.IsTrue(ByteUtils.AreByteArraysEqual(cipher, expectedCipher));
+ }
+
+ public void TestAll()
+ {
+ Test1();
+ Test2();
+ Test3();
+ }
+ }
+}
diff --git a/SMBLibrary.Tests/NetBiosTests.cs b/SMBLibrary.Tests/NetBiosTests.cs
new file mode 100644
index 0000000..d3f8fc4
--- /dev/null
+++ b/SMBLibrary.Tests/NetBiosTests.cs
@@ -0,0 +1,44 @@
+/* Copyright (C) 2017-2019 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,
+ * either version 3 of the License, or (at your option) any later version.
+ */
+using System;
+using System.Collections.Generic;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using SMBLibrary.NetBios;
+using Utilities;
+
+namespace SMBLibrary.Tests
+{
+ [TestClass]
+ public class NetBiosTests
+ {
+ [TestMethod]
+ public void Test1()
+ {
+ byte[] buffer = new byte[] { 0x20, 0x46, 0x47, 0x45, 0x4e, 0x44, 0x4a, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x00 };
+ int offset = 0;
+ string name = NetBiosUtils.DecodeName(buffer, ref offset);
+ byte[] encodedName = NetBiosUtils.EncodeName(name, String.Empty);
+ Assert.IsTrue(ByteUtils.AreByteArraysEqual(buffer, encodedName));
+ }
+
+ [TestMethod]
+ public void Test2()
+ {
+ byte[] buffer = new byte[] { 0x20, 0x46, 0x47, 0x45, 0x4e, 0x44, 0x4a, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x41, 0x41, 0x00 };
+ int offset = 0;
+ string name = NetBiosUtils.DecodeName(buffer, ref offset);
+ byte[] encodedName = NetBiosUtils.EncodeName(name, String.Empty);
+ Assert.IsTrue(ByteUtils.AreByteArraysEqual(buffer, encodedName));
+ }
+
+ public void TestAll()
+ {
+ Test1();
+ Test2();
+ }
+ }
+}
diff --git a/SMBLibrary.Tests/Program.cs b/SMBLibrary.Tests/Program.cs
new file mode 100644
index 0000000..14fd6f4
--- /dev/null
+++ b/SMBLibrary.Tests/Program.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace SMBLibrary.Tests
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ new NTLMAuthenticationTests().TestAll();
+ new NTLMSigningTests().TestAll();
+ new RC4Tests().TestAll();
+
+ new NetBiosTests().TestAll();
+ new RPCTests().TestAll();
+ new SMB2SigningTests().TestAll();
+ }
+ }
+}
diff --git a/SMBLibrary.Tests/Properties/AssemblyInfo.cs b/SMBLibrary.Tests/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..abd6321
--- /dev/null
+++ b/SMBLibrary.Tests/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("SMBLibrary.Tests")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Tal Aloni")]
+[assembly: AssemblyProduct("SMBLibrary.Tests")]
+[assembly: AssemblyCopyright("Copyright © Tal Aloni 2014-2019")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("8ab9297a-1e84-4d7e-a080-cf2fbaf9af1d")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/SMBLibrary.Tests/RPCTests.cs b/SMBLibrary.Tests/RPCTests.cs
new file mode 100644
index 0000000..bcda875
--- /dev/null
+++ b/SMBLibrary.Tests/RPCTests.cs
@@ -0,0 +1,110 @@
+/* Copyright (C) 2014-2019 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,
+ * either version 3 of the License, or (at your option) any later version.
+ */
+using System;
+using System.Collections.Generic;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using SMBLibrary.RPC;
+using SMBLibrary.Services;
+using Utilities;
+
+namespace SMBLibrary.Tests
+{
+ [TestClass]
+ public class RPCTests
+ {
+ [TestMethod]
+ public void Test1()
+ {
+ byte[] buffer = new byte[]{ 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xf4, 0x01, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00,
+ 0x08, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x54, 0x00, 0x41, 0x00, 0x4c, 0x00, 0x32, 0x00,
+ 0x2d, 0x00, 0x56, 0x00, 0x4d, 0x00, 0x37, 0x00, 0x00, 0x00, 0xcd, 0xab, 0x0a, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x57, 0x00, 0x4f, 0x00, 0x52, 0x00, 0x4b, 0x00,
+ 0x47, 0x00, 0x52, 0x00, 0x4f, 0x00, 0x55, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ NetrWkstaGetInfoResponse response = new NetrWkstaGetInfoResponse(buffer);
+
+ byte[] responseBytes = response.GetBytes();
+ //Assert.IsTrue(ByteUtils.AreByteArraysEqual(buffer, responseBytes));
+ }
+
+ [TestMethod]
+ public void Test2()
+ {
+ byte[] buffer = new byte[] { 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xf4, 0x01, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x90, 0x84, 0x00, 0x08, 0x00, 0x02, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x39, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x31, 0x00, 0x36, 0x00, 0x38, 0x00, 0x2e, 0x00, 0x31, 0x00, 0x2e, 0x00, 0x35, 0x00, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ NetrServerGetInfoResponse response = new NetrServerGetInfoResponse(buffer);
+
+ byte[] responseBytes = response.GetBytes();
+ //Assert.IsTrue(ByteUtils.AreByteArraysEqual(buffer, responseBytes));
+ }
+
+ [TestMethod]
+ public void Test3()
+ {
+ byte[] buffer = new byte[] {0x00, 0x00, 0x02, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
+ 0x5c, 0x00, 0x5c, 0x00, 0x31, 0x00, 0x39, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x31, 0x00, 0x36, 0x00,
+ 0x38, 0x00, 0x2e, 0x00, 0x31, 0x00, 0x2e, 0x00, 0x35, 0x00, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00};
+ NetrShareEnumRequest request = new NetrShareEnumRequest(buffer);
+
+ byte[] requestBytes = request.GetBytes();
+ //Assert.IsTrue(ByteUtils.AreByteArraysEqual(buffer, requestBytes));
+ }
+
+ [TestMethod]
+ public void Test4()
+ {
+ byte[] buffer = new byte[] {0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x80,
+ 0x0c, 0x00, 0x02, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x02, 0x00,
+ 0x18, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00, 0x80, 0x1c, 0x00, 0x02, 0x00, 0x20, 0x00, 0x02, 0x00,
+ 0x00, 0x00, 0x00, 0x80, 0x24, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x43, 0x00, 0x24, 0x00, 0x00, 0x00, 0x69, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x44, 0x00, 0x65, 0x00, 0x66, 0x00, 0x61, 0x00,
+ 0x75, 0x00, 0x6c, 0x00, 0x74, 0x00, 0x20, 0x00, 0x73, 0x00, 0x68, 0x00, 0x61, 0x00, 0x72, 0x00,
+ 0x65, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+ 0x53, 0x00, 0x68, 0x00, 0x61, 0x00, 0x72, 0x00, 0x65, 0x00, 0x64, 0x00, 0x00, 0x00, 0x41, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x49, 0x00, 0x50, 0x00,
+ 0x43, 0x00, 0x24, 0x00, 0x00, 0x00, 0x24, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x0b, 0x00, 0x00, 0x00, 0x52, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x65, 0x00,
+ 0x20, 0x00, 0x49, 0x00, 0x50, 0x00, 0x43, 0x00, 0x00, 0x00, 0x68, 0x00, 0x07, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x41, 0x00, 0x44, 0x00, 0x4d, 0x00, 0x49, 0x00,
+ 0x4e, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x0d, 0x00, 0x00, 0x00, 0x52, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x65, 0x00,
+ 0x20, 0x00, 0x41, 0x00, 0x64, 0x00, 0x6d, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ NetrShareEnumResponse response = new NetrShareEnumResponse(buffer);
+
+ byte[] responseBytes = response.GetBytes();
+ //Assert.IsTrue(ByteUtils.AreByteArraysEqual(buffer, responseBytes));
+ }
+
+ [TestMethod]
+ public void Test5()
+ {
+ byte[] buffer = new byte[] {0x00, 0x00, 0x02, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
+ 0x5c, 0x00, 0x5c, 0x00, 0x31, 0x00, 0x39, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x31, 0x00, 0x36, 0x00,
+ 0x38, 0x00, 0x2e, 0x00, 0x31, 0x00, 0x2e, 0x00, 0x35, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x53, 0x00, 0x68, 0x00,
+ 0x61, 0x00, 0x72, 0x00, 0x65, 0x00, 0x64, 0x00, 0x00, 0x00, 0xb7, 0x6c, 0x02, 0x00, 0x00, 0x00};
+ NetrShareGetInfoRequest request = new NetrShareGetInfoRequest(buffer);
+
+ byte[] requestBytes = request.GetBytes();
+ //Assert.IsTrue(ByteUtils.AreByteArraysEqual(buffer, requestBytes));
+ }
+
+ public void TestAll()
+ {
+ Test1();
+ Test2();
+ Test3();
+ Test4();
+ Test5();
+ }
+ }
+}
diff --git a/SMBLibrary.Tests/SMB2SigningTests.cs b/SMBLibrary.Tests/SMB2SigningTests.cs
new file mode 100644
index 0000000..8a6890b
--- /dev/null
+++ b/SMBLibrary.Tests/SMB2SigningTests.cs
@@ -0,0 +1,62 @@
+/* Copyright (C) 2017-2019 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,
+ * either version 3 of the License, or (at your option) any later version.
+ */
+using System;
+using System.Collections.Generic;
+using System.Security.Cryptography;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Utilities;
+
+namespace SMBLibrary.Tests
+{
+ [TestClass]
+ public class SMB2SigningTests
+ {
+ [TestMethod]
+ public void Test1()
+ {
+ byte[] exportedSessionKey = new byte[] { 0xD3, 0x83, 0x54, 0xCC, 0x37, 0x43, 0x39, 0xF0, 0x52, 0x4F, 0x78, 0x91, 0x46, 0x78, 0x99, 0x21 };
+
+ byte[] message = new byte[]{0xfe, 0x53, 0x4d, 0x42, 0x40, 0x00, 0x01, 0x00, 0x28, 0x01, 0x00, 0xc0, 0x0b, 0x00, 0x07, 0x00,
+ 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xfe, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
+ 0xfb, 0xd2, 0x84, 0x34, 0x03, 0x24, 0xc6, 0x2f, 0xbe, 0xbb, 0x65, 0xdd, 0x10, 0x51, 0xf3, 0xae,
+ 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff};
+
+ ByteWriter.WriteBytes(message, 48, new byte[16]);
+
+ byte[] signature = new HMACSHA256(exportedSessionKey).ComputeHash(message);
+ signature = ByteReader.ReadBytes(signature, 0, 16);
+ byte[] expected = new byte[] { 0xfb, 0xd2, 0x84, 0x34, 0x03, 0x24, 0xc6, 0x2f, 0xbe, 0xbb, 0x65, 0xdd, 0x10, 0x51, 0xf3, 0xae };
+ Assert.IsTrue(ByteUtils.AreByteArraysEqual(signature, expected));
+ }
+
+ [TestMethod]
+ public void Test2()
+ {
+ byte[] exportedSessionKey = new byte[] { 0x04, 0xE7, 0x07, 0x57, 0x1F, 0x8E, 0x03, 0x53, 0xB7, 0x7A, 0x94, 0xC3, 0x65, 0x3B, 0x87, 0xB5 };
+
+ byte[] message = new byte[]{ 0xfe, 0x53, 0x4d, 0x42, 0x40, 0x00, 0x01, 0x00, 0x28, 0x01, 0x00, 0xc0, 0x0b, 0x00, 0x07, 0x00,
+ 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xfe, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
+ 0xa1, 0x64, 0xff, 0xe5, 0x3d, 0x68, 0x11, 0x98, 0x1f, 0x38, 0x67, 0x72, 0xe3, 0x87, 0xe0, 0x6f,
+ 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff};
+
+ ByteWriter.WriteBytes(message, 48, new byte[16]);
+
+ byte[] signature = new HMACSHA256(exportedSessionKey).ComputeHash(message);
+ signature = ByteReader.ReadBytes(signature, 0, 16);
+ byte[] expected = new byte[] { 0xa1, 0x64, 0xff, 0xe5, 0x3d, 0x68, 0x11, 0x98, 0x1f, 0x38, 0x67, 0x72, 0xe3, 0x87, 0xe0, 0x6f };
+ Assert.IsTrue(ByteUtils.AreByteArraysEqual(signature, expected));
+ }
+
+ public void TestAll()
+ {
+ Test1();
+ Test2();
+ }
+ }
+}
diff --git a/SMBLibrary.Tests/SMBLibrary.Tests.csproj b/SMBLibrary.Tests/SMBLibrary.Tests.csproj
new file mode 100644
index 0000000..c184e26
--- /dev/null
+++ b/SMBLibrary.Tests/SMBLibrary.Tests.csproj
@@ -0,0 +1,69 @@
+
+
+ Debug
+ AnyCPU
+ 8.0.50727
+ 2.0
+ {C79B06EB-32C1-44CA-B7E1-A891B8135658}
+ Exe
+ Properties
+ SMBLibrary.Tests
+ SMBLibrary.Tests
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ False
+ Components\Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {8CE25496-A52B-4841-822F-74C469D10EE7}
+ SMBLibrary.Win32
+
+
+ {8D9E8F5D-FD13-4E4C-9723-A333DA2034A7}
+ SMBLibrary
+
+
+ {6E0F2D1E-6167-4032-BA90-DEE3A99207D0}
+ Utilities
+
+
+
+
+
\ No newline at end of file
diff --git a/SMBLibrary/Authentication/NTLM/Helpers/MD4.cs b/SMBLibrary/Authentication/NTLM/Helpers/MD4.cs
index 64d8ec8..3d45fba 100644
--- a/SMBLibrary/Authentication/NTLM/Helpers/MD4.cs
+++ b/SMBLibrary/Authentication/NTLM/Helpers/MD4.cs
@@ -50,7 +50,7 @@ namespace System.Security.Cryptography
///
///
///
- internal class MD4
+ public class MD4
{
// MD4 specific object variables
//-----------------------------------------------------------------------
diff --git a/SMBLibrary/SMBLibrary.csproj b/SMBLibrary/SMBLibrary.csproj
index 96d335a..d355446 100644
--- a/SMBLibrary/SMBLibrary.csproj
+++ b/SMBLibrary/SMBLibrary.csproj
@@ -581,12 +581,6 @@
-
-
-
-
-
-
diff --git a/SMBServer.sln b/SMBServer.sln
index e1ac730..855ffd7 100644
--- a/SMBServer.sln
+++ b/SMBServer.sln
@@ -9,6 +9,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Utilities", "Utilities\Util
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SMBLibrary.Win32", "SMBLibrary.Win32\SMBLibrary.Win32.csproj", "{8CE25496-A52B-4841-822F-74C469D10EE7}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SMBLibrary.Tests", "SMBLibrary.Tests\SMBLibrary.Tests.csproj", "{C79B06EB-32C1-44CA-B7E1-A891B8135658}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -31,6 +33,10 @@ Global
{8CE25496-A52B-4841-822F-74C469D10EE7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8CE25496-A52B-4841-822F-74C469D10EE7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8CE25496-A52B-4841-822F-74C469D10EE7}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C79B06EB-32C1-44CA-B7E1-A891B8135658}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C79B06EB-32C1-44CA-B7E1-A891B8135658}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C79B06EB-32C1-44CA-B7E1-A891B8135658}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C79B06EB-32C1-44CA-B7E1-A891B8135658}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE