350 lines
12 KiB
Plaintext
350 lines
12 KiB
Plaintext
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//
|
|
|
|
using System;
|
|
using System.Diagnostics;
|
|
using System.Collections.Generic;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
using Microsoft.Singularity;
|
|
using Microsoft.SingSharp;
|
|
using Microsoft.Singularity.Channels;
|
|
using Utils;
|
|
|
|
namespace Smb.Protocol
|
|
{
|
|
#region SMB Requests
|
|
// This region contains structures that define many of the SMB requests that we use,
|
|
// and the responses that we will receive from servers. Each request begins with
|
|
// an instance of SmbHeader.
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack=1)]
|
|
pointerfree struct SmbNegotiateRequest
|
|
{
|
|
public SmbHeader Header;
|
|
public ushort ByteCount;
|
|
// repeated sets of dialect strings follow
|
|
}
|
|
|
|
public static class SmbDialect
|
|
{
|
|
public const string PcNetworkProgram = "PC NETWORK PROGRAM 1.0";
|
|
public const string Lanman1 = "LANMAN1.0";
|
|
public const string WindowsForWorkgroups = "Windows for Workgroups 3.1a";
|
|
public const string LM1_2x002 = "LM1.2X002";
|
|
public const string NTLM012 = "NT LM 0.12";
|
|
}
|
|
|
|
[Flags]
|
|
public enum SmbNegotiateSecurityMode : byte
|
|
{
|
|
SupportsUserShareLevel = (1 << 0),
|
|
SupportsChallengeResponseAuthentication = (1 << 1),
|
|
SecuritySignaturesEnabled = (1 << 2),
|
|
SignaturesRequired = (1 << 3),
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack=1)]
|
|
pointerfree struct SmbNegotiateResponse17
|
|
{
|
|
public SmbHeader Header;
|
|
public ushort DialectIndex;
|
|
public byte SecurityMode;
|
|
public ushort MaxMpxCount;
|
|
public ushort MaxNumberVcs;
|
|
public uint MaxBufferSize;
|
|
public uint MaxRawSize;
|
|
public uint SessionKey;
|
|
public uint Capabilities;
|
|
public uint SystemTimeLow;
|
|
public uint SystemTimeHigh;
|
|
public ushort ServerTimeZone;
|
|
public byte EncryptionKeyLength;
|
|
|
|
// this field is not included in the parameter count
|
|
public ushort ByteCount;
|
|
|
|
// If the negotiate response is NOT using extended security, then the
|
|
// following variable-length fields come next:
|
|
//
|
|
// char OemDomainName[]
|
|
}
|
|
|
|
|
|
/*
|
|
typedef struct _REQ_SESSION_SETUP_ANDX {
|
|
UCHAR WordCount; // Count of parameter words = 10
|
|
UCHAR AndXCommand; // Secondary (X) command; 0xFF = none
|
|
UCHAR AndXReserved; // Reserved (must be 0)
|
|
_USHORT( AndXOffset ); // Offset to next command WordCount
|
|
_USHORT( MaxBufferSize ); // Consumer's maximum buffer size
|
|
_USHORT( MaxMpxCount ); // Actual maximum multiplexed pending requests
|
|
_USHORT( VcNumber ); // 0 = first (only), nonzero=additional VC number
|
|
_ULONG( SessionKey ); // Session key (valid iff VcNumber != 0)
|
|
_USHORT( PasswordLength ); // Account password size
|
|
_ULONG( Reserved );
|
|
_USHORT( ByteCount ); // Count of data bytes; min = 0
|
|
UCHAR Buffer[1]; // Buffer containing:
|
|
//UCHAR AccountPassword[]; // Account Password
|
|
//UCHAR AccountName[]; // Account Name
|
|
//UCHAR PrimaryDomain[]; // Client's primary domain
|
|
//UCHAR NativeOS[]; // Client's native operating system
|
|
//UCHAR NativeLanMan[]; // Client's native LAN Manager type
|
|
} REQ_SESSION_SETUP_ANDX;
|
|
typedef REQ_SESSION_SETUP_ANDX SMB_UNALIGNED *PREQ_SESSION_SETUP_ANDX;
|
|
|
|
|
|
This is the "old school" SessionSetupAndX. Length of parameter block is 11.
|
|
*/
|
|
[StructLayout(LayoutKind.Explicit, Size=22, Pack=1)]
|
|
pointerfree struct SessionSetupAndX_Old
|
|
{
|
|
// Parameter block, including the AndX data
|
|
[FieldOffset(0)] public byte AndXCommand;
|
|
[FieldOffset(1)] public byte AndXPadding;
|
|
[FieldOffset(2)] public ushort AndXOffset;
|
|
[FieldOffset(4)] public ushort MaxBufferSize;
|
|
[FieldOffset(6)] public ushort MaxMpxCount;
|
|
[FieldOffset(8)] public ushort VcNumber;
|
|
[FieldOffset(10)] public ushort SessionKey0;
|
|
[FieldOffset(12)] public ushort SessionKey1;
|
|
[FieldOffset(14)] public ushort PasswordLength;
|
|
[FieldOffset(16)] public ushort Reserved0;
|
|
[FieldOffset(18)] public ushort Reserved1;
|
|
[FieldOffset(20)] public ushort ByteCount;
|
|
// variable-length data follows
|
|
|
|
public const int SizeOf = 22;
|
|
// public const int ParameterCount = 10;
|
|
}
|
|
|
|
/*
|
|
Client Request
|
|
============================== Description
|
|
=====================================
|
|
UCHAR WordCount; Count of parameter words = 12
|
|
UCHAR AndXCommand; Secondary (X) command; 0xFF = none
|
|
UCHAR AndXReserved; Reserved (must be 0)
|
|
USHORT AndXOffset; Offset to next command WordCount
|
|
USHORT MaxBufferSize; Client's maximum buffer size
|
|
USHORT MaxMpxCount; Actual maximum multiplexed pending requests
|
|
USHORT VcNumber; 0 = first (only), nonzero=additional VC number
|
|
ULONG SessionKey; Session key (valid iff VcNumber != 0)
|
|
USHORT SecurityBlobLength; Length of opaque security blob
|
|
ULONG Reserved; must be 0
|
|
ULONG Capabilities; Client capabilities
|
|
USHORT ByteCount; Count of data bytes; min = 0
|
|
UCHAR SecurityBlob[] The opaque security blob
|
|
STRING NativeOS[]; Client's native operating system, Unicode
|
|
STRING NativeLanMan[]; Client's native LAN Manager type, Unicode
|
|
|
|
|
|
NetMon interprets this as the payload being NTLMSSP
|
|
|
|
|
|
*/
|
|
|
|
[StructLayout(LayoutKind.Explicit, Size=22, Pack=1)]
|
|
pointerfree struct SessionSetupAndX_12
|
|
{
|
|
// Parameter block, including the AndX data
|
|
[FieldOffset(0)] public byte AndXCommand;
|
|
[FieldOffset(1)] public byte AndXPadding;
|
|
[FieldOffset(2)] public ushort AndXOffset;
|
|
|
|
[FieldOffset(4)] public ushort MaxBufferSize;
|
|
[FieldOffset(6)] public ushort MaxMpxCount;
|
|
|
|
[FieldOffset(8)] public ushort VcNumber;
|
|
[FieldOffset(10)] public ushort SessionKey0;
|
|
|
|
[FieldOffset(12)] public ushort SessionKey1;
|
|
[FieldOffset(14)] public ushort SecurityBlobLength;
|
|
|
|
[FieldOffset(16)] public ushort Reserved0;
|
|
[FieldOffset(18)] public ushort Reserved1;
|
|
|
|
[FieldOffset(20)] public uint Capabilities;
|
|
|
|
[FieldOffset(24)] public ushort ByteCount;
|
|
|
|
// variable-length data follows
|
|
// byte[] SecurityBlob;
|
|
// char[] NativeOS; // in Unicode
|
|
// char[] NativeLanMan; // in Unicode
|
|
|
|
|
|
public const int SizeOf = 26;
|
|
public const int ParameterCount = 12;
|
|
}
|
|
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack=1)]
|
|
pointerfree struct SmbSessionSetupAndXResponse
|
|
{
|
|
public SmbHeader Header;
|
|
public byte AndXCommand;
|
|
public byte AndXReserved;
|
|
public ushort AndXOffset;
|
|
public ushort Action;
|
|
public ushort ByteCount;
|
|
// string NativeOS
|
|
// string NativeLanMan
|
|
// string PrimaryDomain
|
|
}
|
|
|
|
/*
|
|
|
|
This structure is used with the "NT LM 0.12" dialect.
|
|
It indicates that the client wants to setup a session, and does not want to use "extended security".
|
|
Extended security uses SPNEGO, which is a general security token exchange mechanism, described in
|
|
RFC 2478. This SESSION SETUP message can either use cleartext passwords (bad!), or can use NTLM
|
|
challenge/response messages. The LM hash response is stored in the CaseInsensitivePassword field,
|
|
and the NT hash response (marginally more secure) is stored in the CaseSensitivePassword field.
|
|
|
|
*/
|
|
[StructLayout(LayoutKind.Sequential, Pack=1)]
|
|
pointerfree struct SmbSessionSetupAndXRequest13
|
|
{
|
|
public SmbHeader Header;
|
|
|
|
// Parameter block, including the AndX data
|
|
public byte AndXCommand;
|
|
public byte AndXPadding;
|
|
public ushort AndXOffset;
|
|
public ushort MaxBufferSize;
|
|
public ushort MaxMpxCount;
|
|
public ushort VcNumber;
|
|
public uint SessionKey;
|
|
public ushort CaseInsensitivePasswordLength;
|
|
public ushort CaseSensitivePasswordLength;
|
|
public uint Reserved;
|
|
public uint Capabilities;
|
|
public ushort ByteCount;
|
|
|
|
// byte zero padding; // this is here to pad Unicode to 2-byte boundary if necessary
|
|
// STRING AccountName;
|
|
// STRING PrimaryDomain;
|
|
// STRING NativeOS;
|
|
// STRING NativeLanMan;
|
|
|
|
|
|
// variable-length data follows
|
|
// byte[] SecurityBlob;
|
|
// char[] NativeOS; // in Unicode
|
|
// char[] NativeLanMan; // in Unicode
|
|
|
|
public const int ParameterCount = 13;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
typedef struct _REQ_NT_SESSION_SETUP_ANDX {
|
|
UCHAR WordCount; // Count of parameter words = 13
|
|
UCHAR AndXCommand; // Secondary (X) command; 0xFF = none
|
|
UCHAR AndXReserved; // Reserved (must be 0)
|
|
_USHORT( AndXOffset ); // Offset to next command WordCount
|
|
_USHORT( MaxBufferSize ); // Consumer's maximum buffer size
|
|
_USHORT( MaxMpxCount ); // Actual maximum multiplexed pending requests
|
|
_USHORT( VcNumber ); // 0 = first (only), nonzero=additional VC number
|
|
_ULONG( SessionKey ); // Session key (valid iff VcNumber != 0)
|
|
_USHORT( CaseInsensitivePasswordLength ); // Account password size, ANSI
|
|
_USHORT( CaseSensitivePasswordLength ); // Account password size, Unicode
|
|
_ULONG( Reserved);
|
|
_ULONG( Capabilities ); // Client capabilities
|
|
_USHORT( ByteCount ); // Count of data bytes; min = 0
|
|
UCHAR Buffer[1]; // Buffer containing:
|
|
//UCHAR CaseInsensitivePassword[]; // Account Password, ANSI
|
|
//UCHAR CaseSensitivePassword[]; // Account Password, Unicode
|
|
//UCHAR AccountName[]; // Account Name
|
|
//UCHAR PrimaryDomain[]; // Client's primary domain
|
|
//UCHAR NativeOS[]; // Client's native operating system
|
|
//UCHAR NativeLanMan[]; // Client's native LAN Manager type
|
|
} REQ_NT_SESSION_SETUP_ANDX;
|
|
typedef REQ_NT_SESSION_SETUP_ANDX SMB_UNALIGNED *PREQ_NT_SESSION_SETUP_ANDX;
|
|
*/
|
|
#if false
|
|
[StructLayout(LayoutKind.Explicit, Size=26, Pack=1)]
|
|
pointerfree struct SessionSetupAndX_Nt
|
|
{
|
|
// Parameter block, including the AndX data
|
|
[FieldOffset(0)] public byte AndXCommand;
|
|
[FieldOffset(1)] public byte AndXPadding;
|
|
[FieldOffset(2)] public ushort AndXOffset;
|
|
[FieldOffset(4)] public ushort MaxBufferSize;
|
|
[FieldOffset(6)] public ushort MaxMpxCount;
|
|
[FieldOffset(8)] public ushort VcNumber;
|
|
[FieldOffset(10)] public ushort SessionKey0;
|
|
[FieldOffset(12)] public ushort SessionKey1;
|
|
[FieldOffset(14)] public ushort CaseInsensitivePasswordLength;
|
|
[FieldOffset(16)] public ushort CaseSensensitivePasswordLength;
|
|
[FieldOffset(18)] public ushort Reserved0;
|
|
[FieldOffset(20)] public ushort Reserved1;
|
|
[FieldOffset(22)] public ushort Capabilities0;
|
|
[FieldOffset(24)] public ushort Capabilities1;
|
|
[FieldOffset(26)] public ushort ByteCount;
|
|
// variable-length data follows
|
|
|
|
public const int SizeOf = 26;
|
|
public const int ParameterCount = 13;
|
|
}
|
|
#endif
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack=1)]
|
|
pointerfree struct SmbTreeConnectAndX
|
|
{
|
|
public SmbHeader Header;
|
|
public byte AndXCommand;
|
|
public byte AndXReserved;
|
|
public ushort AndXOffset;
|
|
public ushort Flags;
|
|
public ushort PasswordLength;
|
|
public ushort ByteCount;
|
|
// byte Password[];
|
|
// string Path;
|
|
// string Service;
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
pointerfree struct AndXParameterBlock
|
|
{
|
|
public byte NextCommand;
|
|
public byte Padding0;
|
|
public ushort NextCommandOffset;
|
|
|
|
public AndXParameterBlock(SmbCommand command, ushort offset)
|
|
{
|
|
NextCommand = (byte)command;
|
|
NextCommandOffset = offset;
|
|
Padding0 = 0;
|
|
}
|
|
}
|
|
|
|
[Flags]
|
|
enum SmbCapability
|
|
{
|
|
RawMode = 0x0001,
|
|
MpxMode = 0x0002,
|
|
Unicode = 0x0004,
|
|
LargeFiles = 0x0008,
|
|
NtSmbs = 0x0010,
|
|
RpcRemoteApis = 0x0020,
|
|
NtStatus = 0x0040,
|
|
Level2Oplocks = 0x0080,
|
|
LockAndRead = 0x0100,
|
|
NtFind = 0x0200,
|
|
Dfs = 0x1000, // This server is DFS aware
|
|
InfolevelPassthru = 0x2000, // NT information level requests can pass through
|
|
LargeReadx = 0x4000, // Server supports oversized READ&X on files
|
|
LargeWritex = 0x8000,
|
|
}
|
|
|
|
|
|
#endregion
|
|
}
|