Added SMB2 command structures and enums

This commit is contained in:
Tal Aloni 2017-01-20 17:25:57 +02:00
parent d5b73a8f9d
commit 966096df5f
67 changed files with 3701 additions and 0 deletions

View file

@ -0,0 +1,48 @@
/* Copyright (C) 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,
* either version 3 of the License, or (at your option) any later version.
*/
using System;
using System.Collections.Generic;
using Utilities;
namespace SMBLibrary.SMB2
{
/// <summary>
/// SMB2 CANCEL Request
/// </summary>
public class CancelRequest : SMB2Command
{
public const int DeclaredSize = 4;
public ushort StructureSize;
public ushort Reserved;
public CancelRequest() : base(SMB2CommandName.Cancel)
{
StructureSize = DeclaredSize;
}
public CancelRequest(byte[] buffer, int offset) : base(buffer, offset)
{
StructureSize = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 0);
Reserved = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 2);
}
public override void WriteCommandBytes(byte[] buffer, int offset)
{
LittleEndianWriter.WriteUInt16(buffer, offset + 0, StructureSize);
LittleEndianWriter.WriteUInt16(buffer, offset + 2, Reserved);
}
public override int CommandLength
{
get
{
return DeclaredSize;
}
}
}
}

View file

@ -0,0 +1,60 @@
/* Copyright (C) 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,
* either version 3 of the License, or (at your option) any later version.
*/
using System;
using System.Collections.Generic;
using Utilities;
namespace SMBLibrary.SMB2
{
/// <summary>
/// SMB2 CHANGE_NOTIFY Request
/// </summary>
public class ChangeNotifyRequest : SMB2Command
{
public const int DeclaredSize = 32;
public ushort StructureSize;
public ChangeNotifyFlags Flags;
public uint OutputBufferLength;
public FileID FileId;
public NotifyChange CompletionFilter;
public uint Reserved;
public ChangeNotifyRequest() : base(SMB2CommandName.ChangeNotify)
{
StructureSize = DeclaredSize;
}
public ChangeNotifyRequest(byte[] buffer, int offset) : base(buffer, offset)
{
StructureSize = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 0);
Flags = (ChangeNotifyFlags)LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 2);
OutputBufferLength = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 4);
FileId = new FileID(buffer, offset + SMB2Header.Length + 8);
CompletionFilter = (NotifyChange)LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 24);
Reserved = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 28);
}
public override void WriteCommandBytes(byte[] buffer, int offset)
{
LittleEndianWriter.WriteUInt16(buffer, offset + 0, StructureSize);
LittleEndianWriter.WriteUInt16(buffer, offset + 2, (ushort)Flags);
LittleEndianWriter.WriteUInt32(buffer, offset + 4, OutputBufferLength);
FileId.WriteBytes(buffer, offset + 8);
LittleEndianWriter.WriteUInt32(buffer, offset + 24, (uint)CompletionFilter);
LittleEndianWriter.WriteUInt32(buffer, offset + 28, Reserved);
}
public override int CommandLength
{
get
{
return DeclaredSize;
}
}
}
}

View file

@ -0,0 +1,62 @@
/* Copyright (C) 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,
* either version 3 of the License, or (at your option) any later version.
*/
using System;
using System.Collections.Generic;
using Utilities;
namespace SMBLibrary.SMB2
{
/// <summary>
/// SMB2 CHANGE_NOTIFY Response
/// </summary>
public class ChangeNotifyResponse : SMB2Command
{
public const int FixedSize = 8;
public const int DeclaredSize = 9;
public ushort StructureSize;
private ushort OutputBufferOffset;
private uint OutputBufferLength;
public byte[] OutputBuffer = new byte[0];
public ChangeNotifyResponse() : base(SMB2CommandName.ChangeNotify)
{
Header.IsResponse = true;
StructureSize = DeclaredSize;
}
public ChangeNotifyResponse(byte[] buffer, int offset) : base(buffer, offset)
{
StructureSize = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 0);
OutputBufferOffset = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 2);
OutputBufferLength = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 4);
OutputBuffer = ByteReader.ReadBytes(buffer, offset + OutputBufferOffset, (int)OutputBufferLength);
}
public override void WriteCommandBytes(byte[] buffer, int offset)
{
OutputBufferOffset = 0;
OutputBufferLength = (uint)OutputBuffer.Length;
if (OutputBuffer.Length > 0)
{
OutputBufferOffset = SMB2Header.Length + FixedSize;
}
LittleEndianWriter.WriteUInt16(buffer, offset + 0, StructureSize);
LittleEndianWriter.WriteUInt16(buffer, offset + 2, OutputBufferOffset);
LittleEndianWriter.WriteUInt32(buffer, offset + 4, OutputBufferLength);
ByteWriter.WriteBytes(buffer, offset + FixedSize, OutputBuffer);
}
public override int CommandLength
{
get
{
return FixedSize + OutputBuffer.Length;
}
}
}
}

View file

@ -0,0 +1,54 @@
/* Copyright (C) 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,
* either version 3 of the License, or (at your option) any later version.
*/
using System;
using System.Collections.Generic;
using Utilities;
namespace SMBLibrary.SMB2
{
/// <summary>
/// SMB2 CLOSE Request
/// </summary>
public class CloseRequest : SMB2Command
{
public const int DeclaredSize = 24;
public ushort StructureSize;
public CloseFlags Flags;
public uint Reserved;
public FileID FileId;
public CloseRequest() : base(SMB2CommandName.Close)
{
StructureSize = DeclaredSize;
}
public CloseRequest(byte[] buffer, int offset) : base(buffer, offset)
{
StructureSize = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 0);
Flags = (CloseFlags)LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 2);
Reserved = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 4);
FileId = new FileID(buffer, offset + SMB2Header.Length + 8);
}
public override void WriteCommandBytes(byte[] buffer, int offset)
{
LittleEndianWriter.WriteUInt16(buffer, offset + 0, StructureSize);
LittleEndianWriter.WriteUInt16(buffer, offset + 2, (ushort)Flags);
LittleEndianWriter.WriteUInt32(buffer, offset + 4, Reserved);
FileId.WriteBytes(buffer, offset + 8);
}
public override int CommandLength
{
get
{
return DeclaredSize;
}
}
}
}

View file

@ -0,0 +1,73 @@
/* Copyright (C) 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,
* either version 3 of the License, or (at your option) any later version.
*/
using System;
using System.Collections.Generic;
using Utilities;
namespace SMBLibrary.SMB2
{
/// <summary>
/// SMB2 CLOSE Response
/// </summary>
public class CloseResponse : SMB2Command
{
public const int DeclaredSize = 60;
public ushort StructureSize;
public CloseFlags Flags;
public uint Reserved;
public DateTime? CreationTime;
public DateTime? LastAccessTime;
public DateTime? LastWriteTime;
public DateTime? ChangeTime;
public ulong AllocationSize;
public ulong EndofFile;
public FileAttributes FileAttributes;
public CloseResponse() : base(SMB2CommandName.Close)
{
Header.IsResponse = true;
StructureSize = DeclaredSize;
}
public CloseResponse(byte[] buffer, int offset) : base(buffer, offset)
{
StructureSize = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 0);
Flags = (CloseFlags)LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 2);
Reserved = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 4);
CreationTime = FileTimeHelper.ReadNullableFileTime(buffer, offset + SMB2Header.Length + 8);
LastAccessTime = FileTimeHelper.ReadNullableFileTime(buffer, offset + SMB2Header.Length + 16);
LastWriteTime = FileTimeHelper.ReadNullableFileTime(buffer, offset + SMB2Header.Length + 24);
ChangeTime = FileTimeHelper.ReadNullableFileTime(buffer, offset + SMB2Header.Length + 32);
AllocationSize = LittleEndianConverter.ToUInt64(buffer, offset + SMB2Header.Length + 40);
EndofFile = LittleEndianConverter.ToUInt64(buffer, offset + SMB2Header.Length + 48);
FileAttributes = (FileAttributes)LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 56);
}
public override void WriteCommandBytes(byte[] buffer, int offset)
{
LittleEndianWriter.WriteUInt16(buffer, offset + 0, StructureSize);
LittleEndianWriter.WriteUInt16(buffer, offset + 2, (ushort)Flags);
LittleEndianWriter.WriteUInt32(buffer, offset + 4, Reserved);
FileTimeHelper.WriteFileTime(buffer, offset + 8, CreationTime);
FileTimeHelper.WriteFileTime(buffer, offset + 16, LastAccessTime);
FileTimeHelper.WriteFileTime(buffer, offset + 24, LastWriteTime);
FileTimeHelper.WriteFileTime(buffer, offset + 32, ChangeTime);
LittleEndianWriter.WriteUInt64(buffer, offset + 40, AllocationSize);
LittleEndianWriter.WriteUInt64(buffer, offset + 48, EndofFile);
LittleEndianWriter.WriteUInt32(buffer, offset + 56, (uint)FileAttributes);
}
public override int CommandLength
{
get
{
return DeclaredSize;
}
}
}
}

View file

@ -0,0 +1,119 @@
/* Copyright (C) 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,
* either version 3 of the License, or (at your option) any later version.
*/
using System;
using System.Collections.Generic;
using Utilities;
namespace SMBLibrary.SMB2
{
/// <summary>
/// SMB2 LOGOFF Request
/// </summary>
public class CreateRequest : SMB2Command
{
public const int FixedLength = 56;
public const int DeclaredSize = 57;
public ushort StructureSize;
public byte SecurityFlags; // Reserved
public OplockLevel RequestedOplockLevel;
public ImpersonationLevel ImpersonationLevel;
public ulong SmbCreateFlags;
public ulong Reserved;
public AccessMask DesiredAccess;
public FileAttributes FileAttributes;
public ShareAccess ShareAccess;
public CreateDisposition CreateDisposition;
public CreateOptions CreateOptions;
private ushort NameOffset;
private ushort NameLength;
public string Name;
private uint CreateContextsOffsets;
private uint CreateContextsLength;
public List<CreateContext> CreateContexts = new List<CreateContext>();
public CreateRequest() : base(SMB2CommandName.Create)
{
StructureSize = DeclaredSize;
}
public CreateRequest(byte[] buffer, int offset) : base(buffer, offset)
{
StructureSize = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 0);
SecurityFlags = ByteReader.ReadByte(buffer, offset + SMB2Header.Length + 2);
RequestedOplockLevel = (OplockLevel)ByteReader.ReadByte(buffer, offset + SMB2Header.Length + 3);
ImpersonationLevel = (ImpersonationLevel)LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 4);
SmbCreateFlags = LittleEndianConverter.ToUInt64(buffer, offset + SMB2Header.Length + 8);
Reserved = LittleEndianConverter.ToUInt64(buffer, offset + SMB2Header.Length + 16);
DesiredAccess = new AccessMask(buffer, offset + SMB2Header.Length + 24);
FileAttributes = (FileAttributes)LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 28);
ShareAccess = (ShareAccess)LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 32);
CreateDisposition = (CreateDisposition)LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 36);
CreateOptions = (CreateOptions)LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 40);
NameOffset = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 44);
NameLength = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 46);
CreateContextsOffsets = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 48);
CreateContextsLength = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 52);
Name = ByteReader.ReadUTF16String(buffer, offset + NameOffset, NameLength / 2);
if (CreateContextsLength > 0)
{
CreateContexts = CreateContext.ReadCreateContextList(buffer, (int)CreateContextsOffsets);
}
}
public override void WriteCommandBytes(byte[] buffer, int offset)
{
NameOffset = 0;
NameLength = (ushort)(Name.Length * 2);
if (Name.Length > 0)
{
NameOffset = SMB2Header.Length + FixedLength;
}
CreateContextsOffsets = 0;
CreateContextsLength = 0;
int paddedNameLength = (int)Math.Ceiling((double)(Name.Length * 2) / 8) * 8;
if (CreateContexts.Count > 0)
{
CreateContextsOffsets = (uint)(SMB2Header.Length + 56 + paddedNameLength);
CreateContextsLength = (uint)CreateContext.GetCreateContextListLength(CreateContexts);
}
LittleEndianWriter.WriteUInt16(buffer, offset + 0, StructureSize);
ByteWriter.WriteByte(buffer, offset + 2, SecurityFlags);
ByteWriter.WriteByte(buffer, offset + 3, (byte)RequestedOplockLevel);
LittleEndianWriter.WriteUInt32(buffer, offset + 4, (uint)ImpersonationLevel);
LittleEndianWriter.WriteUInt64(buffer, offset + 8, (ulong)SmbCreateFlags);
LittleEndianWriter.WriteUInt64(buffer, offset + 16, (ulong)Reserved);
DesiredAccess.WriteBytes(buffer, offset + 24);
LittleEndianWriter.WriteUInt32(buffer, offset + 28, (uint)FileAttributes);
LittleEndianWriter.WriteUInt32(buffer, offset + 32, (uint)ShareAccess);
LittleEndianWriter.WriteUInt32(buffer, offset + 36, (uint)CreateDisposition);
LittleEndianWriter.WriteUInt32(buffer, offset + 40, (uint)CreateOptions);
LittleEndianWriter.WriteUInt16(buffer, offset + 44, NameOffset);
LittleEndianWriter.WriteUInt16(buffer, offset + 46, NameLength);
LittleEndianWriter.WriteUInt32(buffer, offset + 48, CreateContextsOffsets);
LittleEndianWriter.WriteUInt32(buffer, offset + 52, CreateContextsLength);
ByteWriter.WriteUTF16String(buffer, offset + 56, Name);
CreateContext.WriteCreateContextList(buffer, offset + 56 + paddedNameLength, CreateContexts);
}
public override int CommandLength
{
get
{
if (CreateContexts.Count == 0)
{
return FixedLength + Name.Length * 2;
}
else
{
int paddedNameLength = (int)Math.Ceiling((double)(Name.Length * 2) / 8) * 8;
return FixedLength + paddedNameLength + CreateContext.GetCreateContextListLength(CreateContexts);
}
}
}
}
}

View file

