Quellcode durchsuchen

Improved SMB_COM_NEGOTIATE response implementation

Tal Aloni vor 8 Jahren
Ursprung
Commit
efc7c1fce9

+ 34 - 20
SMBLibrary/SMB1/Commands/NegotiateResponseNTLM.cs

@@ -1,4 +1,4 @@
-/* Copyright (C) 2014 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
+/* Copyright (C) 2014-2017 Tal Aloni <tal.aloni.il@gmail.com>. 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,
@@ -14,7 +14,7 @@ namespace SMBLibrary.SMB1
     /// <summary>
     /// SMB_COM_NEGOTIATE Response, NT LAN Manager dialect
     /// </summary>
-    public class NegotiateResponseNTLM : SMB1Command
+    public class NegotiateResponse : SMB1Command
     {
         public const int ParametersLength = 34;
         // Parameters:
@@ -28,22 +28,44 @@ namespace SMBLibrary.SMB1
         public ServerCapabilities Capabilities;
         public DateTime SystemTime;
         public short ServerTimeZone;
-        //byte ChallengeLength;
+        private byte ChallengeLength;
         // Data:
         public byte[] Challenge;
         public string DomainName; // SMB_STRING (If Unicode, this field MUST be aligned to start on a 2-byte boundary from the start of the SMB header)
         public string ServerName; // SMB_STRING (this field WILL be aligned to start on a 2-byte boundary from the start of the SMB header)
 
-        public NegotiateResponseNTLM() : base()
+        public NegotiateResponse() : base()
         {
             Challenge = new byte[0];
             DomainName = String.Empty;
             ServerName = String.Empty;
         }
 
+        public NegotiateResponse(byte[] buffer, int offset, bool isUnicode) : base(buffer, offset, isUnicode)
+        {
+            DialectIndex = LittleEndianConverter.ToUInt16(this.SMBParameters, 0);
+            SecurityMode = (SecurityMode)ByteReader.ReadByte(this.SMBParameters, 2);
+            MaxMpxCount = LittleEndianConverter.ToUInt16(this.SMBParameters, 3);
+            MaxNumberVcs = LittleEndianConverter.ToUInt16(this.SMBParameters, 5);
+            MaxBufferSize = LittleEndianConverter.ToUInt32(this.SMBParameters, 7);
+            MaxRawSize = LittleEndianConverter.ToUInt32(this.SMBParameters, 11);
+            SessionKey = LittleEndianConverter.ToUInt32(this.SMBParameters, 15);
+            Capabilities = (ServerCapabilities)LittleEndianConverter.ToUInt32(this.SMBParameters, 19);
+            SystemTime = FileTimeHelper.ReadFileTime(this.SMBParameters, 23);
+            ServerTimeZone = LittleEndianConverter.ToInt16(this.SMBParameters, 31);
+            ChallengeLength = ByteReader.ReadByte(this.SMBParameters, 33);
+
+            int dataOffset = 0;
+            Challenge = ByteReader.ReadBytes(this.SMBData, ref dataOffset, ChallengeLength);
+            // [MS-CIFS] <90> Padding is not added before DomainName
+            // DomainName and ServerName are always in Unicode
+            DomainName = SMB1Helper.ReadSMBString(this.SMBData, ref dataOffset, true);
+            ServerName = SMB1Helper.ReadSMBString(this.SMBData, ref dataOffset, true);
+        }
+
         public override byte[] GetBytes(bool isUnicode)
         {
-            byte challengeLength = (byte)this.Challenge.Length;
+            ChallengeLength = (byte)this.Challenge.Length;
 
             this.SMBParameters = new byte[ParametersLength];
             LittleEndianWriter.WriteUInt16(this.SMBParameters, 0, DialectIndex);
@@ -54,25 +76,17 @@ namespace SMBLibrary.SMB1
             LittleEndianWriter.WriteUInt32(this.SMBParameters, 11, MaxRawSize);
             LittleEndianWriter.WriteUInt32(this.SMBParameters, 15, SessionKey);
             LittleEndianWriter.WriteUInt32(this.SMBParameters, 19, (uint)Capabilities);
-            LittleEndianWriter.WriteInt64(this.SMBParameters, 23, SystemTime.ToFileTimeUtc());
+            FileTimeHelper.WriteFileTime(this.SMBParameters, 23, SystemTime);
             LittleEndianWriter.WriteInt16(this.SMBParameters, 31, ServerTimeZone);
-            ByteWriter.WriteByte(this.SMBParameters, 33, challengeLength);
+            ByteWriter.WriteByte(this.SMBParameters, 33, ChallengeLength);
 
-            int padding = 0;
-            if (isUnicode)
-            {
-                padding = Challenge.Length % 2;
-                this.SMBData = new byte[Challenge.Length + padding + DomainName.Length * 2 + ServerName.Length * 2 + 4];
-            }
-            else
-            {
-                this.SMBData = new byte[Challenge.Length + DomainName.Length + ServerName.Length + 2];
-            }
+            // [MS-CIFS] <90> Padding is not added before DomainName
+            // DomainName and ServerName are always in Unicode
+            this.SMBData = new byte[Challenge.Length + (DomainName.Length + 1) * 2 + (ServerName.Length + 1) * 2];
             int offset = 0;
             ByteWriter.WriteBytes(this.SMBData, ref offset, Challenge);
-            offset += padding;
-            SMB1Helper.WriteSMBString(this.SMBData, ref offset, isUnicode, DomainName);
-            SMB1Helper.WriteSMBString(this.SMBData, ref offset, isUnicode, ServerName);
+            SMB1Helper.WriteSMBString(this.SMBData, ref offset, true, DomainName);
+            SMB1Helper.WriteSMBString(this.SMBData, ref offset, true, ServerName);
 
             return base.GetBytes(isUnicode);
         }

+ 23 - 10
SMBLibrary/SMB1/Commands/NegotiateResponseNTLMExtended.cs

@@ -1,4 +1,4 @@
-/* Copyright (C) 2014 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
+/* Copyright (C) 2014-2017 Tal Aloni <tal.aloni.il@gmail.com>. 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,
@@ -14,7 +14,7 @@ namespace SMBLibrary.SMB1
     /// <summary>
     /// SMB_COM_NEGOTIATE Response, NT LAN Manager dialect, Extended Security response
     /// </summary>
-    public class NegotiateResponseNTLMExtended : SMB1Command
+    public class NegotiateResponseExtended : SMB1Command
     {
         public const int ParametersLength = 34;
         // Parameters:
@@ -28,25 +28,38 @@ namespace SMBLibrary.SMB1
         public ServerCapabilities Capabilities;
         public DateTime SystemTime;
         public short ServerTimeZone;
-        //byte ChallengeLength; // MUST be set to 0
+        private byte ChallengeLength; // MUST be set to 0
         // Data:
         public Guid ServerGuid;
         public byte[] SecurityBlob;
 
-        public NegotiateResponseNTLMExtended() : base()
+        public NegotiateResponseExtended() : base()
         {
-            // MS-SMB Page 129: The server can leave SecurityBlob empty if not configured to send GSS token
+            // [MS-SMB] 3.3.5.2: The server can leave SecurityBlob empty if not configured to send GSS token.
             SecurityBlob = new byte[0];
         }
 
-        public NegotiateResponseNTLMExtended(byte[] buffer, int offset) : base(buffer, offset, false)
+        public NegotiateResponseExtended(byte[] buffer, int offset) : base(buffer, offset, false)
         {
-            throw new NotImplementedException();
+            DialectIndex = LittleEndianConverter.ToUInt16(this.SMBParameters, 0);
+            SecurityMode = (SecurityMode)ByteReader.ReadByte(this.SMBParameters, 2);
+            MaxMpxCount = LittleEndianConverter.ToUInt16(this.SMBParameters, 3);
+            MaxNumberVcs = LittleEndianConverter.ToUInt16(this.SMBParameters, 5);
+            MaxBufferSize = LittleEndianConverter.ToUInt32(this.SMBParameters, 7);
+            MaxRawSize = LittleEndianConverter.ToUInt32(this.SMBParameters, 11);
+            SessionKey = LittleEndianConverter.ToUInt32(this.SMBParameters, 15);
+            Capabilities = (ServerCapabilities)LittleEndianConverter.ToUInt32(this.SMBParameters, 19);
+            SystemTime = FileTimeHelper.ReadFileTime(this.SMBParameters, 23);
+            ServerTimeZone = LittleEndianConverter.ToInt16(this.SMBParameters, 31);
+            ChallengeLength = ByteReader.ReadByte(this.SMBParameters, 33);
+
+            ServerGuid = LittleEndianConverter.ToGuid(this.SMBData, 0);
+            SecurityBlob = ByteReader.ReadBytes(this.SMBData, 16, this.SMBData.Length - 16);
         }
 
         public override byte[] GetBytes(bool isUnicode)
         {
-            byte challengeLength = 0;
+            ChallengeLength = 0;
 
             this.SMBParameters = new byte[ParametersLength];
             LittleEndianWriter.WriteUInt16(this.SMBParameters, 0, DialectIndex);
@@ -57,9 +70,9 @@ namespace SMBLibrary.SMB1
             LittleEndianWriter.WriteUInt32(this.SMBParameters, 11, MaxRawSize);
             LittleEndianWriter.WriteUInt32(this.SMBParameters, 15, SessionKey);
             LittleEndianWriter.WriteUInt32(this.SMBParameters, 19, (uint)Capabilities);
-            LittleEndianWriter.WriteInt64(this.SMBParameters, 23, SystemTime.ToFileTimeUtc());
+            FileTimeHelper.WriteFileTime(this.SMBParameters, 23, SystemTime);
             LittleEndianWriter.WriteInt16(this.SMBParameters, 31, ServerTimeZone);
-            ByteWriter.WriteByte(this.SMBParameters, 33, challengeLength);
+            ByteWriter.WriteByte(this.SMBParameters, 33, ChallengeLength);
 
             this.SMBData = new byte[16 + SecurityBlob.Length];
             LittleEndianWriter.WriteGuidBytes(this.SMBData, 0, ServerGuid);

+ 4 - 6
SMBLibrary/SMB1/Commands/SMB1Command.cs

@@ -244,15 +244,13 @@ namespace SMBLibrary.SMB1
                     return new TreeDisconnectResponse(buffer, offset);
                 case CommandName.SMB_COM_NEGOTIATE:
                     {
-                        if (wordCount * 2 == NegotiateResponseNTLM.ParametersLength)
+                        if (wordCount * 2 == NegotiateResponse.ParametersLength)
                         {
-                            throw new NotImplementedException();
-                            //return new NegotiateResponseNTLM(header.UnicodeFlag);
+                            return new NegotiateResponse(buffer, offset, isUnicode);
                         }
-                        else if (wordCount * 2 == NegotiateResponseNTLMExtended.ParametersLength)
+                        else if (wordCount * 2 == NegotiateResponseExtended.ParametersLength)
                         {
-                            throw new NotImplementedException();
-                            //return new NegotiateResponseNTLMExtended(header.UnicodeFlag);
+                            return new NegotiateResponseExtended(buffer, offset);
                         }
                         else
                         {

+ 2 - 2
SMBLibrary/SMBLibrary.csproj

@@ -279,9 +279,9 @@
     <Compile Include="SMB1\Commands\LogoffAndXRequest.cs" />
     <Compile Include="SMB1\Commands\LogoffAndXResponse.cs" />
     <Compile Include="SMB1\Commands\NegotiateRequest.cs" />
+    <Compile Include="SMB1\Commands\NegotiateResponse.cs" />
+    <Compile Include="SMB1\Commands\NegotiateResponseExtended.cs" />
     <Compile Include="SMB1\Commands\NegotiateResponseNotSupported.cs" />
-    <Compile Include="SMB1\Commands\NegotiateResponseNTLM.cs" />
-    <Compile Include="SMB1\Commands\NegotiateResponseNTLMExtended.cs" />
     <Compile Include="SMB1\Commands\NTCreateAndXRequest.cs" />
     <Compile Include="SMB1\Commands\NTCreateAndXResponse.cs" />
     <Compile Include="SMB1\Commands\NTCreateAndXResponseExtended.cs" />

+ 4 - 4
SMBLibrary/Server/SMB1/NegotiateHelper.cs

@@ -19,9 +19,9 @@ namespace SMBLibrary.Server.SMB1
     /// </summary>
     public class NegotiateHelper
     {
-        internal static NegotiateResponseNTLM GetNegotiateResponse(SMB1Header header, NegotiateRequest request, GSSProvider securityProvider, ConnectionState state)
+        internal static NegotiateResponse GetNegotiateResponse(SMB1Header header, NegotiateRequest request, GSSProvider securityProvider, ConnectionState state)
         {
-            NegotiateResponseNTLM response = new NegotiateResponseNTLM();
+            NegotiateResponse response = new NegotiateResponse();
 
             response.DialectIndex = (ushort)request.Dialects.IndexOf(SMBServer.NTLanManagerDialect);
             response.SecurityMode = SecurityMode.UserSecurityMode | SecurityMode.EncryptPasswords;
@@ -51,9 +51,9 @@ namespace SMBLibrary.Server.SMB1
             return response;
         }
 
-        internal static NegotiateResponseNTLMExtended GetNegotiateResponseExtended(NegotiateRequest request, Guid serverGuid)
+        internal static NegotiateResponseExtended GetNegotiateResponseExtended(NegotiateRequest request, Guid serverGuid)
         {
-            NegotiateResponseNTLMExtended response = new NegotiateResponseNTLMExtended();
+            NegotiateResponseExtended response = new NegotiateResponseExtended();
             response.DialectIndex = (ushort)request.Dialects.IndexOf(SMBServer.NTLanManagerDialect);
             response.SecurityMode = SecurityMode.UserSecurityMode | SecurityMode.EncryptPasswords;
             response.MaxMpxCount = 50;