/////////////////////////////////////////////////////////////////////////////// // // 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 }