@ -0,0 +1,98 @@
/* Copyright (C) 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,
* either version 3 of the License, or (at your option) any later version.
*/
using System;
using System.Collections.Generic;
using Utilities;
namespace SMBLibrary.SMB2
{
/// <summary>
/// SMB2 CREATE Response
/// </summary>
public class CreateResponse : SMB2Command
{
public const int DeclaredSize = 89;
public ushort StructureSize;
public OplockLevel OplockLevel;
public CreateResponseFlags Flags;
public CreateAction CreateAction;
public DateTime? CreationTime;
public DateTime? LastAccessTime;
public DateTime? LastWriteTime;
public DateTime? ChangeTime;
public ulong AllocationSize;
public ulong EndofFile;
public FileAttributes FileAttributes;
public uint Reserved2;
public FileID FileId;
private uint CreateContextsOffsets;
private uint CreateContextsLength;
public List<CreateContext> CreateContexts = new List<CreateContext>();
public CreateResponse() : base(SMB2CommandName.Create)
{
Header.IsResponse = true;
StructureSize = DeclaredSize;
}
public CreateResponse(byte[] buffer, int offset) : base(buffer, offset)
{
StructureSize = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 0);
OplockLevel = (OplockLevel)ByteReader.ReadByte(buffer, offset + SMB2Header.Length + 2);
Flags = (CreateResponseFlags)ByteReader.ReadByte(buffer, offset + SMB2Header.Length + 3);
CreateAction = (CreateAction)LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 4);
CreationTime = FileTimeHelper.ReadNullableFileTime(buffer, offset + SMB2Header.Length + 8);
LastAccessTime = FileTimeHelper.ReadNullableFileTime(buffer, offset + SMB2Header.Length + 16);
LastWriteTime = FileTimeHelper.ReadNullableFileTime(buffer, offset + SMB2Header.Length + 24);
ChangeTime = FileTimeHelper.ReadNullableFileTime(buffer, offset + SMB2Header.Length + 32);
AllocationSize = LittleEndianConverter.ToUInt64(buffer, offset + SMB2Header.Length + 40);
EndofFile = LittleEndianConverter.ToUInt64(buffer, offset + SMB2Header.Length + 48);
FileAttributes = (FileAttributes)LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 56);
Reserved2 = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 60);
FileId = new FileID(buffer, offset + SMB2Header.Length + 64);
CreateContextsOffsets = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 80);
CreateContextsLength = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 84);
if (CreateContextsLength > 0)
{
CreateContexts = CreateContext.ReadCreateContextList(buffer, offset + (int)CreateContextsOffsets);
}
}
public override void WriteCommandBytes(byte[] buffer, int offset)
{
LittleEndianWriter.WriteUInt16(buffer, offset + 0, StructureSize);
ByteWriter.WriteByte(buffer, offset + 2, (byte)OplockLevel);
ByteWriter.WriteByte(buffer, offset + 3, (byte)Flags);
LittleEndianWriter.WriteUInt32(buffer, offset + 4, (uint)CreateAction);
FileTimeHelper.WriteFileTime(buffer, offset + 8, CreationTime);
FileTimeHelper.WriteFileTime(buffer, offset + 16, LastAccessTime);
FileTimeHelper.WriteFileTime(buffer, offset + 24, LastWriteTime);
FileTimeHelper.WriteFileTime(buffer, offset + 32, ChangeTime);
LittleEndianWriter.WriteUInt64(buffer, offset + 40, AllocationSize);
LittleEndianWriter.WriteUInt64(buffer, offset + 48, EndofFile);
LittleEndianWriter.WriteUInt32(buffer, offset + 56, (uint)FileAttributes);
LittleEndianWriter.WriteUInt32(buffer, offset + 60, Reserved2);
FileId.WriteBytes(buffer, offset + 64);
CreateContextsOffsets = 0;
CreateContextsLength = (uint)CreateContext.GetCreateContextListLength(CreateContexts);
if (CreateContexts.Count > 0)
{
CreateContextsOffsets = SMB2Header.Length + 88;
CreateContext.WriteCreateContextList(buffer, 88, CreateContexts);
}
}
public override int CommandLength
{
get
{
return 88 + CreateContext.GetCreateContextListLength(CreateContexts);
}
}
}
}

View file

@ -0,0 +1,48 @@
/* Copyright (C) 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,
* either version 3 of the License, or (at your option) any later version.
*/
using System;
using System.Collections.Generic;
using Utilities;
namespace SMBLibrary.SMB2
{
/// <summary>
/// SMB2 ECHO Request
/// </summary>
public class EchoRequest : SMB2Command
{
public const int DeclaredSize = 4;
public ushort StructureSize;
public ushort Reserved;
public EchoRequest() : base(SMB2CommandName.Echo)
{
StructureSize = DeclaredSize;
}
public EchoRequest(byte[] buffer, int offset) : base(buffer, offset)
{
StructureSize = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 0);
Reserved = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 2);
}
public override void WriteCommandBytes(byte[] buffer, int offset)
{
LittleEndianWriter.WriteUInt16(buffer, offset + 0, StructureSize);
LittleEndianWriter.WriteUInt16(buffer, offset + 2, Reserved);
}
public override int CommandLength
{
get
{
return DeclaredSize;
}
}
}
}

View file

@ -0,0 +1,49 @@
/* Copyright (C) 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,
* either version 3 of the License, or (at your option) any later version.
*/
using System;
using System.Collections.Generic;
using Utilities;
namespace SMBLibrary.SMB2
{
/// <summary>
/// SMB2 ECHO Response
/// </summary>
public class EchoResponse : SMB2Command
{
public const int DeclaredSize = 4;
public ushort StructureSize;
public ushort Reserved;
public EchoResponse() : base(SMB2CommandName.Echo)
{
Header.IsResponse = true;
StructureSize = DeclaredSize;
}
public EchoResponse(byte[] buffer, int offset) : base(buffer, offset)
{
StructureSize = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 0);
Reserved = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 2);
}
public override void WriteCommandBytes(byte[] buffer, int offset)
{
LittleEndianWriter.WriteUInt16(buffer, offset + 0, StructureSize);
LittleEndianWriter.WriteUInt16(buffer, offset + 2, Reserved);
}
public override int CommandLength
{
get
{
return DeclaredSize;
}
}
}
}

View file

@ -0,0 +1,77 @@
/* Copyright (C) 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,
* either version 3 of the License, or (at your option) any later version.
*/
using System;
using System.Collections.Generic;
using Utilities;
namespace SMBLibrary.SMB2
{
/// <summary>
/// SMB2 ERROR Response
/// </summary>
public class ErrorResponse : SMB2Command
{
public const int FixedSize = 8;
public const int DeclaredSize = 9;
public ushort StructureSize;
public byte ErrorContextCount;
public byte Reserved;
private uint ByteCount;
public byte[] ErrorData = new byte[0];
public ErrorResponse(SMB2CommandName commandName) : base(commandName)
{
Header.IsResponse = true;
StructureSize = DeclaredSize;
}
public ErrorResponse(SMB2CommandName commandName, NTStatus status) : base(commandName)
{
Header.IsResponse = true;
Header.Status = status;
StructureSize = DeclaredSize;
}
public ErrorResponse(byte[] buffer, int offset) : base(buffer, offset)
{
StructureSize = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 0);
ErrorContextCount = ByteReader.ReadByte(buffer, offset + SMB2Header.Length + 2);
Reserved = ByteReader.ReadByte(buffer, offset + SMB2Header.Length + 3);
ByteCount = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 4);
ErrorData = ByteReader.ReadBytes(buffer, offset + SMB2Header.Length + 8, (int)ByteCount);
}
public override void WriteCommandBytes(byte[] buffer, int offset)
{
ByteCount = (uint)ErrorData.Length;
LittleEndianWriter.WriteUInt16(buffer, offset + 0, StructureSize);
ByteWriter.WriteByte(buffer, offset + 2, ErrorContextCount);
ByteWriter.WriteByte(buffer, offset + 3, Reserved);
LittleEndianWriter.WriteUInt32(buffer, offset + 4, ByteCount);
if (ErrorData.Length > 0)
{
ByteWriter.WriteBytes(buffer, offset + 8, ErrorData);
}
else
{
// If the ByteCount field is zero then the server MUST supply an ErrorData field that is one byte in length, and SHOULD set that byte to zero
ByteWriter.WriteBytes(buffer, offset + 8, new byte[1]);
}
}
public override int CommandLength
{
get
{
// If the ByteCount field is zero then the server MUST supply an ErrorData field that is one byte in length
return FixedSize + Math.Max(ErrorData.Length, 1);
}
}
}
}

View file

@ -0,0 +1,54 @@
/* Copyright (C) 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,
* either version 3 of the License, or (at your option) any later version.
*/
using System;
using System.Collections.Generic;
using Utilities;
namespace SMBLibrary.SMB2
{
/// <summary>
/// SMB2 FLUSH Request
/// </summary>
public class FlushRequest : SMB2Command
{
public const int DeclaredSize = 24;
public ushort StructureSize;
public ushort Reserved1;
public uint Reserved2;
public FileID FileId;
public FlushRequest() : base(SMB2CommandName.Flush)
{
StructureSize = DeclaredSize;
}
public FlushRequest(byte[] buffer, int offset) : base(buffer, offset)
{
StructureSize = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 0);
Reserved1 = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 2);
Reserved2 = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 4);
FileId = new FileID(buffer, offset + SMB2Header.Length + 8);
}
public override void WriteCommandBytes(byte[] buffer, int offset)
{
LittleEndianWriter.WriteUInt16(buffer, offset + 0, StructureSize);
LittleEndianWriter.WriteUInt16(buffer, offset + 2, Reserved1);
LittleEndianWriter.WriteUInt32(buffer, offset + 4, Reserved2);
FileId.WriteBytes(buffer, offset + 8);
}
public override int CommandLength
{
get
{
return DeclaredSize;
}
}
}
}

View file

@ -0,0 +1,49 @@
/* Copyright (C) 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,
* either version 3 of the License, or (at your option) any later version.
*/
using System;
using System.Collections.Generic;
using Utilities;
namespace SMBLibrary.SMB2
{
/// <summary>
/// SMB2 FLUSH Response
/// </summary>
public class FlushResponse : SMB2Command
{
public const int DeclaredSize = 4;
public ushort StructureSize;
public ushort Reserved;
public FlushResponse() : base(SMB2CommandName.Flush)
{
Header.IsResponse = true;
StructureSize = DeclaredSize;
}
public FlushResponse(byte[] buffer, int offset) : base(buffer, offset)
{
StructureSize = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 0);
Reserved = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 2);
}
public override void WriteCommandBytes(byte[] buffer, int offset)
{
LittleEndianWriter.WriteUInt16(buffer, offset + 0, StructureSize);
LittleEndianWriter.WriteUInt16(buffer, offset + 2, Reserved);
}
public override int CommandLength
{
get
{
return DeclaredSize;
}
}
}
}

View file

@ -0,0 +1,122 @@
/* Copyright (C) 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,
* either version 3 of the License, or (at your option) any later version.
*/
using System;
using System.Collections.Generic;
using Utilities;
namespace SMBLibrary.SMB2
{
/// <summary>
/// SMB2 IOCTL Request
/// </summary>
public class IOCtlRequest : SMB2Command
{
public const int FixedLength = 56;
public const int DeclaredSize = 57;
public ushort StructureSize;
public ushort Reserved;
public uint CtlCode;
public FileID FileId;
private uint InputOffset;
private uint InputCount;
public uint MaxInputResponse;
private uint OutputOffset;
private uint OutputCount;
public uint MaxOutputResponse;
public IOCtlRequestFlags Flags;
public uint Reserved2;
public byte[] Input = new byte[0];
public byte[] Output = new byte[0];
public IOCtlRequest() : base(SMB2CommandName.IOCtl)
{
StructureSize = DeclaredSize;
}
public IOCtlRequest(byte[] buffer, int offset) : base(buffer, offset)
{
StructureSize = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 0);
Reserved = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 2);
CtlCode = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 4);
FileId = new FileID(buffer, offset + SMB2Header.Length + 8);
InputOffset = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 24);
InputCount = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 28);
MaxInputResponse = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 32);
OutputOffset = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 36);
OutputCount = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 40);
MaxOutputResponse = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 44);
Flags = (IOCtlRequestFlags)LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 48);
Reserved2 = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 52);
Input = ByteReader.ReadBytes(buffer, offset + (int)InputOffset, (int)InputCount);
Output = ByteReader.ReadBytes(buffer, offset + (int)OutputOffset, (int)OutputCount);
}
public override void WriteCommandBytes(byte[] buffer, int offset)
{
InputOffset = 0;
InputCount = (uint)Input.Length;
OutputOffset = 0;
OutputCount = (uint)Output.Length;
if (Input.Length > 0)
{
InputOffset = SMB2Header.Length + FixedLength;
}
if (Output.Length > 0)
{
OutputOffset = InputOffset + (uint)Input.Length;
}
LittleEndianWriter.WriteUInt16(buffer, offset + 0, StructureSize);
LittleEndianWriter.WriteUInt16(buffer, offset + 2, Reserved);
LittleEndianWriter.WriteUInt32(buffer, offset + 4, CtlCode);
FileId.WriteBytes(buffer, offset + 8);
LittleEndianWriter.WriteUInt32(buffer, offset + 24, InputOffset);
LittleEndianWriter.WriteUInt32(buffer, offset + 28, InputCount);
LittleEndianWriter.WriteUInt32(buffer, offset + 32, MaxInputResponse);
LittleEndianWriter.WriteUInt32(buffer, offset + 36, OutputOffset);
LittleEndianWriter.WriteUInt32(buffer, offset + 40, OutputCount);
LittleEndianWriter.WriteUInt32(buffer, offset + 44, MaxOutputResponse);
LittleEndianWriter.WriteUInt32(buffer, offset + 48, (uint)Flags);
LittleEndianWriter.WriteUInt32(buffer, offset + 52, Reserved2);
if (Input.Length > 0)
{
ByteWriter.WriteBytes(buffer, offset + FixedLength, Input);
}
if (Output.Length > 0)
{
ByteWriter.WriteBytes(buffer, offset + FixedLength + Input.Length, Output);
}
}
public bool IsFSCtl
{
get
{
return (Flags & IOCtlRequestFlags.IsFSCtl) > 0;
}
set
{
if (value)
{
Flags |= IOCtlRequestFlags.IsFSCtl;
}
else
{
Flags &= ~IOCtlRequestFlags.IsFSCtl;
}
}
}
public override int CommandLength
{
get
{
return FixedLength + Input.Length + Output.Length;
}
}
}
}

View file

