NegotiateRequest: Parse NegotiateContextList (SMB 3.1.1)

This commit is contained in:
Tal Aloni 2024-07-30 20:06:52 +03:00
parent 1aef438a8e
commit e40a5b2daf
2 changed files with 98 additions and 6 deletions

View file

@ -0,0 +1,46 @@
/* Copyright (C) 2024 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,
* either version 3 of the License, or (at your option) any later version.
*/
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SMBLibrary.SMB2;
namespace SMBLibrary.Tests.SMB2
{
[TestClass]
public class NegotiateRequestParsingTests
{
[TestMethod]
public void ParseNegotiateRequestWithNegotiateContextList()
{
byte[] negotiateRequestCommandBytes = new byte[]
{
0xfe,0x53,0x4d,0x42,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0xff,0xfe,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,0x00,0x00,0x00,0x00,0x00,
0x24,0x00,0x05,0x00,0x01,0x00,0x00,0x00,0x7f,0x00,0x00,0x00,0xd2,0xb6,0x2a,0x44,
0x99,0x4d,0xef,0x11,0xb8,0x9d,0x00,0x22,0x48,0x39,0x02,0x34,0x70,0x00,0x00,0x00,
0x04,0x00,0x00,0x00,0x02,0x02,0x10,0x02,0x00,0x03,0x02,0x03,0x11,0x03,0x00,0x00,
0x01,0x00,0x26,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x20,0x00,0x01,0x00,0x6c,0xec,
0x6e,0x4d,0x8e,0x58,0x93,0xd9,0xb3,0x47,0x24,0x09,0x12,0x7a,0xc8,0x4f,0x9b,0xf6,
0x1d,0xaa,0xbc,0xab,0x22,0xf5,0xec,0xf6,0x3d,0xb5,0x3e,0xc3,0x76,0x85,0x00,0x00,
0x02,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x02,0x00,0x01,0x00,0x00,0x00,
0x03,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
0x04,0x00,0x02,0x00,0x03,0x00,0x01,0x00,0x05,0x00,0x34,0x00,0x00,0x00,0x00,0x00,
0x6d,0x00,0x69,0x00,0x72,0x00,0x61,0x00,0x67,0x00,0x65,0x00,0x2d,0x00,0x73,0x00,
0x65,0x00,0x72,0x00,0x76,0x00,0x65,0x00,0x72,0x00,0x34,0x00,0x2e,0x00,0x75,0x00,
0x73,0x00,0x65,0x00,0x72,0x00,0x73,0x00,0x2e,0x00,0x6c,0x00,0x6f,0x00,0x63,0x00,
0x61,0x00,0x6c,0x00
};
NegotiateRequest negotiateRequest = new NegotiateRequest(negotiateRequestCommandBytes, 0);
Assert.AreEqual(5, negotiateRequest.Dialects.Count);
Assert.AreEqual(4, negotiateRequest.NegotiateContextList.Count);
Assert.AreEqual(NegotiateContextType.SMB2_PREAUTH_INTEGRITY_CAPABILITIES, negotiateRequest.NegotiateContextList[0].ContextType);
Assert.AreEqual(NegotiateContextType.SMB2_ENCRYPTION_CAPABILITIES, negotiateRequest.NegotiateContextList[1].ContextType);
}
}
}

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2017 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
/* Copyright (C) 2017-2024 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,
@ -23,8 +23,9 @@ namespace SMBLibrary.SMB2
public ushort Reserved;
public Capabilities Capabilities; // If the client does not implements the SMB 3.x dialect family, this field MUST be set to 0.
public Guid ClientGuid;
public DateTime ClientStartTime;
public DateTime ClientStartTime; // If Dialects does not contain SMB311
public List<SMB2Dialect> Dialects = new List<SMB2Dialect>();
public List<NegotiateContext> NegotiateContextList = new List<NegotiateContext>(); // If Dialects contains SMB311
public NegotiateRequest() : base(SMB2CommandName.Negotiate)
{
@ -39,12 +40,28 @@ namespace SMBLibrary.SMB2
Reserved = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 6);
Capabilities = (Capabilities)LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 8);
ClientGuid = LittleEndianConverter.ToGuid(buffer, offset + SMB2Header.Length + 12);
ClientStartTime = DateTime.FromFileTimeUtc(LittleEndianConverter.ToInt64(buffer, offset + SMB2Header.Length + 28));
bool containsNegotiateContextList = false;
for (int index = 0; index < dialectCount; index++)
{
SMB2Dialect dialect = (SMB2Dialect)LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 36 + index * 2);
Dialects.Add(dialect);
if (dialect == SMB2Dialect.SMB311)
{
containsNegotiateContextList = true;
}
}
if (containsNegotiateContextList)
{
uint negotiateContextOffset = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 28);
ushort NegotiateContextCount = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 32);
NegotiateContextList = NegotiateContext.ReadNegotiateContextList(buffer, offset + (int)negotiateContextOffset, NegotiateContextCount);
}
else
{
ClientStartTime = DateTime.FromFileTimeUtc(LittleEndianConverter.ToInt64(buffer, offset + SMB2Header.Length + 28));
}
}
@ -56,12 +73,31 @@ namespace SMBLibrary.SMB2
LittleEndianWriter.WriteUInt16(buffer, offset + 6, Reserved);
LittleEndianWriter.WriteUInt32(buffer, offset + 8, (uint)Capabilities);
LittleEndianWriter.WriteGuid(buffer, offset + 12, ClientGuid);
LittleEndianWriter.WriteInt64(buffer, offset + 28, ClientStartTime.ToFileTimeUtc());
bool containsNegotiateContextList = false;
for (int index = 0; index < Dialects.Count; index++)
{
SMB2Dialect dialect = Dialects[index];
LittleEndianWriter.WriteUInt16(buffer, offset + 36 + index * 2, (ushort)dialect);
if (dialect == SMB2Dialect.SMB311)
{
containsNegotiateContextList = true;
}
}
int paddingLength = (8 - ((36 + Dialects.Count * 2) % 8)) % 8;
if (containsNegotiateContextList)
{
uint negotiateContextOffset = (uint)(SMB2Header.Length + 36 + Dialects.Count * 2 + paddingLength);
ushort negotiateContextCount = (ushort)NegotiateContextList.Count;
LittleEndianWriter.WriteUInt32(buffer, offset + 28, negotiateContextOffset);
LittleEndianWriter.WriteUInt16(buffer, offset + 32, negotiateContextCount);
NegotiateContext.WriteNegotiateContextList(buffer, offset - SMB2Header.Length + (int)negotiateContextOffset, NegotiateContextList);
}
else
{
LittleEndianWriter.WriteInt64(buffer, offset + 28, ClientStartTime.ToFileTimeUtc());
}
}
@ -69,7 +105,17 @@ namespace SMBLibrary.SMB2
{
get
{
return 36 + Dialects.Count * 2;
bool containsNegotiateContextList = Dialects.Contains(SMB2Dialect.SMB311);
if (containsNegotiateContextList)
{
int paddingLength = (8 - ((36 + Dialects.Count * 2) % 8)) % 8;
int negotiateContextListLength = NegotiateContext.GetNegotiateContextListLength(NegotiateContextList);
return 36 + Dialects.Count * 2 + paddingLength + negotiateContextListLength;
}
else
{
return 36 + Dialects.Count * 2;
}
}
}
}