@ -0,0 +1,101 @@
/* Copyright (C) 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,
* either version 3 of the License, or (at your option) any later version.
*/
using System;
using System.Collections.Generic;
using Utilities;
namespace SMBLibrary.SMB2
{
/// <summary>
/// SMB2 IOCTL Request
/// </summary>
public class IOCtlResponse : SMB2Command
{
public const int FixedLength = 48;
public const int DeclaredSize = 49;
public ushort StructureSize;
public ushort Reserved;
public uint CtlCode;
public FileID FileId;
private uint InputOffset;
private uint InputCount;
private uint OutputOffset;
private uint OutputCount;
public uint Flags;
public uint Reserved2;
public byte[] Input = new byte[0];
public byte[] Output = new byte[0];
public IOCtlResponse() : base(SMB2CommandName.IOCtl)
{
Header.IsResponse = true;
StructureSize = DeclaredSize;
}
public IOCtlResponse(byte[] buffer, int offset) : base(buffer, offset)
{
StructureSize = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 0);
Reserved = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 2);
CtlCode = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 4);
FileId = new FileID(buffer, offset + SMB2Header.Length + 8);
InputOffset = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 24);
InputCount = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 28);
OutputOffset = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 32);
OutputCount = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 36);
Flags = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 40);
Reserved2 = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 44);
Input = ByteReader.ReadBytes(buffer, offset + (int)InputOffset, (int)InputCount);
Output = ByteReader.ReadBytes(buffer, offset + (int)OutputOffset, (int)OutputCount);
}
public override void WriteCommandBytes(byte[] buffer, int offset)
{
InputOffset = 0;
InputCount = (uint)Input.Length;
OutputOffset = 0;
OutputCount = (uint)Output.Length;
if (Input.Length > 0)
{
InputOffset = SMB2Header.Length + FixedLength;
}
// MS-SMB2: the output offset MUST be set to InputOffset + InputCount rounded up to a multiple of 8
int paddedInputLength = (int)Math.Ceiling((double)Input.Length / 8) * 8;
if (Output.Length > 0)
{
OutputOffset = SMB2Header.Length + FixedLength + (uint)paddedInputLength;
}
LittleEndianWriter.WriteUInt16(buffer, offset + 0, StructureSize);
LittleEndianWriter.WriteUInt16(buffer, offset + 2, Reserved);
LittleEndianWriter.WriteUInt32(buffer, offset + 4, CtlCode);
FileId.WriteBytes(buffer, offset + 8);
LittleEndianWriter.WriteUInt32(buffer, offset + 24, InputOffset);
LittleEndianWriter.WriteUInt32(buffer, offset + 28, InputCount);
LittleEndianWriter.WriteUInt32(buffer, offset + 32, OutputOffset);
LittleEndianWriter.WriteUInt32(buffer, offset + 36, OutputCount);
LittleEndianWriter.WriteUInt32(buffer, offset + 40, Flags);
LittleEndianWriter.WriteUInt32(buffer, offset + 44, Reserved2);
if (Input.Length > 0)
{
ByteWriter.WriteBytes(buffer, offset + FixedLength, Input);
}
if (Output.Length > 0)
{
ByteWriter.WriteBytes(buffer, offset + FixedLength + paddedInputLength, Output);
}
}
public override int CommandLength
{
get
{
int paddedInputLength = (int)Math.Ceiling((double)Input.Length / 8) * 8;
return FixedLength + paddedInputLength + Output.Length;
}
}
}
}

View file

@ -0,0 +1,60 @@
/* Copyright (C) 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,
* either version 3 of the License, or (at your option) any later version.
*/
using System;
using System.Collections.Generic;
using Utilities;
namespace SMBLibrary.SMB2
{
/// <summary>
/// SMB2 LOCK Request
/// </summary>
public class LockRequest : SMB2Command
{
public const int DeclaredSize = 48;
public ushort StructureSize;
public ushort LockCount;
public byte LSN; // 4 bits
public uint LockSequenceIndex; // 28 bits
public FileID FileId;
public List<LockElement> Locks;
public LockRequest() : base(SMB2CommandName.Lock)
{
StructureSize = DeclaredSize;
}
public LockRequest(byte[] buffer, int offset) : base(buffer, offset)
{
StructureSize = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 0);
LockCount = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 2);
uint temp = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 4);
LSN = (byte)(temp >> 28);
LockSequenceIndex = (temp & 0x0FFFFFFF);
FileId = new FileID(buffer, offset + SMB2Header.Length + 8);
Locks = LockElement.ReadLockList(buffer, offset + SMB2Header.Length + 24, (int)LockCount);
}
public override void WriteCommandBytes(byte[] buffer, int offset)
{
LittleEndianWriter.WriteUInt16(buffer, offset + 0, StructureSize);
LittleEndianWriter.WriteUInt16(buffer, offset + 2, LockCount);
LittleEndianWriter.WriteUInt32(buffer, offset + 4, (uint)(LSN & 0x0F) << 28 | (uint)(LockSequenceIndex & 0x0FFFFFFF));
FileId.WriteBytes(buffer, offset + 8);
LockElement.WriteLockList(buffer, offset + 24, Locks);
}
public override int CommandLength
{
get
{
return 48 + Locks.Count * LockElement.StructureLength;
}
}
}
}

View file

@ -0,0 +1,49 @@
/* Copyright (C) 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,
* either version 3 of the License, or (at your option) any later version.
*/
using System;
using System.Collections.Generic;
using Utilities;
namespace SMBLibrary.SMB2
{
/// <summary>
/// SMB2 LOCK Response
/// </summary>
public class LockResponse : SMB2Command
{
public const int DeclaredSize = 4;
public ushort StructureSize;
public ushort Reserved;
public LockResponse() : base(SMB2CommandName.Lock)
{
Header.IsResponse = true;
StructureSize = DeclaredSize;
}
public LockResponse(byte[] buffer, int offset) : base(buffer, offset)
{
StructureSize = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 0);
Reserved = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 2);
}
public override void WriteCommandBytes(byte[] buffer, int offset)
{
LittleEndianWriter.WriteUInt16(buffer, offset + 0, StructureSize);
LittleEndianWriter.WriteUInt16(buffer, offset + 2, Reserved);
}
public override int CommandLength
{
get
{
return DeclaredSize;
}
}
}
}

View file

@ -0,0 +1,48 @@
/* Copyright (C) 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,
* either version 3 of the License, or (at your option) any later version.
*/
using System;
using System.Collections.Generic;
using Utilities;
namespace SMBLibrary.SMB2
{
/// <summary>
/// SMB2 LOGOFF Request
/// </summary>
public class LogoffRequest : SMB2Command
{
public const int DeclaredSize = 4;
public ushort StructureSize;
public ushort Reserved;
public LogoffRequest() : base(SMB2CommandName.Logoff)
{
StructureSize = 4;
}
public LogoffRequest(byte[] buffer, int offset) : base(buffer, offset)
{
StructureSize = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 0);
Reserved = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 2);
}
public override void WriteCommandBytes(byte[] buffer, int offset)
{
LittleEndianWriter.WriteUInt16(buffer, offset + 0, StructureSize);
LittleEndianWriter.WriteUInt16(buffer, offset + 2, Reserved);
}
public override int CommandLength
{
get
{
return DeclaredSize;
}
}
}
}

View file

@ -0,0 +1,49 @@
/* Copyright (C) 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,
* either version 3 of the License, or (at your option) any later version.
*/
using System;
using System.Collections.Generic;
using Utilities;
namespace SMBLibrary.SMB2
{
/// <summary>
/// SMB2 LOGOFF Response
/// </summary>
public class LogoffResponse : SMB2Command
{
public const int DeclaredSize = 4;
public ushort StructureSize;
public ushort Reserved;
public LogoffResponse() : base(SMB2CommandName.Logoff)
{
Header.IsResponse = true;
StructureSize = 4;
}
public LogoffResponse(byte[] buffer, int offset) : base(buffer, offset)
{
StructureSize = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 0);
Reserved = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 2);
}
public override void WriteCommandBytes(byte[] buffer, int offset)
{
LittleEndianWriter.WriteUInt16(buffer, offset + 0, StructureSize);
LittleEndianWriter.WriteUInt16(buffer, offset + 2, Reserved);
}
public override int CommandLength
{
get
{
return DeclaredSize;
}
}
}
}

View file

@ -0,0 +1,76 @@
/* Copyright (C) 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,
* either version 3 of the License, or (at your option) any later version.
*/
using System;
using System.Collections.Generic;
using Utilities;
namespace SMBLibrary.SMB2
{
/// <summary>
/// SMB2 NEGOTIATE Request
/// </summary>
public class NegotiateRequest : SMB2Command
{
public const int DeclaredSize = 36;
public ushort StructureSize;
private ushort DialectCount;
public SecurityMode SecurityMode;
public ushort Reserved;
public ServerCapabilities Capabilities;
public Guid ClientGuid;
public DateTime ClientStartTime;
public List<SMB2Dialect> Dialects = new List<SMB2Dialect>();
public NegotiateRequest() : base(SMB2CommandName.Negotiate)
{
StructureSize = DeclaredSize;
}
public NegotiateRequest(byte[] buffer, int offset) : base(buffer, offset)
{
StructureSize = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 0);
DialectCount = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 2);
SecurityMode = (SecurityMode)LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 4);
Reserved = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 6);
Capabilities = (ServerCapabilities)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));
for (int index = 0; index < DialectCount; index++)
{
SMB2Dialect dialect = (SMB2Dialect)LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 36 + index * 2);
Dialects.Add(dialect);
}
}
public override void WriteCommandBytes(byte[] buffer, int offset)
{
LittleEndianWriter.WriteUInt16(buffer, offset + 0, StructureSize);
LittleEndianWriter.WriteUInt16(buffer, offset + 2, DialectCount);
LittleEndianWriter.WriteUInt16(buffer, offset + 4, (ushort)SecurityMode);
LittleEndianWriter.WriteUInt16(buffer, offset + 6, Reserved);
LittleEndianWriter.WriteUInt32(buffer, offset + 8, (uint)Capabilities);
LittleEndianWriter.WriteGuidBytes(buffer, offset + 12, ClientGuid);
LittleEndianWriter.WriteInt64(buffer, offset + 28, ClientStartTime.ToFileTimeUtc());
for (int index = 0; index < Dialects.Count; index++)
{
SMB2Dialect dialect = Dialects[index];
LittleEndianWriter.WriteUInt16(buffer, offset + 36 + index * 2, (ushort)dialect);
}
}
public override int CommandLength
{
get
{
return 36 + Dialects.Count * 2;
}
}
}
}

View file

@ -0,0 +1,114 @@
/* Copyright (C) 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,
* either version 3 of the License, or (at your option) any later version.
*/
using System;
using System.Collections.Generic;
using Utilities;
namespace SMBLibrary.SMB2
{
/// <summary>
/// SMB2 NEGOTIATE Response
/// </summary>
public class NegotiateResponse : SMB2Command
{
public const int FixedSize = 64;
public const int DeclaredSize = 65;
public ushort StructureSize;
public SecurityMode SecurityMode;
public SMB2Dialect DialectRevision;
private ushort NegotiateContextCount;
public Guid ServerGuid;
public ServerCapabilities Capabilities;
public uint MaxTransactSize;
public uint MaxReadSize;
public uint MaxWriteSize;
public DateTime SystemTime;
public DateTime ServerStartTime;
private ushort SecurityBufferOffset;
private ushort SecurityBufferLength;
private uint NegotiateContextOffset;
public byte[] SecurityBuffer = new byte[0];
public List<NegotiateContext> NegotiateContextList = new List<NegotiateContext>();
public NegotiateResponse() : base(SMB2CommandName.Negotiate)
{
Header.IsResponse = true;
StructureSize = DeclaredSize;
}
public NegotiateResponse(byte[] buffer, int offset) : base(buffer, offset)
{
StructureSize = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 0);
SecurityMode = (SecurityMode)LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 2);
DialectRevision = (SMB2Dialect)LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 4);
NegotiateContextCount = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 6);
ServerGuid = LittleEndianConverter.ToGuid(buffer, offset + SMB2Header.Length + 8);
Capabilities = (ServerCapabilities)LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 24);
MaxTransactSize = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 28);
MaxReadSize = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 32);
MaxWriteSize = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 36);
SystemTime = DateTime.FromFileTimeUtc(LittleEndianConverter.ToInt64(buffer, offset + SMB2Header.Length + 40));
ServerStartTime = DateTime.FromFileTimeUtc(LittleEndianConverter.ToInt64(buffer, offset + SMB2Header.Length + 48));
SecurityBufferOffset = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 56);
SecurityBufferLength = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 58);
NegotiateContextOffset = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 60);
SecurityBuffer = ByteReader.ReadBytes(buffer, offset + SecurityBufferOffset, SecurityBufferLength);
NegotiateContextList = NegotiateContext.ReadNegotiateContextList(buffer, (int)NegotiateContextOffset, NegotiateContextCount);
}
public override void WriteCommandBytes(byte[] buffer, int offset)
{
SecurityBufferOffset = 0;
SecurityBufferLength = (ushort)SecurityBuffer.Length;
int paddedSecurityBufferLength = (int)Math.Ceiling((double)SecurityBufferLength / 8) * 8;
if (SecurityBuffer.Length > 0)
{
SecurityBufferOffset = SMB2Header.Length + FixedSize;
}
NegotiateContextOffset = 0;
NegotiateContextCount = (ushort)NegotiateContextList.Count;
if (NegotiateContextList.Count > 0)
{
// NegotiateContextList must be 8-byte aligned
NegotiateContextOffset = (uint)(SMB2Header.Length + FixedSize + paddedSecurityBufferLength);
}
LittleEndianWriter.WriteUInt16(buffer, offset + 0, StructureSize);
LittleEndianWriter.WriteUInt16(buffer, offset + 2, (ushort)SecurityMode);
LittleEndianWriter.WriteUInt16(buffer, offset + 4, (ushort)DialectRevision);
LittleEndianWriter.WriteUInt16(buffer, offset + 6, NegotiateContextCount);
LittleEndianWriter.WriteGuidBytes(buffer, offset + 8, ServerGuid);
LittleEndianWriter.WriteUInt32(buffer, offset + 24, (uint)Capabilities);
LittleEndianWriter.WriteUInt32(buffer, offset + 28, MaxTransactSize);
LittleEndianWriter.WriteUInt32(buffer, offset + 32, MaxReadSize);
LittleEndianWriter.WriteUInt32(buffer, offset + 36, MaxWriteSize);
LittleEndianWriter.WriteInt64(buffer, offset + 40, SystemTime.ToFileTimeUtc());
LittleEndianWriter.WriteInt64(buffer, offset + 48, ServerStartTime.ToFileTimeUtc());
LittleEndianWriter.WriteUInt16(buffer, offset + 56, SecurityBufferOffset);
LittleEndianWriter.WriteUInt16(buffer, offset + 58, SecurityBufferLength);
LittleEndianWriter.WriteUInt32(buffer, offset + 60, NegotiateContextOffset);
ByteWriter.WriteBytes(buffer, offset + FixedSize, SecurityBuffer);
NegotiateContext.WriteNegotiateContextList(buffer, offset + FixedSize + paddedSecurityBufferLength, NegotiateContextList);
}
public override int CommandLength
{
get
{
if (NegotiateContextList.Count == 0)
{
return FixedSize + SecurityBuffer.Length;
}
else
{
int paddedSecurityBufferLength = (int)Math.Ceiling((double)SecurityBufferLength / 8) * 8;
return FixedSize + paddedSecurityBufferLength + NegotiateContext.GetNegotiateContextListLength(NegotiateContextList);
}
}
}
}
}

View file

@ -0,0 +1,133 @@
/* Copyright (C) 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,
* either version 3 of the License, or (at your option) any later version.
*/
using System;
using System.Collections.Generic;
using Utilities;
namespace SMBLibrary.SMB2
{
/// <summary>
/// SMB2 QUERY_DIRECTORY Request
/// </summary>
public class QueryDirectoryRequest : SMB2Command
{
public const int FixedLength = 32;
public const int DeclaredSize = 33;
public ushort StructureSize;
public FileInformationClass FileInformationClass;
public QueryDirectoryFlags Flags;
public uint FileIndex;
public FileID FileId;
private ushort FileNameOffset;
private ushort FileNameLength;
public uint OutputBufferLength;
public string FileName = String.Empty;
public QueryDirectoryRequest() : base(SMB2CommandName.QueryDirectory)
{
StructureSize = DeclaredSize;
}
public QueryDirectoryRequest(byte[] buffer, int offset) : base(buffer, offset)
{
StructureSize = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 0);
FileInformationClass = (FileInformationClass)ByteReader.ReadByte(buffer, offset + SMB2Header.Length + 2);
Flags = (QueryDirectoryFlags)ByteReader.ReadByte(buffer, offset + SMB2Header.Length + 3);
FileIndex = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 4);
FileId = new FileID(buffer, offset + SMB2Header.Length + 8);
FileNameOffset = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 24);
FileNameLength = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 26);
OutputBufferLength = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 28);
FileName = ByteReader.ReadUTF16String(buffer, offset + FileNameOffset, FileNameLength / 2);
}
public override void WriteCommandBytes(byte[] buffer, int offset)
{
FileNameOffset = 0;
FileNameLength = (ushort)(FileName.Length * 2);
if (FileName.Length > 0)
{
FileNameOffset = SMB2Header.Length + FixedLength;
}
LittleEndianWriter.WriteUInt16(buffer, offset + 0, StructureSize);
ByteWriter.WriteByte(buffer, offset + 2, (byte)FileInformationClass);
ByteWriter.WriteByte(buffer, offset + 3, (byte)Flags);
LittleEndianWriter.WriteUInt32(buffer, offset + 4, FileIndex);
FileId.WriteBytes(buffer, offset + 8);
LittleEndianWriter.WriteUInt16(buffer, offset + 24, FileNameOffset);
LittleEndianWriter.WriteUInt16(buffer, offset + 26, FileNameLength);
LittleEndianWriter.WriteUInt32(buffer, offset + 28, OutputBufferLength);
ByteWriter.WriteUTF16String(buffer, offset + 32, FileName);
}
public bool Restart
{
get
{
return ((this.Flags & QueryDirectoryFlags.SMB2_RESTART_SCANS) > 0);
}
set
{
if (value)
{
Flags |= QueryDirectoryFlags.SMB2_RESTART_SCANS;
}
else
{
Flags &= ~QueryDirectoryFlags.SMB2_RESTART_SCANS;
}
}
}
public bool ReturnSingleEntry
{
get
{
return ((this.Flags & QueryDirectoryFlags.SMB2_RETURN_SINGLE_ENTRY) > 0);
}
set
{
if (value)
{
Flags |= QueryDirectoryFlags.SMB2_RETURN_SINGLE_ENTRY;
}
else
{
Flags &= ~QueryDirectoryFlags.SMB2_RETURN_SINGLE_ENTRY;
}
}
}
public bool Reopen
{
get
{
return ((this.Flags & QueryDirectoryFlags.SMB2_REOPEN) > 0);
}
set
{
if (value)
{
Flags |= QueryDirectoryFlags.SMB2_REOPEN;
}
else
{
Flags &= ~QueryDirectoryFlags.SMB2_REOPEN;
}
}
}
public override int CommandLength
{
get
{
return FixedLength + FileName.Length * 2;
}
}
}
}

View file

@ -0,0 +1,79 @@
/* Copyright (C) 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,
* either version 3 of the License, or (at your option) any later version.
*/
using System;
using System.Collections.Generic;
using Utilities;
namespace SMBLibrary.SMB2
{
/// <summary>
/// SMB2 QUERY_DIRECTORY Response
/// </summary>
public class QueryDirectoryResponse : SMB2Command
{
public const int FixedLength = 8;
public const int DeclaredSize = 9;
public ushort StructureSize;
private ushort OutputBufferOffset;
private uint OutputBufferLength;
public byte[] OutputBuffer = new byte[0];
public QueryDirectoryResponse() : base(SMB2CommandName.QueryDirectory)
{
Header.IsResponse = true;
StructureSize = DeclaredSize;
}
public QueryDirectoryResponse(byte[] buffer, int offset) : base(buffer, offset)
{
StructureSize = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 0);
OutputBufferOffset = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 2);
OutputBufferLength = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 4);
OutputBuffer = ByteReader.ReadBytes(buffer, offset + (int)OutputBufferOffset, (int)OutputBufferLength);
}
public override void WriteCommandBytes(byte[] buffer, int offset)
{
OutputBufferOffset = 0;
OutputBufferLength = (uint)OutputBuffer.Length;
if (OutputBuffer.Length > 0)
{
OutputBufferOffset = SMB2Header.Length + FixedLength;
}
LittleEndianWriter.WriteUInt16(buffer, offset + 0, StructureSize);
LittleEndianWriter.WriteUInt16(buffer, offset + 2, OutputBufferOffset);
LittleEndianWriter.WriteUInt32(buffer, offset + 4, OutputBufferLength);
ByteWriter.WriteBytes(buffer, offset + FixedLength, OutputBuffer);
}
public List<QueryDirectoryFileInformation> GetFileInformationList(FileInformationClass fileInformationClass)
{
if (OutputBuffer.Length > 0)
{
return QueryDirectoryFileInformation.ReadFileInformationList(OutputBuffer, 0, fileInformationClass);
}
else
{
return new List<QueryDirectoryFileInformation>();
}
}
public void SetFileInformationList(List<QueryDirectoryFileInformation> fileInformationList)
{
OutputBuffer = QueryDirectoryFileInformation.GetBytes(fileInformationList);
}
public override int CommandLength
{
get
{
return FixedLength + OutputBuffer.Length;
}
}
}
}

View file

@ -0,0 +1,111 @@
/* Copyright (C) 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,
* either version 3 of the License, or (at your option) any later version.
*/
using System;
using System.Collections.Generic;
using Utilities;
namespace SMBLibrary.SMB2
{
/// <summary>
/// SMB2 QUERY_INFO Request
/// </summary>
public class QueryInfoRequest : SMB2Command
{
public const int FixedSize = 40;
public const int DeclaredSize = 41;
public ushort StructureSize;
public InfoType InfoType;
private byte FileInfoClass;
public uint OutputBufferLength;
private ushort InputBufferOffset;
public ushort Reserved;
private uint InputBufferLength;
public uint AdditionalInformation;
public uint Flags;
public FileID FileId;
public byte[] InputBuffer = new byte[0];
public QueryInfoRequest() : base(SMB2CommandName.QueryInfo)
{
StructureSize = DeclaredSize;
}
public QueryInfoRequest(byte[] buffer, int offset) : base(buffer, offset)
{
StructureSize = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 0);
InfoType = (InfoType)ByteReader.ReadByte(buffer, offset + SMB2Header.Length + 2);
FileInfoClass = ByteReader.ReadByte(buffer, offset + SMB2Header.Length + 3);
OutputBufferLength = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 4);
InputBufferOffset = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 8);
Reserved = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 10);
InputBufferLength = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 12);
AdditionalInformation = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 16);
Flags = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 20);
FileId = new FileID(buffer, offset + SMB2Header.Length + 24);
InputBuffer = ByteReader.ReadBytes(buffer, offset + InputBufferOffset, (int)InputBufferLength);
}
public override void WriteCommandBytes(byte[] buffer, int offset)
{
InputBufferOffset = 0;
InputBufferLength = (uint)InputBuffer.Length;
if (InputBuffer.Length > 0)
{
InputBufferOffset = SMB2Header.Length + FixedSize;
}
LittleEndianWriter.WriteUInt16(buffer, offset + 0, StructureSize);
ByteWriter.WriteByte(buffer, offset + 2, (byte)InfoType);
ByteWriter.WriteByte(buffer, offset + 3, FileInfoClass);
LittleEndianWriter.WriteUInt32(buffer, offset + 4, OutputBufferLength);
LittleEndianWriter.WriteUInt16(buffer, offset + 8, InputBufferOffset);
LittleEndianWriter.WriteUInt16(buffer, offset + 10, Reserved);
LittleEndianWriter.WriteUInt32(buffer, offset + 12, InputBufferLength);
LittleEndianWriter.WriteUInt32(buffer, offset + 16, AdditionalInformation);
LittleEndianWriter.WriteUInt32(buffer, offset + 20, Flags);
FileId.WriteBytes(buffer, offset + 24);
ByteWriter.WriteBytes(buffer, offset + FixedSize, InputBuffer);
}
public FileInformationClass FileInformationClass
{
get
{
return (FileInformationClass)FileInfoClass;
}
set
{
FileInfoClass = (byte)value;
}
}
public FileSystemInformationClass FileSystemInformationClass
{
get
{
return (FileSystemInformationClass)FileInfoClass;
}
set
{
FileInfoClass = (byte)value;
}
}
public void SetFileInformation(FileInformation fileInformation)
{
InputBuffer = fileInformation.GetBytes();
}
public override int CommandLength
{
get
{
return FixedSize + InputBuffer.Length;
}
}
}
}

View file

@ -0,0 +1,72 @@
/* Copyright (C) 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,
* either version 3 of the License, or (at your option) any later version.
*/
using System;
using System.Collections.Generic;
using Utilities;
namespace SMBLibrary.SMB2
{
/// <summary>
/// SMB2 QUERY_INFO Response
/// </summary>
public class QueryInfoResponse : SMB2Command
{
public const int FixedSize = 8;
public const int DeclaredSize = 9;
public ushort StructureSize;
private ushort OutputBufferOffset;
private uint OutputBufferLength;
public byte[] OutputBuffer = new byte[0];
public QueryInfoResponse() : base(SMB2CommandName.QueryInfo)
{
Header.IsResponse = true;
StructureSize = DeclaredSize;
}
public QueryInfoResponse(byte[] buffer, int offset) : base(buffer, offset)
{
StructureSize = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 0);
OutputBufferOffset = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 2);
OutputBufferLength = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 4);
OutputBuffer = ByteReader.ReadBytes(buffer, offset + OutputBufferOffset, (int)OutputBufferLength);
}
public override void WriteCommandBytes(byte[] buffer, int offset)
{
OutputBufferOffset = 0;
OutputBufferLength = (uint)OutputBuffer.Length;
if (OutputBuffer.Length > 0)
{
OutputBufferOffset = SMB2Header.Length + FixedSize;
}
LittleEndianWriter.WriteUInt16(buffer, offset + 0, StructureSize);
LittleEndianWriter.WriteUInt16(buffer, offset + 2, OutputBufferOffset);
LittleEndianWriter.WriteUInt32(buffer, offset + 4, OutputBufferLength);
ByteWriter.WriteBytes(buffer, offset + FixedSize, OutputBuffer);
}
public void SetFileInformation(FileInformation fileInformation)
{
OutputBuffer = fileInformation.GetBytes();
}
public void SetFileSystemInformation(FileSystemInformation fileSystemInformation)
{
OutputBuffer = fileSystemInformation.GetBytes();
}
public override int CommandLength
{
get
{
return FixedSize + OutputBuffer.Length;
}
}
}
}

View file

@ -0,0 +1,97 @@
/* Copyright (C) 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,
* either version 3 of the License, or (at your option) any later version.
*/
using System;
using System.Collections.Generic;
using Utilities;
namespace SMBLibrary.SMB2
{
/// <summary>
/// SMB2 READ Request
/// </summary>
public class ReadRequest : SMB2Command
{
public const int FixedSize = 48;
public const int DeclaredSize = 49;
public ushort StructureSize;
public byte Padding;
public ReadFlags Flags;
public uint ReadLength;
public ulong Offset;
public FileID FileId;
public uint MinimumCount;
public uint Channel;
public uint RemainingBytes;
private ushort ReadChannelInfoOffset;
private ushort ReadChannelInfoLength;
public byte[] ReadChannelInfo = new byte[0];
public ReadRequest() : base(SMB2CommandName.Read)
{
StructureSize = DeclaredSize;
}
public ReadRequest(byte[] buffer, int offset) : base(buffer, offset)
{
StructureSize = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 0);
Padding = ByteReader.ReadByte(buffer, offset + SMB2Header.Length + 2);
Flags = (ReadFlags)ByteReader.ReadByte(buffer, offset + SMB2Header.Length + 3);
ReadLength = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 4);
Offset = LittleEndianConverter.ToUInt64(buffer, offset + SMB2Header.Length + 8);
FileId = new FileID(buffer, offset + SMB2Header.Length + 16);
MinimumCount = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 32);
Channel = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 36);
RemainingBytes = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 40);
ReadChannelInfoOffset = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 44);
ReadChannelInfoLength = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 46);
if (ReadChannelInfoLength > 0)
{
ReadChannelInfo = ByteReader.ReadBytes(buffer, offset + ReadChannelInfoOffset, ReadChannelInfoLength);
}
}
public override void WriteCommandBytes(byte[] buffer, int offset)
{
ReadChannelInfoOffset = 0;
ReadChannelInfoLength = (ushort)ReadChannelInfo.Length;
if (ReadChannelInfo.Length > 0)
{
ReadChannelInfoOffset = SMB2Header.Length + FixedSize;
}
LittleEndianWriter.WriteUInt16(buffer, offset + 0, StructureSize);
ByteWriter.WriteByte(buffer, offset + 2, Padding);
ByteWriter.WriteByte(buffer, offset + 3, (byte)Flags);
LittleEndianWriter.WriteUInt32(buffer, offset + 4, ReadLength);
LittleEndianWriter.WriteUInt64(buffer, offset + 8, Offset);
FileId.WriteBytes(buffer, offset + 16);
LittleEndianWriter.WriteUInt32(buffer, offset + 32, MinimumCount);
LittleEndianWriter.WriteUInt32(buffer, offset + 36, Channel);
LittleEndianWriter.WriteUInt32(buffer, offset + 40, RemainingBytes);
LittleEndianWriter.WriteUInt16(buffer, offset + 44, ReadChannelInfoOffset);
LittleEndianWriter.WriteUInt16(buffer, offset + 46, ReadChannelInfoLength);
if (ReadChannelInfo.Length > 0)
{
ByteWriter.WriteBytes(buffer, offset + FixedSize, ReadChannelInfo);
}
else
{
// The client MUST set one byte of [the buffer] field to 0
ByteWriter.WriteBytes(buffer, offset + FixedSize, new byte[1]);
}
}
public override int CommandLength
{
get
{
// The client MUST set one byte of [the buffer] field to 0
return Math.Max(FixedSize + ReadChannelInfo.Length, DeclaredSize);
}
}
}
}

View file

@ -0,0 +1,77 @@
/* Copyright (C) 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,
* either version 3 of the License, or (at your option) any later version.
*/
using System;
using System.Collections.Generic;
using Utilities;
namespace SMBLibrary.SMB2
{
/// <summary>
/// SMB2 READ Response
/// </summary>
public class ReadResponse : SMB2Command
{
public const int FixedSize = 16;
public const int DeclaredSize = 17;
public ushort StructureSize;
private byte DataOffset;
public byte Reserved;
private uint DataLength;
public uint DataRemaining;
public uint Reserved2;
public byte[] Data = new byte[0];
public ReadResponse() : base(SMB2CommandName.Read)
{
Header.IsResponse = true;
StructureSize = DeclaredSize;
}
public ReadResponse(byte[] buffer, int offset) : base(buffer, offset)
{
StructureSize = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 0);
DataOffset = ByteReader.ReadByte(buffer, offset + SMB2Header.Length + 2);
Reserved = ByteReader.ReadByte(buffer, offset + SMB2Header.Length + 3);
DataLength = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 4);
DataRemaining = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 8);
Reserved2 = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 12);
if (DataLength > 0)
{
Data = ByteReader.ReadBytes(buffer, offset + DataOffset, (int)DataLength);
}
}
public override void WriteCommandBytes(byte[] buffer, int offset)
{
DataOffset = 0;
DataLength = (uint)Data.Length;
if (Data.Length > 0)
{
DataOffset = SMB2Header.Length + FixedSize;
}
LittleEndianWriter.WriteUInt16(buffer, offset + 0, StructureSize);
ByteWriter.WriteByte(buffer, offset + 2, DataOffset);
ByteWriter.WriteByte(buffer, offset + 3, Reserved);
LittleEndianWriter.WriteUInt32(buffer, offset + 4, DataLength);
LittleEndianWriter.WriteUInt32(buffer, offset + 8, DataRemaining);
LittleEndianWriter.WriteUInt32(buffer, offset + 12, Reserved2);
if (Data.Length > 0)
{
ByteWriter.WriteBytes(buffer, offset + FixedSize, Data);
}
}
public override int CommandLength
{
get
{
return FixedSize + Data.Length;
}
}
}
}

View file

@ -0,0 +1,157 @@
/* Copyright (C) 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,
* either version 3 of the License, or (at your option) any later version.
*/
using System;
using System.Collections.Generic;
using Utilities;
namespace SMBLibrary.SMB2
{
public abstract class SMB2Command
{
public SMB2Header Header;
public SMB2Command(SMB2CommandName commandName)
{
Header = new SMB2Header(commandName);
}
public SMB2Command(byte[] buffer, int offset)
{
Header = new SMB2Header(buffer, offset);
}
public void WriteBytes(byte[] buffer, int offset)
{
Header.WriteBytes(buffer, offset);
WriteCommandBytes(buffer, offset + SMB2Header.Length);
}
public abstract void WriteCommandBytes(byte[] buffer, int offset);
public byte[] GetBytes()
{
byte[] buffer = new byte[this.Length];
WriteBytes(buffer, 0);
return buffer;
}
public SMB2CommandName CommandName
{
get
{
return Header.Command;
}
}
public int Length
{
get
{
return SMB2Header.Length + CommandLength;
}
}
public abstract int CommandLength
{
get;
}
public static SMB2Command ReadRequest(byte[] buffer, int offset)
{
SMB2CommandName Command = (SMB2CommandName)LittleEndianConverter.ToUInt16(buffer, offset + 12);
switch (Command)
{
case SMB2CommandName.Negotiate:
return new NegotiateRequest(buffer, offset);
case SMB2CommandName.SessionSetup:
return new SessionSetupRequest(buffer, offset);
case SMB2CommandName.Logoff:
return new LogoffRequest(buffer, offset);
case SMB2CommandName.TreeConnect:
return new TreeConnectRequest(buffer, offset);
case SMB2CommandName.TreeDisconnect:
return new TreeDisconnectRequest(buffer, offset);
case SMB2CommandName.Create:
return new CreateRequest(buffer, offset);
case SMB2CommandName.Close:
return new CloseRequest(buffer, offset);
case SMB2CommandName.Flush:
return new FlushRequest(buffer, offset);
case SMB2CommandName.Read:
return new ReadRequest(buffer, offset);
case SMB2CommandName.Write:
return new WriteRequest(buffer, offset);
case SMB2CommandName.Lock:
return new LockRequest(buffer, offset);
case SMB2CommandName.IOCtl:
return new IOCtlRequest(buffer, offset);
case SMB2CommandName.Cancel:
return new CancelRequest(buffer, offset);
case SMB2CommandName.Echo:
return new EchoRequest(buffer, offset);
case SMB2CommandName.QueryDirectory:
return new QueryDirectoryRequest(buffer, offset);
case SMB2CommandName.ChangeNotify:
return new ChangeNotifyRequest(buffer, offset);
case SMB2CommandName.QueryInfo:
return new QueryInfoRequest(buffer, offset);
case SMB2CommandName.SetInfo:
return new SetInfoRequest(buffer, offset);
default:
throw new System.IO.InvalidDataException("Invalid SMB2 command in buffer");
}
}
public static List<SMB2Command> ReadRequestChain(byte[] buffer, int offset)
{
List<SMB2Command> result = new List<SMB2Command>();
SMB2Command command;
do
{
command = ReadRequest(buffer, offset);
result.Add(command);
offset += (int)command.Header.NextCommand;
}
while (command.Header.NextCommand != 0);
return result;
}
public static byte[] GetCommandChainBytes(List<SMB2Command> commands)
{
int totalLength = 0;
for (int index = 0; index < commands.Count; index++)
{
// Any subsequent SMB2 header MUST be 8-byte aligned
int length = commands[index].Length;
if (index < commands.Count - 1)
{
int paddedLength = (int)Math.Ceiling((double)length / 8) * 8;
totalLength += paddedLength;
}
else
{
totalLength += length;
}
}
byte[] buffer = new byte[totalLength];
int offset = 0;
for (int index = 0; index < commands.Count; index++)
{
SMB2Command command = commands[index];
int commandLength = command.Length;
int paddedLength = (int)Math.Ceiling((double)commandLength / 8) * 8;
if (index < commands.Count - 1)
{
command.Header.NextCommand = (uint)paddedLength;
}
command.WriteBytes(buffer, offset);
offset += paddedLength;
}
return buffer;
}
}
}

View file

@ -0,0 +1,79 @@
/* Copyright (C) 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,
* either version 3 of the License, or (at your option) any later version.
*/
using System;
using System.Collections.Generic;
using Utilities;
namespace SMBLibrary.SMB2
{
/// <summary>
/// SMB2 SESSION_SETUP Request
/// </summary>
public class SessionSetupRequest : SMB2Command
{
public const int FixedSize = 24;
public const int DeclaredSize = 25;
public ushort StructureSize;
public SessionSetupFlags Flags;
public SecurityMode SecurityMode;
public ServerCapabilities Capabilities;
public uint Channel;
private ushort SecurityBufferOffset;
private ushort SecurityBufferLength;
public ulong PreviousSessionId;
public byte[] SecurityBuffer = new byte[0];
public SessionSetupRequest() : base(SMB2CommandName.SessionSetup)
{
StructureSize = DeclaredSize;
}
public SessionSetupRequest(byte[] buffer, int offset) : base(buffer, offset)
{
StructureSize = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 0);
Flags = (SessionSetupFlags)ByteReader.ReadByte(buffer, offset + SMB2Header.Length + 2);
SecurityMode = (SecurityMode)ByteReader.ReadByte(buffer, offset + SMB2Header.Length + 3);
Capabilities = (ServerCapabilities)LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 4);
Channel = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 8);
SecurityBufferOffset = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 12);
SecurityBufferLength = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 14);
PreviousSessionId = LittleEndianConverter.ToUInt64(buffer, offset + SMB2Header.Length + 16);
if (SecurityBufferLength > 0)
{
SecurityBuffer = ByteReader.ReadBytes(buffer, offset + SecurityBufferOffset, SecurityBufferLength);
}
}
public override void WriteCommandBytes(byte[] buffer, int offset)
{
SecurityBufferOffset = 0;
SecurityBufferLength = (ushort)SecurityBuffer.Length;
if (SecurityBuffer.Length > 0)
{
SecurityBufferOffset = SMB2Header.Length + FixedSize;
}
LittleEndianWriter.WriteUInt16(buffer, offset + 0, StructureSize);
ByteWriter.WriteByte(buffer, offset + 2, (byte)Flags);
ByteWriter.WriteByte(buffer, offset + 3, (byte)SecurityMode);
LittleEndianWriter.WriteUInt32(buffer, offset + 4, (uint)Capabilities);
LittleEndianWriter.WriteUInt32(buffer, offset + 8, Channel);
LittleEndianWriter.WriteUInt16(buffer, offset + 12, SecurityBufferOffset);
LittleEndianWriter.WriteUInt16(buffer, offset + 14, SecurityBufferLength);
LittleEndianWriter.WriteUInt64(buffer, offset + 16, PreviousSessionId);
ByteWriter.WriteBytes(buffer, offset + FixedSize, SecurityBuffer);
}
public override int CommandLength
{
get
{
return FixedSize + SecurityBuffer.Length;
}
}
}
}

View file

@ -0,0 +1,65 @@
/* Copyright (C) 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,
* either version 3 of the License, or (at your option) any later version.
*/
using System;
using System.Collections.Generic;
using Utilities;
namespace SMBLibrary.SMB2
{
/// <summary>
/// SMB2 SESSION_SETUP Response
/// </summary>
public class SessionSetupResponse : SMB2Command
{
public const int FixedSize = 8;
public const int DeclaredSize = 9;
public ushort StructureSize;
public SessionFlags SessionFlags;
private ushort SecurityBufferOffset;
private ushort SecurityBufferLength;
public byte[] SecurityBuffer = new byte[0];
public SessionSetupResponse() : base(SMB2CommandName.SessionSetup)
{
Header.IsResponse = true;
StructureSize = DeclaredSize;
}
public SessionSetupResponse(byte[] buffer, int offset) : base(buffer, offset)
{
StructureSize = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 0);
SessionFlags = (SessionFlags)LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 2);
SecurityBufferOffset = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 4);
SecurityBufferLength = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 6);
SecurityBuffer = ByteReader.ReadBytes(buffer, offset + SecurityBufferOffset, SecurityBufferLength);
}
public override void WriteCommandBytes(byte[] buffer, int offset)
{
SecurityBufferOffset = 0;
SecurityBufferLength = (ushort)SecurityBuffer.Length;
if (SecurityBuffer.Length > 0)
{
SecurityBufferOffset = SMB2Header.Length + FixedSize;
}
LittleEndianWriter.WriteUInt16(buffer, offset + 0, StructureSize);
LittleEndianWriter.WriteUInt16(buffer, offset + 2, (ushort)SessionFlags);
LittleEndianWriter.WriteUInt16(buffer, offset + 4, SecurityBufferOffset);
LittleEndianWriter.WriteUInt16(buffer, offset + 6, SecurityBufferLength);
ByteWriter.WriteBytes(buffer, offset + 8, SecurityBuffer);
}
public override int CommandLength
{
get
{
return FixedSize + SecurityBuffer.Length;
}
}
}
}

View file

@ -0,0 +1,105 @@
/* Copyright (C) 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,
* either version 3 of the License, or (at your option) any later version.
*/
using System;
using System.Collections.Generic;
using Utilities;
namespace SMBLibrary.SMB2
{
/// <summary>
/// SMB2 SET_INFO Request
/// </summary>
public class SetInfoRequest : SMB2Command
{
public const int FixedSize = 32;
public const int DeclaredSize = 33;
public ushort StructureSize;
public InfoType InfoType;
private byte FileInfoClass;
public uint BufferLength;
private ushort BufferOffset;
public ushort Reserved;
public uint AdditionalInformation;
public FileID FileId;
public byte[] Buffer = new byte[0];
public SetInfoRequest() : base(SMB2CommandName.SetInfo)
{
StructureSize = DeclaredSize;
}
public SetInfoRequest(byte[] buffer, int offset) : base(buffer, offset)
{
StructureSize = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 0);
InfoType = (InfoType)ByteReader.ReadByte(buffer, offset + SMB2Header.Length + 2);
FileInfoClass = ByteReader.ReadByte(buffer, offset + SMB2Header.Length + 3);
BufferLength = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 4);
BufferOffset = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 8);
Reserved = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 10);
AdditionalInformation = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 12);
FileId = new FileID(buffer, offset + SMB2Header.Length + 16);
Buffer = ByteReader.ReadBytes(buffer, offset + BufferOffset, (int)BufferLength);
}
public override void WriteCommandBytes(byte[] buffer, int offset)
{
BufferOffset = 0;
BufferLength = (uint)Buffer.Length;
if (Buffer.Length > 0)
{
BufferOffset = SMB2Header.Length + FixedSize;
}
LittleEndianWriter.WriteUInt16(buffer, offset + 0, StructureSize);
ByteWriter.WriteByte(buffer, offset + 2, (byte)InfoType);
ByteWriter.WriteByte(buffer, offset + 3, FileInfoClass);
LittleEndianWriter.WriteUInt32(buffer, offset + 4, BufferLength);
LittleEndianWriter.WriteUInt16(buffer, offset + 8, BufferOffset);
LittleEndianWriter.WriteUInt16(buffer, offset + 10, Reserved);
LittleEndianWriter.WriteUInt32(buffer, offset + 12, AdditionalInformation);
FileId.WriteBytes(buffer, offset + 16);
ByteWriter.WriteBytes(buffer, offset + FixedSize, Buffer);
}
public FileInformationClass FileInformationClass
{
get
{
return (FileInformationClass)FileInfoClass;
}
set
{
FileInfoClass = (byte)value;
}
}
public FileSystemInformationClass FileSystemInformationClass
{
get
{
return (FileSystemInformationClass)FileInfoClass;
}
set
{
FileInfoClass = (byte)value;
}
}
public void SetFileInformation(FileInformation fileInformation)
{
Buffer = fileInformation.GetBytes();
}
public override int CommandLength
{
get
{
return FixedSize + Buffer.Length;
}
}
}
}

View file

@ -0,0 +1,46 @@
/* Copyright (C) 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,
* either version 3 of the License, or (at your option) any later version.
*/
using System;
using System.Collections.Generic;
using Utilities;
namespace SMBLibrary.SMB2
{
/// <summary>
/// SMB2 SET_INFO Response
/// </summary>
public class SetInfoResponse : SMB2Command
{
public const int DeclaredSize = 2;
public ushort StructureSize;
public SetInfoResponse() : base(SMB2CommandName.SetInfo)
{
Header.IsResponse = true;
StructureSize = DeclaredSize;
}
public SetInfoResponse(byte[] buffer, int offset) : base(buffer, offset)
{
StructureSize = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 0);
}
public override void WriteCommandBytes(byte[] buffer, int offset)
{
LittleEndianWriter.WriteUInt16(buffer, offset + 0, StructureSize);
}
public override int CommandLength
{
get
{
return DeclaredSize;
}
}
}
}

View file

@ -0,0 +1,70 @@
/* Copyright (C) 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,
* either version 3 of the License, or (at your option) any later version.
*/
using System;
using System.Collections.Generic;
using Utilities;
namespace SMBLibrary.SMB2
{
/// <summary>
/// SMB2 TREE_CONNECT Request
/// </summary>
public class TreeConnectRequest : SMB2Command
{
public const int FixedSize = 8;
public const int DeclaredSize = 9;
public ushort StructureSize;
public ushort Reserved;
private ushort PathOffset;
private ushort PathLength;
public string Path = String.Empty;
public TreeConnectRequest() : base(SMB2CommandName.TreeConnect)
{
StructureSize = DeclaredSize;
}
public TreeConnectRequest(byte[] buffer, int offset) : base(buffer, offset)
{
StructureSize = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 0);
Reserved = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 2);
PathOffset = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 4);
PathLength = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 6);
if (PathLength > 0)
{
Path = ByteReader.ReadUTF16String(buffer, offset + PathOffset, PathLength / 2);
}
}
public override void WriteCommandBytes(byte[] buffer, int offset)
{
PathOffset = 0;
PathLength = (ushort)(Path.Length * 2);
if (Path.Length > 0)
{
PathOffset = SMB2Header.Length + 8;
}
LittleEndianWriter.WriteUInt16(buffer, offset + 0, StructureSize);
LittleEndianWriter.WriteUInt16(buffer, offset + 2, Reserved);
LittleEndianWriter.WriteUInt16(buffer, offset + 4, PathOffset);
LittleEndianWriter.WriteUInt16(buffer, offset + 6, PathLength);
if (Path.Length > 0)
{
ByteWriter.WriteUTF16String(buffer, offset + 8, Path);
}
}
public override int CommandLength
{
get
{
return 8 + Path.Length * 2;
}
}
}
}

View file

@ -0,0 +1,61 @@
/* Copyright (C) 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,
* either version 3 of the License, or (at your option) any later version.
*/
using System;
using System.Collections.Generic;
using Utilities;
namespace SMBLibrary.SMB2
{
/// <summary>
/// SMB2 TREE_CONNECT Response
/// </summary>
public class TreeConnectResponse : SMB2Command
{
public const int DeclaredSize = 16;
public ushort StructureSize;
public ShareType ShareType;
public byte Reserved;
public ShareFlags ShareFlags;
public ShareCapabilities Capabilities;
public AccessMask MaximalAccess;
public TreeConnectResponse() : base(SMB2CommandName.TreeConnect)
{
Header.IsResponse = true;
StructureSize = DeclaredSize;
}
public TreeConnectResponse(byte[] buffer, int offset) : base(buffer, offset)
{
StructureSize = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 0);
ShareType = (ShareType)ByteReader.ReadByte(buffer, offset + SMB2Header.Length + 2);
Reserved = ByteReader.ReadByte(buffer, offset + SMB2Header.Length + 3);
ShareFlags = (ShareFlags)LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 4);
Capabilities = (ShareCapabilities)LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 8);
MaximalAccess = new AccessMask(buffer, offset + SMB2Header.Length + 12);
}
public override void WriteCommandBytes(byte[] buffer, int offset)
{
LittleEndianWriter.WriteUInt16(buffer, offset + 0, StructureSize);
ByteWriter.WriteByte(buffer, offset + 2, (byte)ShareType);
ByteWriter.WriteByte(buffer, offset + 3, Reserved);
LittleEndianWriter.WriteUInt32(buffer, offset + 4, (uint)ShareFlags);
LittleEndianWriter.WriteUInt32(buffer, offset + 8, (uint)Capabilities);
MaximalAccess.WriteBytes(buffer, offset + 12);
}
public override int CommandLength
{
get
{
return DeclaredSize;
}
}
}
}

View file

@ -0,0 +1,48 @@
/* Copyright (C) 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,
* either version 3 of the License, or (at your option) any later version.
*/
using System;
using System.Collections.Generic;
using Utilities;
namespace SMBLibrary.SMB2
{
/// <summary>
/// SMB2 TREE_DISCONNECT Request
/// </summary>
public class TreeDisconnectRequest : SMB2Command
{
public const int DeclaredSize = 4;
public ushort StructureSize;
public ushort Reserved;
public TreeDisconnectRequest() : base(SMB2CommandName.TreeDisconnect)
{
StructureSize = DeclaredSize;
}
public TreeDisconnectRequest(byte[] buffer, int offset) : base(buffer, offset)
{
StructureSize = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 0);
Reserved = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 2);
}
public override void WriteCommandBytes(byte[] buffer, int offset)
{
LittleEndianWriter.WriteUInt16(buffer, offset + 0, StructureSize);
LittleEndianWriter.WriteUInt16(buffer, offset + 2, Reserved);
}
public override int CommandLength
{
get
{
return DeclaredSize;
}
}
}
}

View file

@ -0,0 +1,49 @@
/* Copyright (C) 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,
* either version 3 of the License, or (at your option) any later version.
*/
using System;
using System.Collections.Generic;
using Utilities;
namespace SMBLibrary.SMB2
{
/// <summary>
/// SMB2 TREE_DISCONNECT Response
/// </summary>
public class TreeDisconnectResponse : SMB2Command
{
public const int DeclaredSize = 4;
public ushort StructureSize;
public ushort Reserved;
public TreeDisconnectResponse() : base(SMB2CommandName.TreeDisconnect)
{
Header.IsResponse = true;
StructureSize = DeclaredSize;
}
public TreeDisconnectResponse(byte[] buffer, int offset) : base(buffer, offset)
{
StructureSize = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 0);
Reserved = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 2);
}
public override void WriteCommandBytes(byte[] buffer, int offset)
{
LittleEndianWriter.WriteUInt16(buffer, offset + 0, StructureSize);
LittleEndianWriter.WriteUInt16(buffer, offset + 2, Reserved);
}
public override int CommandLength
{
get
{
return DeclaredSize;
}
}
}
}

View file

@ -0,0 +1,99 @@
/* Copyright (C) 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,
* either version 3 of the License, or (at your option) any later version.
*/
using System;
using System.Collections.Generic;
using Utilities;
namespace SMBLibrary.SMB2
{
/// <summary>
/// SMB2 WRITE Request
/// </summary>
public class WriteRequest : SMB2Command
{
public const int FixedSize = 48;
public const int DeclaredSize = 49;
public ushort StructureSize;
private ushort DataOffset;
private uint DataLength;
public ulong Offset;
public FileID FileId;
public uint Channel;
public uint RemainingBytes;
private ushort WriteChannelInfoOffset;
private ushort WriteChannelInfoLength;
public WriteFlags Flags;
public byte[] Data = new byte[0];
public byte[] WriteChannelInfo = new byte[0];
public WriteRequest() : base(SMB2CommandName.Write)
{
StructureSize = DeclaredSize;
}
public WriteRequest(byte[] buffer, int offset) : base(buffer, offset)
{
StructureSize = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 0);
DataOffset = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 2);
DataLength = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 4);
Offset = LittleEndianConverter.ToUInt64(buffer, offset + SMB2Header.Length + 8);
FileId = new FileID(buffer, offset + SMB2Header.Length + 16);
Channel = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 32);
RemainingBytes = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 36);
WriteChannelInfoOffset = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 40);
WriteChannelInfoLength = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 42);
Flags = (WriteFlags)LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 44);
Data = ByteReader.ReadBytes(buffer, offset + DataOffset, (int)DataLength);
WriteChannelInfo = ByteReader.ReadBytes(buffer, offset + WriteChannelInfoOffset, WriteChannelInfoLength);
}
public override void WriteCommandBytes(byte[] buffer, int offset)
{
// Note: DataLength is UInt32 while WriteChannelInfoOffset is UInt16
// so it is best to put WriteChannelInfo before Data.
WriteChannelInfoOffset = 0;
WriteChannelInfoLength = (ushort)WriteChannelInfo.Length;
if (WriteChannelInfo.Length > 0)
{
WriteChannelInfoOffset = SMB2Header.Length + FixedSize;
}
DataOffset = 0;
DataLength = (uint)Data.Length;
if (Data.Length > 0)
{
DataOffset = (ushort)(WriteChannelInfoOffset + WriteChannelInfo.Length);
}
LittleEndianWriter.WriteUInt16(buffer, offset + 0, StructureSize);
LittleEndianWriter.WriteUInt16(buffer, offset + 2, DataOffset);
LittleEndianWriter.WriteUInt32(buffer, offset + 4, DataLength);
LittleEndianWriter.WriteUInt64(buffer, offset + 8, Offset);
FileId.WriteBytes(buffer, offset + 16);
LittleEndianWriter.WriteUInt32(buffer, offset + 32, Channel);
LittleEndianWriter.WriteUInt32(buffer, offset + 36, RemainingBytes);
LittleEndianWriter.WriteUInt16(buffer, offset + 40, WriteChannelInfoOffset);
LittleEndianWriter.WriteUInt16(buffer, offset + 42, WriteChannelInfoLength);
LittleEndianWriter.WriteUInt32(buffer, offset + 44, (uint)Flags);
if (WriteChannelInfo.Length > 0)
{
ByteWriter.WriteBytes(buffer, offset + FixedSize, WriteChannelInfo);
}
if (Data.Length > 0)
{
ByteWriter.WriteBytes(buffer, offset + FixedSize + WriteChannelInfo.Length, Data);
}
}
public override int CommandLength
{
get
{
return FixedSize + Data.Length + WriteChannelInfo.Length;
}
}
}
}

View file

@ -0,0 +1,74 @@
/* Copyright (C) 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,
* either version 3 of the License, or (at your option) any later version.
*/
using System;
using System.Collections.Generic;
using Utilities;
namespace SMBLibrary.SMB2
{
/// <summary>
/// SMB2 WRITE Response
/// </summary>
public class WriteResponse : SMB2Command
{
public const int FixedSize = 16;
public const int DeclaredSize = 17;
public ushort StructureSize;
public ushort Reserved;
public uint Count;
public uint Remaining;
private ushort WriteChannelInfoOffset;
private ushort WriteChannelInfoLength;
public byte[] WriteChannelInfo = new byte[0];
public WriteResponse() : base(SMB2CommandName.Write)
{
Header.IsResponse = true;
StructureSize = DeclaredSize;
}
public WriteResponse(byte[] buffer, int offset) : base(buffer, offset)
{
StructureSize = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 0);
Reserved = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 2);
Count = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 4);
Remaining = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 8);
WriteChannelInfoOffset = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 12);
WriteChannelInfoLength = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 14);
WriteChannelInfo = ByteReader.ReadBytes(buffer, offset + WriteChannelInfoOffset, WriteChannelInfoLength);
}
public override void WriteCommandBytes(byte[] buffer, int offset)
{
WriteChannelInfoOffset = 0;
WriteChannelInfoLength = (ushort)WriteChannelInfo.Length;
if (WriteChannelInfo.Length > 0)
{
WriteChannelInfoOffset = SMB2Header.Length + FixedSize;
}
LittleEndianWriter.WriteUInt16(buffer, offset + 0, StructureSize);
LittleEndianWriter.WriteUInt16(buffer, offset + 2, Reserved);
LittleEndianWriter.WriteUInt32(buffer, offset + 4, Count);
LittleEndianWriter.WriteUInt32(buffer, offset + 8, Remaining);
LittleEndianWriter.WriteUInt16(buffer, offset + 12, WriteChannelInfoOffset);
LittleEndianWriter.WriteUInt16(buffer, offset + 14, WriteChannelInfoLength);
if (WriteChannelInfo.Length > 0)
{
ByteWriter.WriteBytes(buffer, offset + FixedSize, WriteChannelInfo);
}
}
public override int CommandLength
{
get
{
return FixedSize + WriteChannelInfo.Length;
}
}
}
}

View file

@ -0,0 +1,10 @@
using System;
namespace SMBLibrary.SMB2
{
[Flags]
public enum ChangeNotifyFlags : ushort
{
WatchTree = 0x0001, // SMB2_WATCH_TREE
}
}

View file

@ -0,0 +1,21 @@
using System;
namespace SMBLibrary.SMB2
{
[Flags]
public enum NotifyChange : uint
{
FileName = 0x0000001, // FILE_NOTIFY_CHANGE_FILE_NAME
DirName = 0x0000002, // FILE_NOTIFY_CHANGE_DIR_NAME
Attributes = 0x0000004, // FILE_NOTIFY_CHANGE_ATTRIBUTES
Size = 0x0000008, // FILE_NOTIFY_CHANGE_SIZE
LastWrite = 0x000000010, // FILE_NOTIFY_CHANGE_LAST_WRITE
LastAccess = 0x00000020, // FILE_NOTIFY_CHANGE_LAST_ACCESS
Creation = 0x00000040, // FILE_NOTIFY_CHANGE_CREATION
EA = 0x00000080, // FILE_NOTIFY_CHANGE_EA
Security = 0x00000100, // FILE_NOTIFY_CHANGE_SECURITY
StreamName = 0x00000200, // FILE_NOTIFY_CHANGE_STREAM_NAME
StreamSize = 0x00000400, // FILE_NOTIFY_CHANGE_STREAM_SIZE
StreamWrite = 0x00000800, // FILE_NOTIFY_CHANGE_STREAM_WRITE
}
}

View file

@ -0,0 +1,10 @@
using System;
namespace SMBLibrary.SMB2
{
[Flags]
public enum CloseFlags : byte
{
PostQueryAttribute = 0x0001, // SMB2_CLOSE_FLAG_POSTQUERY_ATTRIB
}
}

View file

@ -0,0 +1,11 @@
namespace SMBLibrary.SMB2
{
public enum CreateAction : uint
{
FILE_SUPERSEDED = 0x00000000,
FILE_OPENED = 0x00000001,
FILE_CREATED = 0x00000002,
FILE_OVERWRITTEN = 0x00000003,
}
}

View file

@ -0,0 +1,10 @@
using System;
namespace SMBLibrary.SMB2
{
[Flags]
public enum CreateResponseFlags : byte
{
ReparsePoint = 0x01, // SMB2_CREATE_FLAG_REPARSEPOINT
}
}

View file

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace SMBLibrary.SMB2
{
public enum ImpersonationLevel : uint
{
Anonymous = 0x00000000,
Identification = 0x00000001,
Impersonation = 0x00000002,
Delegate = 0x00000003,
}
}

View file

@ -0,0 +1,14 @@
using System;
namespace SMBLibrary.SMB2
{
[Flags]
public enum OplockLevel : byte
{
None = 0x00, // SMB2_OPLOCK_LEVEL_NONE
Level2 = 0x01, // SMB2_OPLOCK_LEVEL_II
Exclusive = 0x08, // SMB2_OPLOCK_LEVEL_EXCLUSIVE
Batch = 0x09, // SMB2_OPLOCK_LEVEL_BATCH
Lease = 0xFF, // SMB2_OPLOCK_LEVEL_LEASE
}
}

View file

@ -0,0 +1,10 @@
using System;
namespace SMBLibrary.SMB2
{
[Flags]
public enum IOCtlRequestFlags : uint
{
IsFSCtl = 0x00000001, // SMB2_0_IOCTL_IS_FSCTL
}
}

View file

@ -0,0 +1,11 @@
namespace SMBLibrary.SMB2
{
public enum InfoType : byte
{
File = 0x01, // SMB2_0_INFO_FILE
FileSystem = 0x02, // SMB2_0_INFO_FILESYSTEM
Security = 0x03, // SMB2_0_INFO_SECURITY
Quota = 0x04, // SMB2_0_INFO_QUOTA
}
}

View file

@ -0,0 +1,9 @@
namespace SMBLibrary.SMB2
{
public enum NegotiateContextType : ushort
{
SMB2_PREAUTH_INTEGRITY_CAPABILITIES = 0x0001,
SMB2_ENCRYPTION_CAPABILITIES = 0x0002,
}
}

View file

@ -0,0 +1,21 @@
namespace SMBLibrary.SMB2
{
public enum SMB2Dialect : ushort
{
SMB202 = 0x0202, // SMB 2.0.2
SMB210 = 0x0210, // SMB 2.1
SMB300 = 0x0300, // SMB 3.0
SMB302 = 0x0302, // SMB 3.0.2
SMB311 = 0x0311, // SMB 3.1.1
/// <summary>
/// indicates that the server implements SMB 2.1 or future dialect revisions and expects
/// the client to send a subsequent SMB2 Negotiate request to negotiate the actual SMB 2
/// Protocol revision to be used.
/// The wildcard revision number is sent only in response to a multi-protocol negotiate
/// request with the "SMB 2.???" dialect string.
/// </summary>
SMB2xx = 0x02FF, // SMB 2.xx
}
}

View file

@ -0,0 +1,9 @@
namespace SMBLibrary.SMB2
{
public enum SecurityMode : ushort
{
SigningEnabled = 0x0001, // SMB2_NEGOTIATE_SIGNING_ENABLED
SigningRequired = 0x0002, // SMB2_NEGOTIATE_SIGNING_REQUIRED
}
}

View file

@ -0,0 +1,16 @@
using System;
namespace SMBLibrary.SMB2
{
[Flags]
public enum ServerCapabilities : uint
{
DFS = 0x00000001, // SMB2_GLOBAL_CAP_DFS
Leasing = 0x00000002, // SMB2_GLOBAL_CAP_LEASING
LargeMTU = 0x0000004, // SMB2_GLOBAL_CAP_LARGE_MTU
MultiChannel = 0x0000008, // SMB2_GLOBAL_CAP_MULTI_CHANNEL
PersistentHandles = 0x00000010, // SMB2_GLOBAL_CAP_PERSISTENT_HANDLES
DirectoryLeasing = 0x00000020, // SMB2_GLOBAL_CAP_DIRECTORY_LEASING
Encryption = 0x00000040, // SMB2_GLOBAL_CAP_ENCRYPTION (SMB 3.x)
}
}

View file

@ -0,0 +1,13 @@
using System;
namespace SMBLibrary.SMB2
{
[Flags]
public enum QueryDirectoryFlags : byte
{
SMB2_RESTART_SCANS = 0x01,
SMB2_RETURN_SINGLE_ENTRY = 0x02,
SMB2_INDEX_SPECIFIED = 0x04,
SMB2_REOPEN = 0x10,
}
}

View file

@ -0,0 +1,10 @@
using System;
namespace SMBLibrary.SMB2
{
[Flags]
public enum ReadFlags : byte
{
Unbuffered = 0x01, // SMB2_READFLAG_READ_UNBUFFERED;
}
}

View file

@ -0,0 +1,26 @@
namespace SMBLibrary.SMB2
{
public enum SMB2CommandName : ushort
{
Negotiate = 0x0000, // SMB2 NEGOTIATE
SessionSetup = 0x0001, // SMB2 SESSION_SETUP
Logoff = 0x0002, // SMB2 LOGOFF
TreeConnect = 0x0003, // SMB2 TREE_CONNECT
TreeDisconnect = 0x0004, // SMB2 TREE_DISCONNECT
Create = 0x0005, // SMB2 CREATE
Close = 0x0006, // SMB2 CLOSE
Flush = 0x0007, // SMB2 FLUSH
Read = 0x0008, // SMB2 READ
Write = 0x0009, // SMB2 WRITE
Lock = 0x000A, // SMB2 LOCK
IOCtl = 0x000B, // SMB2 IOCTL
Cancel = 0x000C, // SMB2 CANCEL
Echo = 0x000D, // SMB2 ECHO
QueryDirectory = 0x000E, // SMB2 QUERY_DIRECTORY
ChangeNotify = 0x000F, // SMB2 CHANGE_NOTIFY
QueryInfo = 0x0010, // SMB2 QUERY_INFO
SetInfo = 0x0011, // SMB2 SET_INFO
OplockBreak = 0x0012, // SMB2 OPLOCK_BREAK
}
}

View file

@ -0,0 +1,14 @@
using System;
namespace SMBLibrary.SMB2
{
[Flags]
public enum SMB2PacketHeaderFlags : uint
{
ServerToRedir = 0x0000001, // SMB2_FLAGS_SERVER_TO_REDIR
AsyncCommand = 0x0000002, // SMB2_FLAGS_ASYNC_COMMAND
RelatedOperations = 0x0000004, // SMB2_FLAGS_RELATED_OPERATIONS
Signed = 0x0000008, // SMB2_FLAGS_SIGNED
DfsOperations = 0x10000000, // SMB2_FLAGS_DFS_OPERATIONS
}
}

View file

@ -0,0 +1,12 @@
using System;
namespace SMBLibrary.SMB2
{
[Flags]
public enum SessionFlags : ushort
{
IsGuest = 0x01, // SMB2_SESSION_FLAG_IS_GUEST
IsNull = 0x02, // SMB2_SESSION_FLAG_IS_NULL
EncryptData = 0x04, // SMB2_SESSION_FLAG_ENCRYPT_DATA (SMB 3.x)
}
}

View file

@ -0,0 +1,10 @@
using System;
namespace SMBLibrary.SMB2
{
[Flags]
public enum SessionSetupFlags : byte
{
Binding = 0x01, // SMB2_SESSION_FLAG_BINDING
}
}

View file

@ -0,0 +1,14 @@
using System;
namespace SMBLibrary.SMB2
{
[Flags]
public enum ShareCapabilities : uint
{
Dfs = 0x00000008, // SMB2_SHARE_CAP_DFS
ContinuousAvailability = 0x00000010, // SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY
Scaleout = 0x00000020, // SMB2_SHARE_CAP_SCALEOUT
Cluster = 0x00000040, // SMB2_SHARE_CAP_CLUSTER
Asymmetric = 0x00000080, // SMB2_SHARE_CAP_ASYMMETRIC
}
}

View file

@ -0,0 +1,23 @@
using System;
namespace SMBLibrary.SMB2
{
[Flags]
public enum ShareFlags : uint
{
ManualCaching = 0x00000000, // SMB2_SHAREFLAG_MANUAL_CACHING
AutoCaching = 0x00000010, // SMB2_SHAREFLAG_AUTO_CACHING
VdoCaching = 0x00000020, // SMB2_SHAREFLAG_VDO_CACHING
NoCaching = 0x00000030, // SMB2_SHAREFLAG_NO_CACHING
Dfs = 0x00000001, // SMB2_SHAREFLAG_DFS
DfsRoot = 0x00000002, // SMB2_SHAREFLAG_DFS_ROOT
RestrictExclusiveOpens = 0x00000100, // SMB2_SHAREFLAG_RESTRICT_EXCLUSIVE_OPENS
ForceSharedDelete = 0x00000200, // SMB2_SHAREFLAG_FORCE_SHARED_DELETE
AllowNamespaceCaching = 0x00000400, // SMB2_SHAREFLAG_ALLOW_NAMESPACE_CACHING
AccessBasedDirectoryEnum = 0x00000800, // SMB2_SHAREFLAG_ACCESS_BASED_DIRECTORY_ENUM
ForceLevel2Oplock = 0x00001000, // SMB2_SHAREFLAG_FORCE_LEVELII_OPLOCK
EnableHashV1 = 0x00002000, // SMB2_SHAREFLAG_ENABLE_HASH_V1 (SMB 2.1)
EnableHashV2 = 0x00004000, // SMB2_SHAREFLAG_ENABLE_HASH_V2 (SMB 3.x)
EncryptData = 0x00008000, // SMB2_SHAREFLAG_ENCRYPT_DATA (SMB 3.x)
}
}

View file

@ -0,0 +1,10 @@
namespace SMBLibrary.SMB2
{
public enum ShareType : byte
{
Disk = 0x01, // SMB2_SHARE_TYPE_DISK
Pipe = 0x02, // SMB2_SHARE_TYPE_PIPE
Print = 0x03, // SMB2_SHARE_TYPE_PRINT
}
}

View file

@ -0,0 +1,10 @@
using System;
namespace SMBLibrary.SMB2
{
public enum WriteFlags : uint
{
WriteThrough = 0x00000001, // SMB2_WRITEFLAG_WRITE_THROUGH
Unbuffered = 0x00000002, // SMB2_WRITEFLAG_WRITE_UNBUFFERED
}
}

View file

@ -0,0 +1,141 @@
/* Copyright (C) 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,
* either version 3 of the License, or (at your option) any later version.
*/
using System;
using Utilities;
namespace SMBLibrary.SMB2
{
public class SMB2Header
{
public const int Length = 64;
public static readonly byte[] ProtocolSignature = new byte[] { 0xFE, 0x53, 0x4D, 0x42 };
public byte[] ProtocolId; // 4 bytes, 0xFE followed by "SMB"
public ushort StructureSize;
public ushort CreditCharge;
public NTStatus Status;
public SMB2CommandName Command;
public ushort Credits; // CreditRequest or CreditResponse (The number of credits granted to the client)
public SMB2PacketHeaderFlags Flags;
public uint NextCommand; // offset in bytes
public ulong MessageID;
public uint Reserved; // Sync
public uint TreeID; // Sync
public ulong AsyncID; // Async
public ulong SessionID;
public byte[] Signature; // 16 bytes (present if SMB2_FLAGS_SIGNED is set)
public SMB2Header(SMB2CommandName commandName)
{
ProtocolId = ProtocolSignature;
StructureSize = Length;
Command = commandName;
}
public SMB2Header(byte[] buffer, int offset)
{
ProtocolId = ByteReader.ReadBytes(buffer, offset + 0, 4);
StructureSize = LittleEndianConverter.ToUInt16(buffer, offset + 4);
CreditCharge = LittleEndianConverter.ToUInt16(buffer, offset + 6);
Status = (NTStatus)LittleEndianConverter.ToUInt32(buffer, offset + 8);
Command = (SMB2CommandName)LittleEndianConverter.ToUInt16(buffer, offset + 12);
Credits = LittleEndianConverter.ToUInt16(buffer, offset + 14);
Flags = (SMB2PacketHeaderFlags)LittleEndianConverter.ToUInt32(buffer, offset + 16);
NextCommand = LittleEndianConverter.ToUInt32(buffer, offset + 20);
MessageID = LittleEndianConverter.ToUInt64(buffer, offset + 24);
if ((Flags & SMB2PacketHeaderFlags.AsyncCommand) > 0)
{
AsyncID = LittleEndianConverter.ToUInt64(buffer, offset + 32);
}
else
{
Reserved = LittleEndianConverter.ToUInt32(buffer, offset + 32);
TreeID = LittleEndianConverter.ToUInt32(buffer, offset + 36);
}
SessionID = LittleEndianConverter.ToUInt64(buffer, offset + 40);
if ((Flags & SMB2PacketHeaderFlags.Signed) > 0)
{
Signature = ByteReader.ReadBytes(buffer, offset + 48, 16);
}
}
public void WriteBytes(byte[] buffer, int offset)
{
ByteWriter.WriteBytes(buffer, offset + 0, ProtocolId);
LittleEndianWriter.WriteUInt16(buffer, offset + 4, StructureSize);
LittleEndianWriter.WriteUInt16(buffer, offset + 6, CreditCharge);
LittleEndianWriter.WriteUInt32(buffer, offset + 8, (uint)Status);
LittleEndianWriter.WriteUInt16(buffer, offset + 12, (ushort)Command);
LittleEndianWriter.WriteUInt16(buffer, offset + 14, Credits);
LittleEndianWriter.WriteUInt32(buffer, offset + 16, (uint)Flags);
LittleEndianWriter.WriteUInt32(buffer, offset + 20, NextCommand);
LittleEndianWriter.WriteUInt64(buffer, offset + 24, MessageID);
if ((Flags & SMB2PacketHeaderFlags.AsyncCommand) > 0)
{
LittleEndianWriter.WriteUInt64(buffer, offset + 32, AsyncID);
}
else
{
LittleEndianWriter.WriteUInt32(buffer, offset + 32, Reserved);
LittleEndianWriter.WriteUInt32(buffer, offset + 36, TreeID);
}
LittleEndianWriter.WriteUInt64(buffer, offset + 40, SessionID);
if ((Flags & SMB2PacketHeaderFlags.Signed) > 0)
{
ByteWriter.WriteBytes(buffer, offset + 48, Signature);
}
}
public bool IsResponse
{
get
{
return (Flags & SMB2PacketHeaderFlags.ServerToRedir) > 0;
}
set
{
if (value)
{
Flags |= SMB2PacketHeaderFlags.ServerToRedir;
}
else
{
Flags &= ~SMB2PacketHeaderFlags.ServerToRedir;
}
}
}
public bool IsRelatedOperations
{
get
{
return (Flags & SMB2PacketHeaderFlags.RelatedOperations) > 0;
}
set
{
if (value)
{
Flags |= SMB2PacketHeaderFlags.RelatedOperations;
}
else
{
Flags &= ~SMB2PacketHeaderFlags.RelatedOperations;
}
}
}
public static bool IsValidSMB2Header(byte[] buffer)
{
if (buffer.Length >= 4)
{
byte[] signature = ByteReader.ReadBytes(buffer, 0, 4);
return ByteUtils.AreByteArraysEqual(signature, ProtocolSignature);
}
return false;
}
}
}

View file

@ -0,0 +1,150 @@
/* Copyright (C) 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,
* either version 3 of the License, or (at your option) any later version.
*/
using System;
using System.Collections.Generic;
using Utilities;
namespace SMBLibrary.SMB2
{
/// <summary>
/// [MS-SMB2] 2.2.13.2 - SMB2_CREATE_CONTEXT
/// </summary>
public class CreateContext
{
public int FixedLength = 16;
/// <summary>
/// The offset from the beginning of this Create Context to the beginning of a subsequent 8-byte aligned Create Context.
/// This field MUST be set to 0 if there are no subsequent contexts.
/// </summary>
public uint Next;
private ushort NameOffset; // The offset from the beginning of this structure to the 8-byte aligned name value
private ushort NameLength;
public ushort Reserved;
private ushort DataOffset; // The offset from the beginning of this structure to the 8-byte aligned data payload
private uint DataLength;
public string Name = String.Empty;
public byte[] Data = new byte[0];
public CreateContext()
{
}
public CreateContext(byte[] buffer, int offset)
{
Next = LittleEndianConverter.ToUInt32(buffer, offset + 0);
NameOffset = LittleEndianConverter.ToUInt16(buffer, offset + 4);
NameLength = LittleEndianConverter.ToUInt16(buffer, offset + 6);
Reserved = LittleEndianConverter.ToUInt16(buffer, offset + 8);
DataOffset = LittleEndianConverter.ToUInt16(buffer, offset + 10);
DataLength = LittleEndianConverter.ToUInt32(buffer, offset + 12);
if (NameLength > 0)
{
Name = ByteReader.ReadUTF16String(buffer, offset + NameOffset, NameLength / 2);
}
if (DataLength > 0)
{
Data = ByteReader.ReadBytes(buffer, offset + DataOffset, (int)DataLength);
}
}
private void WriteBytes(byte[] buffer, int offset)
{
LittleEndianWriter.WriteUInt32(buffer, offset + 0, Next);
NameOffset = 0;
NameLength = (ushort)(Name.Length * 2);
if (Name.Length > 0)
{
NameOffset = (ushort)FixedLength;
}
LittleEndianWriter.WriteUInt16(buffer, offset + 4, NameOffset);
LittleEndianWriter.WriteUInt16(buffer, offset + 6, NameLength);
LittleEndianWriter.WriteUInt16(buffer, offset + 8, Reserved);
DataOffset = 0;
DataLength = (uint)Data.Length;
if (Data.Length > 0)
{
int paddedNameLength = (int)Math.Ceiling((double)(Name.Length * 2) / 8) * 8;
DataOffset = (ushort)(FixedLength + paddedNameLength);
}
LittleEndianWriter.WriteUInt16(buffer, offset + 10, DataOffset);
ByteWriter.WriteUTF16String(buffer, NameOffset, Name);
ByteWriter.WriteBytes(buffer, DataOffset, Data);
}
public int Length
{
get
{
if (Data.Length > 0)
{
int paddedNameLength = (int)Math.Ceiling((double)(Name.Length * 2) / 8) * 8;
return FixedLength + paddedNameLength + Data.Length;
}
else
{
return FixedLength + Name.Length * 2;
}
}
}
public static List<CreateContext> ReadCreateContextList(byte[] buffer, int offset)
{
List<CreateContext> result = new List<CreateContext>();
CreateContext createContext;
do
{
createContext = new CreateContext(buffer, offset);
result.Add(createContext);
offset += (int)createContext.Next;
}
while (createContext.Next != 0);
return result;
}
public static void WriteCreateContextList(byte[] buffer, int offset, List<CreateContext> createContexts)
{
for (int index = 0; index < createContexts.Count; index++)
{
CreateContext createContext = createContexts[index];
int length = createContext.Length;
int paddedLength = (int)Math.Ceiling((double)length / 8) * 8;
if (index < createContexts.Count - 1)
{
createContext.Next = (uint)paddedLength;
}
else
{
createContext.Next = 0;
}
createContext.WriteBytes(buffer, offset);
offset += paddedLength;
}
}
public static int GetCreateContextListLength(List<CreateContext> createContexts)
{
int result = 0;
for(int index = 0; index < createContexts.Count; index++)
{
CreateContext createContext = createContexts[index];
int length = createContext.Length;
if (index < createContexts.Count - 1)
{
int paddedLength = (int)Math.Ceiling((double)length / 8) * 8;
result += paddedLength;
}
else
{
result += length;
}
}
return result;
}
}
}

View file

@ -0,0 +1,13 @@
using System;
namespace SMBLibrary.SMB2
{
[Flags]
public enum LockFlags : uint
{
SharedLock = 0x00000001, // SMB2_LOCKFLAG_SHARED_LOCK
ExclusiveLock = 0x00000002, // SMB2_LOCKFLAG_EXCLUSIVE_LOCK
Unlock = 0x00000004, // SMB2_LOCKFLAG_UNLOCK
FailImmediately = 0x00000008, // SMB2_LOCKFLAG_FAIL_IMMEDIATELY
}
}

View file

@ -0,0 +1,34 @@
/* Copyright (C) 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,
* either version 3 of the License, or (at your option) any later version.
*/
using System;
using Utilities;
namespace SMBLibrary.SMB2
{
/// <summary>
/// [MS-SMB2] 2.2.14.1 - SMB2_FILEID
/// </summary>
public struct FileID
{
public const int Length = 16;
public ulong Persistent;
public ulong Volatile;
public FileID(byte[] buffer, int offset)
{
Persistent = LittleEndianConverter.ToUInt64(buffer, offset + 0);
Volatile = LittleEndianConverter.ToUInt64(buffer, offset + 8);
}
public void WriteBytes(byte[] buffer, int offset)
{
LittleEndianWriter.WriteUInt64(buffer, offset + 0, Persistent);
LittleEndianWriter.WriteUInt64(buffer, offset + 8, Volatile);
}
}
}

View file

@ -0,0 +1,58 @@
/* Copyright (C) 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,
* either version 3 of the License, or (at your option) any later version.
*/
using System;
using System.Collections.Generic;
using Utilities;
namespace SMBLibrary.SMB2
{
public struct LockElement
{
public const int StructureLength = 24;
public ulong Offset;
public ulong Length;
public LockFlags Flags;
public uint Reserved;
public LockElement(byte[] buffer, int offset)
{
Offset = LittleEndianConverter.ToUInt64(buffer, offset + 0);
Length = LittleEndianConverter.ToUInt64(buffer, offset + 8);
Flags = (LockFlags)LittleEndianConverter.ToUInt32(buffer, offset + 16);
Reserved = LittleEndianConverter.ToUInt32(buffer, offset + 20);
}
public void WriteBytes(byte[] buffer, int offset)
{
LittleEndianWriter.WriteUInt64(buffer, offset + 0, Offset);
LittleEndianWriter.WriteUInt64(buffer, offset + 8, Length);
LittleEndianWriter.WriteUInt64(buffer, offset + 16, (uint)Flags);
LittleEndianWriter.WriteUInt64(buffer, offset + 20, Reserved);
}
public static List<LockElement> ReadLockList(byte[] buffer, int offset, int lockCount)
{
List<LockElement> result = new List<LockElement>();
for(int lockIndex = 0; lockIndex > lockCount; lockIndex++)
{
LockElement element = new LockElement(buffer, offset + lockIndex * StructureLength);
result.Add(element);
}
return result;
}
public static void WriteLockList(byte[] buffer, int offset, List<LockElement> locks)
{
for (int lockIndex = 0; lockIndex > locks.Count; lockIndex++)
{
LockElement element = locks[lockIndex];
element.WriteBytes(buffer, offset + lockIndex * StructureLength);
}
}
}
}

View file

@ -0,0 +1,99 @@
/* Copyright (C) 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,
* either version 3 of the License, or (at your option) any later version.
*/
using System;
using System.Collections.Generic;
using Utilities;
namespace SMBLibrary.SMB2
{
/// <summary>
/// [MS-SMB2] 2.2.3.1 - NEGOTIATE_CONTEXT
/// </summary>
public class NegotiateContext
{
public const int FixedLength = 8;
public NegotiateContextType ContextType;
private ushort DataLength;
public uint Reserved;
public byte[] Data = new byte[0];
public NegotiateContext()
{
}
public NegotiateContext(byte[] buffer, int offset)
{
ContextType = (NegotiateContextType)LittleEndianConverter.ToUInt16(buffer, offset + 0);
DataLength = LittleEndianConverter.ToUInt16(buffer, offset + 2);
Reserved = LittleEndianConverter.ToUInt32(buffer, offset + 4);
ByteReader.ReadBytes(buffer, offset + 8, DataLength);
}
public void WriteBytes(byte[] buffer, int offset)
{
DataLength = (ushort)Data.Length;
LittleEndianWriter.WriteUInt16(buffer, offset + 0, (ushort)ContextType);
LittleEndianWriter.WriteUInt16(buffer, offset + 2, DataLength);
LittleEndianWriter.WriteUInt32(buffer, offset + 4, Reserved);
ByteWriter.WriteBytes(buffer, offset + 8, Data);
}
public int Length
{
get
{
return FixedLength + Data.Length;
}
}
public static List<NegotiateContext> ReadNegotiateContextList(byte[] buffer, int offset, int count)
{
List<NegotiateContext> result = new List<NegotiateContext>();
for (int index = 0; index < count; index++)
{
NegotiateContext context = new NegotiateContext(buffer, offset);
result.Add(context);
offset += context.Length;
}
return result;
}
public static void WriteNegotiateContextList(byte[] buffer, int offset, List<NegotiateContext> negotiateContextList)
{
// Subsequent negotiate contexts MUST appear at the first 8-byte aligned offset following the previous negotiate context
for (int index = 0; index < negotiateContextList.Count; index++)
{
NegotiateContext context = negotiateContextList[index];
int length = context.Length;
int paddedLength = (int)Math.Ceiling((double)length / 8) * 8;
context.WriteBytes(buffer, offset);
offset += paddedLength;
}
}
public static int GetNegotiateContextListLength(List<NegotiateContext> negotiateContextList)
{
int result = 0;
for (int index = 0; index < negotiateContextList.Count; index++)
{
NegotiateContext context = negotiateContextList[index];
int length = context.Length;
if (index < negotiateContextList.Count - 1)
{
int paddedLength = (int)Math.Ceiling((double)length / 8) * 8;
result += paddedLength;
}
else
{
result += length;
}
}
return result;
}
}
}

View file

@ -398,6 +398,72 @@
<Compile Include="SMB1\TransactionSubcommands\TransactionWriteNamedPipeRequest.cs" />
<Compile Include="SMB1\TransactionSubcommands\TransactionWriteNamedPipeResponse.cs" />
<Compile Include="SMB1\UTimeHelper.cs" />
<Compile Include="SMB2\Commands\CancelRequest.cs" />
<Compile Include="SMB2\Commands\ChangeNotifyRequest.cs" />
<Compile Include="SMB2\Commands\ChangeNotifyResponse.cs" />
<Compile Include="SMB2\Commands\CloseRequest.cs" />
<Compile Include="SMB2\Commands\CloseResponse.cs" />
<Compile Include="SMB2\Commands\CreateRequest.cs" />
<Compile Include="SMB2\Commands\CreateResponse.cs" />
<Compile Include="SMB2\Commands\EchoRequest.cs" />
<Compile Include="SMB2\Commands\EchoResponse.cs" />
<Compile Include="SMB2\Commands\ErrorResponse.cs" />
<Compile Include="SMB2\Commands\FlushRequest.cs" />
<Compile Include="SMB2\Commands\FlushResponse.cs" />
<Compile Include="SMB2\Commands\IOCtlRequest.cs" />
<Compile Include="SMB2\Commands\IOCtlResponse.cs" />
<Compile Include="SMB2\Commands\LockRequest.cs" />
<Compile Include="SMB2\Commands\LockResponse.cs" />
<Compile Include="SMB2\Commands\LogoffRequest.cs" />
<Compile Include="SMB2\Commands\LogoffResponse.cs" />
<Compile Include="SMB2\Commands\NegotiateRequest.cs" />
<Compile Include="SMB2\Commands\NegotiateResponse.cs" />
<Compile Include="SMB2\Commands\QueryDirectoryRequest.cs" />
<Compile Include="SMB2\Commands\QueryDirectoryResponse.cs" />
<Compile Include="SMB2\Commands\QueryInfoRequest.cs" />
<Compile Include="SMB2\Commands\QueryInfoResponse.cs" />
<Compile Include="SMB2\Commands\ReadRequest.cs" />
<Compile Include="SMB2\Commands\ReadResponse.cs" />
<Compile Include="SMB2\Commands\SessionSetupRequest.cs" />
<Compile Include="SMB2\Commands\SessionSetupResponse.cs" />
<Compile Include="SMB2\Commands\SetInfoRequest.cs" />
<Compile Include="SMB2\Commands\SetInfoResponse.cs" />
<Compile Include="SMB2\Commands\SMB2Command.cs" />
<Compile Include="SMB2\Commands\TreeConnectRequest.cs" />
<Compile Include="SMB2\Commands\TreeConnectResponse.cs" />
<Compile Include="SMB2\Commands\TreeDisconnectRequest.cs" />
<Compile Include="SMB2\Commands\TreeDisconnectResponse.cs" />
<Compile Include="SMB2\Commands\WriteRequest.cs" />
<Compile Include="SMB2\Commands\WriteResponse.cs" />
<Compile Include="SMB2\Enums\ChangeNotify\ChangeNotifyFlags.cs" />
<Compile Include="SMB2\Enums\ChangeNotify\NotifyChange.cs" />
<Compile Include="SMB2\Enums\Close\CloseFlags.cs" />
<Compile Include="SMB2\Enums\Create\CreateAction.cs" />
<Compile Include="SMB2\Enums\Create\CreateResponseFlags.cs" />
<Compile Include="SMB2\Enums\Create\ImpersonationLevel.cs" />
<Compile Include="SMB2\Enums\Create\OplockLevel.cs" />
<Compile Include="SMB2\Enums\InfoType.cs" />
<Compile Include="SMB2\Enums\IOCtl\IOCtlRequestFlags.cs" />
<Compile Include="SMB2\Enums\Negotiate\NegotiateContextType.cs" />
<Compile Include="SMB2\Enums\Negotiate\SecurityMode.cs" />
<Compile Include="SMB2\Enums\Negotiate\ServerCapabilities.cs" />
<Compile Include="SMB2\Enums\Negotiate\SMB2Dialect.cs" />
<Compile Include="SMB2\Enums\QueryDirectory\QueryDirectoryFlags.cs" />
<Compile Include="SMB2\Enums\Read\ReadFlags.cs" />
<Compile Include="SMB2\Enums\SessionSetup\SessionFlags.cs" />
<Compile Include="SMB2\Enums\SessionSetup\SessionSetupFlags.cs" />
<Compile Include="SMB2\Enums\SMB2CommandName.cs" />
<Compile Include="SMB2\Enums\SMB2PacketHeaderFlags.cs" />
<Compile Include="SMB2\Enums\TreeConnect\ShareCapabilities.cs" />
<Compile Include="SMB2\Enums\TreeConnect\ShareFlags.cs" />
<Compile Include="SMB2\Enums\TreeConnect\ShareType.cs" />
<Compile Include="SMB2\Enums\Write\WriteFlags.cs" />
<Compile Include="SMB2\SMB2Header.cs" />
<Compile Include="SMB2\Structures\CreateContext.cs" />
<Compile Include="SMB2\Structures\Enums\LockFlags.cs" />
<Compile Include="SMB2\Structures\FileID.cs" />
<Compile Include="SMB2\Structures\LockElement.cs" />
<Compile Include="SMB2\Structures\NegotiateContext.cs" />
<Compile Include="Structures\ACE\AccessAllowedACE.cs" />
<Compile Include="Structures\ACE\ACE.cs" />
<Compile Include="Structures\ACE\AceHeader.cs" />