mirror of
https://github.com/TalAloni/SMBLibrary.git
synced 2025-04-29 10:17:48 +02:00
SMBServer v1.0.5
This commit is contained in:
parent
b75820452d
commit
bd1006cb81
400 changed files with 28062 additions and 0 deletions
74
SMBLibrary/Authentication/AuthenticateMessage/AVPairUtils.cs
Normal file
74
SMBLibrary/Authentication/AuthenticateMessage/AVPairUtils.cs
Normal file
|
@ -0,0 +1,74 @@
|
|||
/* Copyright (C) 2014 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 System.Text;
|
||||
using Utilities;
|
||||
|
||||
namespace SMBLibrary.Authentication
|
||||
{
|
||||
public class AVPairUtils
|
||||
{
|
||||
public static byte[] GetAVPairSequence(string domainName, string computerName)
|
||||
{
|
||||
KeyValuePairList<AVPairKey, byte[]> pairs = new KeyValuePairList<AVPairKey, byte[]>();
|
||||
pairs.Add(AVPairKey.NbDomainName, UnicodeEncoding.Unicode.GetBytes(domainName));
|
||||
pairs.Add(AVPairKey.NbComputerName, UnicodeEncoding.Unicode.GetBytes(computerName));
|
||||
return AVPairUtils.GetAVPairSequenceBytes(pairs);
|
||||
}
|
||||
|
||||
public static byte[] GetAVPairSequenceBytes(KeyValuePairList<AVPairKey, byte[]> pairs)
|
||||
{
|
||||
int length = 0;
|
||||
foreach (KeyValuePair<AVPairKey, byte[]> pair in pairs)
|
||||
{
|
||||
length += 4 + pair.Value.Length;
|
||||
}
|
||||
length += 4;
|
||||
|
||||
byte[] result = new byte[length];
|
||||
int offset = 0;
|
||||
foreach (KeyValuePair<AVPairKey, byte[]> pair in pairs)
|
||||
{
|
||||
WriteAVPair(result, ref offset, pair.Key, pair.Value);
|
||||
}
|
||||
LittleEndianWriter.WriteUInt16(result, ref offset, (ushort)AVPairKey.EOL);
|
||||
LittleEndianWriter.WriteUInt16(result, ref offset, 0);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void WriteAVPair(byte[] buffer, ref int offset, AVPairKey key, byte[] value)
|
||||
{
|
||||
LittleEndianWriter.WriteUInt16(buffer, ref offset, (ushort)key);
|
||||
LittleEndianWriter.WriteUInt16(buffer, ref offset, (ushort)value.Length);
|
||||
ByteWriter.WriteBytes(buffer, ref offset, value);
|
||||
}
|
||||
|
||||
public static KeyValuePairList<AVPairKey, byte[]> ReadAVPairSequence(byte[] buffer, int offset)
|
||||
{
|
||||
KeyValuePairList<AVPairKey, byte[]> result = new KeyValuePairList<AVPairKey,byte[]>();
|
||||
AVPairKey key = (AVPairKey)LittleEndianConverter.ToUInt16(buffer, offset);
|
||||
while (key != AVPairKey.EOL)
|
||||
{
|
||||
KeyValuePair<AVPairKey, byte[]> pair = ReadAVPair(buffer, ref offset);
|
||||
result.Add(pair);
|
||||
key = (AVPairKey)LittleEndianConverter.ToUInt16(buffer, offset);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static KeyValuePair<AVPairKey, byte[]> ReadAVPair(byte[] buffer, ref int offset)
|
||||
{
|
||||
AVPairKey key = (AVPairKey)LittleEndianReader.ReadUInt16(buffer, ref offset);
|
||||
ushort length = LittleEndianReader.ReadUInt16(buffer, ref offset);
|
||||
byte[] value = ByteReader.ReadBytes(buffer, ref offset, length);
|
||||
return new KeyValuePair<AVPairKey, byte[]>(key, value);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
/* Copyright (C) 2014 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 System.Text;
|
||||
using Utilities;
|
||||
|
||||
namespace SMBLibrary.Authentication
|
||||
{
|
||||
/// <summary>
|
||||
/// [MS-NLMP] AUTHENTICATE_MESSAGE (Type 3 Message)
|
||||
/// </summary>
|
||||
public class AuthenticateMessage
|
||||
{
|
||||
public string Signature; // 8 bytes
|
||||
public MessageTypeName MessageType;
|
||||
public byte[] LmChallengeResponse;
|
||||
public byte[] NtChallengeResponse;
|
||||
public string DomainName;
|
||||
public string UserName;
|
||||
public string WorkStation;
|
||||
public byte[] EncryptedRandomSessionKey;
|
||||
public NegotiateFlags NegotiateFlags;
|
||||
public Version Version;
|
||||
// 16-byte MIC field is omitted for Windows NT / 2000 / XP / Server 2003
|
||||
|
||||
public AuthenticateMessage()
|
||||
{
|
||||
Signature = AuthenticationMessageUtils.ValidSignature;
|
||||
MessageType = MessageTypeName.Authenticate;
|
||||
DomainName = String.Empty;
|
||||
UserName = String.Empty;
|
||||
WorkStation = String.Empty;
|
||||
EncryptedRandomSessionKey = new byte[0];
|
||||
}
|
||||
|
||||
public AuthenticateMessage(byte[] buffer)
|
||||
{
|
||||
Signature = ByteReader.ReadAnsiString(buffer, 0, 8);
|
||||
MessageType = (MessageTypeName)LittleEndianConverter.ToUInt32(buffer, 8);
|
||||
LmChallengeResponse = AuthenticationMessageUtils.ReadBufferPointer(buffer, 12);
|
||||
NtChallengeResponse = AuthenticationMessageUtils.ReadBufferPointer(buffer, 20);
|
||||
DomainName = AuthenticationMessageUtils.ReadUnicodeStringBufferPointer(buffer, 28);
|
||||
UserName = AuthenticationMessageUtils.ReadUnicodeStringBufferPointer(buffer, 36);
|
||||
WorkStation = AuthenticationMessageUtils.ReadUnicodeStringBufferPointer(buffer, 44);
|
||||
EncryptedRandomSessionKey = AuthenticationMessageUtils.ReadBufferPointer(buffer, 52);
|
||||
NegotiateFlags = (NegotiateFlags)LittleEndianConverter.ToUInt32(buffer, 60);
|
||||
if ((NegotiateFlags & NegotiateFlags.NegotiateVersion) > 0)
|
||||
{
|
||||
Version = new Version(buffer, 64);
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] GetBytes()
|
||||
{
|
||||
int fixedLength = 64;
|
||||
|
||||
if ((NegotiateFlags & NegotiateFlags.NegotiateVersion) > 0)
|
||||
{
|
||||
fixedLength += 8;
|
||||
}
|
||||
|
||||
int payloadLength = LmChallengeResponse.Length + NtChallengeResponse.Length + DomainName.Length * 2 + UserName.Length * 2 + WorkStation.Length * 2 + EncryptedRandomSessionKey.Length;
|
||||
byte[] buffer = new byte[fixedLength + payloadLength];
|
||||
ByteWriter.WriteAnsiString(buffer, 0, AuthenticationMessageUtils.ValidSignature, 8);
|
||||
LittleEndianWriter.WriteUInt32(buffer, 8, (uint)MessageType);
|
||||
LittleEndianWriter.WriteUInt32(buffer, 60, (uint)NegotiateFlags);
|
||||
if ((NegotiateFlags & NegotiateFlags.NegotiateVersion) > 0)
|
||||
{
|
||||
Version.WriteBytes(buffer, 64);
|
||||
}
|
||||
|
||||
int offset = fixedLength;
|
||||
AuthenticationMessageUtils.WriteBufferPointer(buffer, 12, (ushort)LmChallengeResponse.Length, (uint)offset);
|
||||
ByteWriter.WriteBytes(buffer, ref offset, LmChallengeResponse);
|
||||
AuthenticationMessageUtils.WriteBufferPointer(buffer, 20, (ushort)NtChallengeResponse.Length, (uint)offset);
|
||||
ByteWriter.WriteBytes(buffer, ref offset, NtChallengeResponse);
|
||||
AuthenticationMessageUtils.WriteBufferPointer(buffer, 28, (ushort)(DomainName.Length * 2), (uint)offset);
|
||||
ByteWriter.WriteUTF16String(buffer, ref offset, DomainName);
|
||||
AuthenticationMessageUtils.WriteBufferPointer(buffer, 36, (ushort)(UserName.Length * 2), (uint)offset);
|
||||
ByteWriter.WriteUTF16String(buffer, ref offset, UserName);
|
||||
AuthenticationMessageUtils.WriteBufferPointer(buffer, 44, (ushort)(WorkStation.Length * 2), (uint)offset);
|
||||
ByteWriter.WriteUTF16String(buffer, ref offset, WorkStation);
|
||||
AuthenticationMessageUtils.WriteBufferPointer(buffer, 52, (ushort)EncryptedRandomSessionKey.Length, (uint)offset);
|
||||
ByteWriter.WriteBytes(buffer, ref offset, EncryptedRandomSessionKey);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
/* Copyright (C) 2014 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 System.Text;
|
||||
using Utilities;
|
||||
|
||||
namespace SMBLibrary.Authentication
|
||||
{
|
||||
public class AuthenticationMessageUtils
|
||||
{
|
||||
public const string ValidSignature = "NTLMSSP\0";
|
||||
|
||||
public static string ReadAnsiStringBufferPointer(byte[] buffer, int offset)
|
||||
{
|
||||
byte[] bytes = ReadBufferPointer(buffer, offset);
|
||||
return ASCIIEncoding.Default.GetString(bytes);
|
||||
}
|
||||
|
||||
public static string ReadUnicodeStringBufferPointer(byte[] buffer, int offset)
|
||||
{
|
||||
byte[] bytes = ReadBufferPointer(buffer, offset);
|
||||
return UnicodeEncoding.Unicode.GetString(bytes);
|
||||
}
|
||||
|
||||
public static byte[] ReadBufferPointer(byte[] buffer, int offset)
|
||||
{
|
||||
ushort length = LittleEndianConverter.ToUInt16(buffer, offset);
|
||||
ushort maxLength = LittleEndianConverter.ToUInt16(buffer, offset + 2);
|
||||
uint bufferOffset = LittleEndianConverter.ToUInt32(buffer, offset + 4);
|
||||
|
||||
if (length == 0)
|
||||
{
|
||||
return new byte[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
return ByteReader.ReadBytes(buffer, (int)bufferOffset, length);
|
||||
}
|
||||
}
|
||||
|
||||
public static void WriteBufferPointer(byte[] buffer, int offset, ushort bufferLength, uint bufferOffset)
|
||||
{
|
||||
LittleEndianWriter.WriteUInt16(buffer, offset, bufferLength);
|
||||
LittleEndianWriter.WriteUInt16(buffer, offset + 2, bufferLength);
|
||||
LittleEndianWriter.WriteUInt32(buffer, offset + 4, bufferOffset);
|
||||
}
|
||||
|
||||
public static bool IsSignatureValid(byte[] messageBytes)
|
||||
{
|
||||
string signature = ByteReader.ReadAnsiString(messageBytes, 0, 8);
|
||||
return (signature == ValidSignature);
|
||||
}
|
||||
|
||||
public static MessageTypeName GetMessageType(byte[] messageBytes)
|
||||
{
|
||||
return (MessageTypeName)LittleEndianConverter.ToUInt32(messageBytes, 8);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
/* Copyright (C) 2014 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 System.Text;
|
||||
using Utilities;
|
||||
|
||||
namespace SMBLibrary.Authentication
|
||||
{
|
||||
/// <summary>
|
||||
/// [MS-NLMP] CHALLENGE_MESSAGE (Type 2 Message)
|
||||
/// </summary>
|
||||
public class ChallengeMessage
|
||||
{
|
||||
public string Signature; // 8 bytes
|
||||
public MessageTypeName MessageType;
|
||||
public string TargetName;
|
||||
public NegotiateFlags NegotiateFlags;
|
||||
public byte[] ServerChallenge; // 8 bytes
|
||||
// Reserved - 8 bytes
|
||||
public byte[] TargetInfo; // sequence of AV_PAIR structures
|
||||
public Version Version;
|
||||
|
||||
public ChallengeMessage()
|
||||
{
|
||||
Signature = AuthenticationMessageUtils.ValidSignature;
|
||||
MessageType = MessageTypeName.Challenge;
|
||||
}
|
||||
|
||||
public ChallengeMessage(byte[] buffer)
|
||||
{
|
||||
Signature = ByteReader.ReadAnsiString(buffer, 0, 8);
|
||||
MessageType = (MessageTypeName)LittleEndianConverter.ToUInt32(buffer, 8);
|
||||
TargetName = AuthenticationMessageUtils.ReadUnicodeStringBufferPointer(buffer, 12);
|
||||
NegotiateFlags = (NegotiateFlags)LittleEndianConverter.ToUInt32(buffer, 20);
|
||||
ServerChallenge = ByteReader.ReadBytes(buffer, 24, 8);
|
||||
// Reserved
|
||||
TargetInfo = AuthenticationMessageUtils.ReadBufferPointer(buffer, 40);
|
||||
if ((NegotiateFlags & NegotiateFlags.NegotiateVersion) > 0)
|
||||
{
|
||||
Version = new Version(buffer, 48);
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] GetBytes()
|
||||
{
|
||||
int fixedLength = 48;
|
||||
if ((NegotiateFlags & NegotiateFlags.NegotiateVersion) > 0)
|
||||
{
|
||||
fixedLength += 8;
|
||||
}
|
||||
|
||||
int payloadLength = TargetName.Length * 2 + TargetInfo.Length;
|
||||
byte[] buffer = new byte[fixedLength + payloadLength];
|
||||
ByteWriter.WriteAnsiString(buffer, 0, AuthenticationMessageUtils.ValidSignature, 8);
|
||||
LittleEndianWriter.WriteUInt32(buffer, 8, (uint)MessageType);
|
||||
LittleEndianWriter.WriteUInt32(buffer, 20, (uint)NegotiateFlags);
|
||||
ByteWriter.WriteBytes(buffer, 24, ServerChallenge);
|
||||
if ((NegotiateFlags & NegotiateFlags.NegotiateVersion) > 0)
|
||||
{
|
||||
Version.WriteBytes(buffer, 48);
|
||||
}
|
||||
|
||||
int offset = fixedLength;
|
||||
AuthenticationMessageUtils.WriteBufferPointer(buffer, 12, (ushort)(TargetName.Length * 2), (uint)offset);
|
||||
ByteWriter.WriteUTF16String(buffer, ref offset, TargetName);
|
||||
AuthenticationMessageUtils.WriteBufferPointer(buffer, 40, (ushort)TargetInfo.Length, (uint)offset);
|
||||
ByteWriter.WriteBytes(buffer, ref offset, TargetInfo);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
|
||||
namespace SMBLibrary.Authentication
|
||||
{
|
||||
public enum AVPairKey : ushort
|
||||
{
|
||||
EOL = 0x0000,
|
||||
NbComputerName = 0x0001, // Unicode
|
||||
NbDomainName = 0x0002, // Unicode
|
||||
DnsComputerName = 0x0003, // Unicode
|
||||
DnsDomainName = 0x0004, // Unicode
|
||||
DnsTreeName = 0x0005, // Unicode
|
||||
Flags = 0x0006, // UInt32
|
||||
Timestamp = 0x0006, // Filetime
|
||||
SingleHost = 0x0008, // platform-specific BLOB
|
||||
TargetName = 0x0009, // Unicode
|
||||
ChannelBindings = 0x000A, // MD5 Hash
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
|
||||
namespace SMBLibrary.Authentication
|
||||
{
|
||||
public enum MessageTypeName : uint
|
||||
{
|
||||
Negotiate = 0x01,
|
||||
Challenge = 0x02,
|
||||
Authenticate = 0x03,
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
using System;
|
||||
|
||||
namespace SMBLibrary.Authentication
|
||||
{
|
||||
[Flags]
|
||||
public enum NegotiateFlags : uint
|
||||
{
|
||||
NegotiateUnicode = 0x01, // NTLMSSP_NEGOTIATE_UNICODE
|
||||
NegotiateOEM = 0x02, // NTLM_NEGOTIATE_OEM
|
||||
RequestTarget = 0x04, // NTLMSSP_REQUEST_TARGET
|
||||
NegotiateSign = 0x10, // NTLMSSP_NEGOTIATE_SIGN
|
||||
NegotiateSeal = 0x20, // NTLMSSP_NEGOTIATE_SEAL
|
||||
NegotiateDatagram = 0x40, // NTLMSSP_NEGOTIATE_DATAGRAM
|
||||
|
||||
/// <summary>
|
||||
/// NegotiateLanManagerKey and NegotiateExtendedSecurity are mutually exclusive
|
||||
/// If both are set then NegotiateLanManagerKey must be ignored
|
||||
/// </summary>
|
||||
NegotiateLanManagerKey = 0x80, // NTLMSSP_NEGOTIATE_LM_KEY
|
||||
NegotiateNTLMKey = 0x200, // NTLMSSP_NEGOTIATE_NTLM
|
||||
//NegotiateNTOnly = 0x400, // Unused, must be clear
|
||||
|
||||
/// <summary>
|
||||
/// If set, the connection SHOULD be anonymous
|
||||
/// </summary>
|
||||
NegotiateAnonymous = 0x800,
|
||||
|
||||
NegotiateOEMDomainSupplied = 0x1000, // NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED
|
||||
NegotiateOEMWorkstationSupplied = 0x2000, // NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED
|
||||
NegotiateAlwaysSign = 0x8000, // NTLMSSP_NEGOTIATE_ALWAYS_SIGN
|
||||
NegotiateTargetTypeDomain = 0x10000, // NTLMSSP_TARGET_TYPE_DOMAIN
|
||||
NegotiateTargetTypeServer = 0x20000, // NTLMSSP_TARGET_TYPE_SERVER
|
||||
NegotiateTargetTypeShare = 0x40000, // Unused, must be clear
|
||||
|
||||
/// <summary>
|
||||
/// NegotiateLanManagerKey and NegotiateExtendedSecurity are mutually exclusive
|
||||
/// If both are set then NegotiateLanManagerKey must be ignored
|
||||
/// </summary>
|
||||
NegotiateExtendedSecurity = 0x80000, // NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY
|
||||
NegotiateIdentify = 0x100000, // NTLMSSP_NEGOTIATE_IDENTIFY
|
||||
RequestNonNTSession = 0x400000, // NTLMSSP_REQUEST_NON_NT_SESSION_KEY
|
||||
NegotiateTargetInfo = 0x800000, // NTLMSSP_NEGOTIATE_TARGET_INFO
|
||||
NegotiateVersion = 0x2000000, // NTLMSSP_NEGOTIATE_VERSION
|
||||
Negotiate128 = 0x20000000, // NTLMSSP_NEGOTIATE_128
|
||||
NegotiateKeyExchange = 0x40000000, // NTLMSSP_NEGOTIATE_KEY_EXCH
|
||||
Negotiate56 = 0x80000000, // NTLMSSP_NEGOTIATE_56
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
/* Copyright (C) 2014 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 System.Text;
|
||||
using Utilities;
|
||||
|
||||
namespace SMBLibrary.Authentication
|
||||
{
|
||||
/// <summary>
|
||||
/// NTLMv2_CLIENT_CHALLENGE
|
||||
/// </summary>
|
||||
public class NTLMv2ClientChallengeStructure
|
||||
{
|
||||
public static readonly DateTime EpochTime = DateTime.FromFileTimeUtc(0);
|
||||
|
||||
public byte ResponseVersion;
|
||||
public byte ResponseVersionHigh;
|
||||
public DateTime Time;
|
||||
public byte[] ClientChallenge;
|
||||
public KeyValuePairList<AVPairKey, byte[]> AVPairs;
|
||||
|
||||
public NTLMv2ClientChallengeStructure()
|
||||
{
|
||||
}
|
||||
|
||||
public NTLMv2ClientChallengeStructure(DateTime time, byte[] clientChallenge, string domainName, string computerName)
|
||||
{
|
||||
ResponseVersion = 1;
|
||||
ResponseVersionHigh = 1;
|
||||
Time = time;
|
||||
ClientChallenge = clientChallenge;
|
||||
AVPairs = new KeyValuePairList<AVPairKey, byte[]>();
|
||||
AVPairs.Add(AVPairKey.NbDomainName, UnicodeEncoding.Unicode.GetBytes(domainName));
|
||||
AVPairs.Add(AVPairKey.NbComputerName, UnicodeEncoding.Unicode.GetBytes(computerName));
|
||||
}
|
||||
|
||||
public NTLMv2ClientChallengeStructure(byte[] buffer) : this(buffer, 0)
|
||||
{
|
||||
}
|
||||
|
||||
public NTLMv2ClientChallengeStructure(byte[] buffer, int offset)
|
||||
{
|
||||
ResponseVersion = ByteReader.ReadByte(buffer, offset + 0);
|
||||
ResponseVersionHigh = ByteReader.ReadByte(buffer, offset + 1);
|
||||
long temp = LittleEndianConverter.ToInt64(buffer, offset + 8);
|
||||
Time = DateTime.FromFileTimeUtc(temp);
|
||||
ClientChallenge = ByteReader.ReadBytes(buffer, offset + 16, 8);
|
||||
AVPairs = AVPairUtils.ReadAVPairSequence(buffer, offset + 28);
|
||||
}
|
||||
|
||||
public byte[] GetBytes()
|
||||
{
|
||||
byte[] sequenceBytes = AVPairUtils.GetAVPairSequenceBytes(AVPairs);
|
||||
byte[] timeBytes = LittleEndianConverter.GetBytes((ulong)Time.ToFileTimeUtc());
|
||||
|
||||
byte[] buffer = new byte[28 + sequenceBytes.Length];
|
||||
ByteWriter.WriteByte(buffer, 0, ResponseVersion);
|
||||
ByteWriter.WriteByte(buffer, 1, ResponseVersionHigh);
|
||||
ByteWriter.WriteBytes(buffer, 8, timeBytes);
|
||||
ByteWriter.WriteBytes(buffer, 16, ClientChallenge, 8);
|
||||
ByteWriter.WriteBytes(buffer, 28, sequenceBytes);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// [MS-NLMP] Page 60, Response key calculation algorithm:
|
||||
/// To create 'temp', 4 zero bytes will be appended to NTLMv2_CLIENT_CHALLENGE
|
||||
/// </summary>
|
||||
public byte[] GetBytesPadded()
|
||||
{
|
||||
return ByteUtils.Concatenate(GetBytes(), new byte[4]);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
/* Copyright (C) 2014 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 System.Text;
|
||||
using Utilities;
|
||||
|
||||
namespace SMBLibrary.Authentication
|
||||
{
|
||||
/// <summary>
|
||||
/// [MS-NLMP] NEGOTIATE_MESSAGE (Type 1 Message)
|
||||
/// </summary>
|
||||
public class NegotiateMessage
|
||||
{
|
||||
public string Signature; // 8 bytes
|
||||
public MessageTypeName MessageType;
|
||||
public NegotiateFlags NegotiateFlags;
|
||||
public string DomainName;
|
||||
public string Workstation;
|
||||
public Version Version;
|
||||
|
||||
public NegotiateMessage()
|
||||
{
|
||||
Signature = AuthenticationMessageUtils.ValidSignature;
|
||||
MessageType = MessageTypeName.Negotiate;
|
||||
DomainName = String.Empty;
|
||||
Workstation = String.Empty;
|
||||
}
|
||||
|
||||
public NegotiateMessage(byte[] buffer)
|
||||
{
|
||||
Signature = ByteReader.ReadAnsiString(buffer, 0, 8);
|
||||
MessageType = (MessageTypeName)LittleEndianConverter.ToUInt32(buffer, 8);
|
||||
NegotiateFlags = (NegotiateFlags)LittleEndianConverter.ToUInt32(buffer, 12);
|
||||
DomainName = AuthenticationMessageUtils.ReadAnsiStringBufferPointer(buffer, 16);
|
||||
Workstation = AuthenticationMessageUtils.ReadAnsiStringBufferPointer(buffer, 24);
|
||||
if ((NegotiateFlags & NegotiateFlags.NegotiateVersion) > 0)
|
||||
{
|
||||
Version = new Version(buffer, 32);
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] GetBytes()
|
||||
{
|
||||
int fixedLength = 32;
|
||||
if ((NegotiateFlags & NegotiateFlags.NegotiateVersion) > 0)
|
||||
{
|
||||
fixedLength += 8;
|
||||
}
|
||||
int payloadLength = DomainName.Length * 2 + Workstation.Length * 2;
|
||||
byte[] buffer = new byte[fixedLength + payloadLength];
|
||||
ByteWriter.WriteAnsiString(buffer, 0, AuthenticationMessageUtils.ValidSignature, 8);
|
||||
LittleEndianWriter.WriteUInt32(buffer, 8, (uint)MessageType);
|
||||
LittleEndianWriter.WriteUInt32(buffer, 12, (uint)NegotiateFlags);
|
||||
|
||||
if ((NegotiateFlags & NegotiateFlags.NegotiateVersion) > 0)
|
||||
{
|
||||
Version.WriteBytes(buffer, 32);
|
||||
}
|
||||
|
||||
int offset = fixedLength;
|
||||
AuthenticationMessageUtils.WriteBufferPointer(buffer, 16, (ushort)(DomainName.Length * 2), (uint)offset);
|
||||
ByteWriter.WriteUTF16String(buffer, ref offset, DomainName);
|
||||
AuthenticationMessageUtils.WriteBufferPointer(buffer, 16, (ushort)(Workstation.Length * 2), (uint)offset);
|
||||
ByteWriter.WriteUTF16String(buffer, ref offset, Workstation);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
}
|
64
SMBLibrary/Authentication/AuthenticateMessage/Version.cs
Normal file
64
SMBLibrary/Authentication/AuthenticateMessage/Version.cs
Normal file
|
@ -0,0 +1,64 @@
|
|||
/* Copyright (C) 2014 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 System.Text;
|
||||
using Utilities;
|
||||
|
||||
namespace SMBLibrary.Authentication
|
||||
{
|
||||
public class Version
|
||||
{
|
||||
public const byte NTLMSSP_REVISION_W2K3 = 0x0F;
|
||||
|
||||
public byte ProductMajorVersion;
|
||||
public byte ProductMinorVersion;
|
||||
public ushort ProductBuild;
|
||||
// Reserved - 3 bytes
|
||||
public byte NTLMRevisionCurrent;
|
||||
|
||||
public Version(byte majorVersion, byte minorVersion, ushort build, byte ntlmRevisionCurrent)
|
||||
{
|
||||
ProductMajorVersion = majorVersion;
|
||||
ProductMinorVersion = minorVersion;
|
||||
ProductBuild = build;
|
||||
NTLMRevisionCurrent = ntlmRevisionCurrent;
|
||||
}
|
||||
|
||||
public Version(byte[] buffer, int offset)
|
||||
{
|
||||
ProductMajorVersion = ByteReader.ReadByte(buffer, offset + 0);
|
||||
ProductMinorVersion = ByteReader.ReadByte(buffer, offset + 1);
|
||||
ProductBuild = LittleEndianConverter.ToUInt16(buffer, offset + 2);
|
||||
NTLMRevisionCurrent = ByteReader.ReadByte(buffer, offset + 7);
|
||||
}
|
||||
|
||||
public void WriteBytes(byte[] buffer, int offset)
|
||||
{
|
||||
ByteWriter.WriteByte(buffer, offset + 0, ProductMajorVersion);
|
||||
ByteWriter.WriteByte(buffer, offset + 1, ProductMinorVersion);
|
||||
LittleEndianWriter.WriteUInt16(buffer, offset + 2, ProductBuild);
|
||||
ByteWriter.WriteByte(buffer, offset + 7, NTLMRevisionCurrent);
|
||||
}
|
||||
|
||||
public static Version WindowsXP
|
||||
{
|
||||
get
|
||||
{
|
||||
return new Version(5, 1, 2600, NTLMSSP_REVISION_W2K3);
|
||||
}
|
||||
}
|
||||
|
||||
public static Version Server2003
|
||||
{
|
||||
get
|
||||
{
|
||||
return new Version(5, 2, 3790, NTLMSSP_REVISION_W2K3);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
418
SMBLibrary/Authentication/MD4.cs
Normal file
418
SMBLibrary/Authentication/MD4.cs
Normal file
|
@ -0,0 +1,418 @@
|
|||
/* Copyright (C) 1990-2, RSA Data Security, Inc. All rights reserved.
|
||||
|
||||
License to copy and use this software is granted provided that it
|
||||
is identified as the "RSA Data Security, Inc. MD4 Message-Digest
|
||||
Algorithm" in all material mentioning or referencing this software
|
||||
or this function.
|
||||
|
||||
License is also granted to make and use derivative works provided
|
||||
that such works are identified as "derived from the RSA Data
|
||||
Security, Inc. MD4 Message-Digest Algorithm" in all material
|
||||
mentioning or referencing the derived work.
|
||||
|
||||
RSA Data Security, Inc. makes no representations concerning either
|
||||
the merchantability of this software or the suitability of this
|
||||
software for any particular purpose. It is provided "as is"
|
||||
without express or implied warranty of any kind.
|
||||
|
||||
|
||||
--------------------------------------------------------------
|
||||
|
||||
Ported from Norbert Hranitzky's (norbert.hranitzky@mchp.siemens.de)
|
||||
Java version by Oren Novotny (osn@po.cwru.edu)
|
||||
|
||||
--------------------------------------------------------------
|
||||
Adapted to C# 2.0 By Tal Aloni
|
||||
--------------------------------------------------------------
|
||||
|
||||
|
||||
*/
|
||||
|
||||
using System.Text;
|
||||
|
||||
namespace System.Security.Cryptography
|
||||
{
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Implements the MD4 message digest algorithm in C#
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// <b>References:</b>
|
||||
/// <ol>
|
||||
/// <li> Ronald L. Rivest,
|
||||
/// "<a href = "http://www.roxen.com/rfc/rfc1320.html">
|
||||
/// The MD4 Message-Digest Algorithm</a>",
|
||||
/// IETF RFC-1320 (informational).
|
||||
/// </li>
|
||||
/// </ol>
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
internal class MD4
|
||||
{
|
||||
// MD4 specific object variables
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// The size in bytes of the input block to the transformation algorithm
|
||||
/// </summary>
|
||||
private const int BLOCK_LENGTH = 64; // = 512 / 8
|
||||
|
||||
/// <summary>
|
||||
/// 512-bit work buffer = 16 x 32-bit words
|
||||
/// </summary>
|
||||
private readonly uint[] X = new uint[16];
|
||||
|
||||
/// <summary>
|
||||
/// 4 32-bit words (interim result)
|
||||
/// </summary>
|
||||
private readonly uint[] context = new uint[4];
|
||||
|
||||
/// <summary>
|
||||
/// 512-bit input buffer = 16 x 32-bit words holds until it reaches 512 bits
|
||||
/// </summary>
|
||||
private byte[] buffer = new byte[BLOCK_LENGTH];
|
||||
|
||||
/// <summary>
|
||||
/// Number of bytes procesed so far mod. 2 power of 64.
|
||||
/// </summary>
|
||||
private long count;
|
||||
|
||||
|
||||
// Constructors
|
||||
//------------------------------------------------------------------------
|
||||
public MD4()
|
||||
{
|
||||
EngineReset();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This constructor is here to implement the clonability of this class
|
||||
/// </summary>
|
||||
/// <param name = "md"> </param>
|
||||
private MD4(MD4 md)
|
||||
: this()
|
||||
{
|
||||
//this();
|
||||
context = (uint[])md.context.Clone();
|
||||
buffer = (byte[])md.buffer.Clone();
|
||||
count = md.count;
|
||||
}
|
||||
|
||||
// Clonable method implementation
|
||||
//-------------------------------------------------------------------------
|
||||
public object Clone()
|
||||
{
|
||||
return new MD4(this);
|
||||
}
|
||||
|
||||
// JCE methods
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Resets this object disregarding any temporary data present at the
|
||||
/// time of the invocation of this call.
|
||||
/// </summary>
|
||||
private void EngineReset()
|
||||
{
|
||||
// initial values of MD4 i.e. A, B, C, D
|
||||
// as per rfc-1320; they are low-order byte first
|
||||
context[0] = 0x67452301;
|
||||
context[1] = 0xEFCDAB89;
|
||||
context[2] = 0x98BADCFE;
|
||||
context[3] = 0x10325476;
|
||||
count = 0L;
|
||||
for (int i = 0; i < BLOCK_LENGTH; i++)
|
||||
buffer[i] = 0;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Continues an MD4 message digest using the input byte
|
||||
/// </summary>
|
||||
/// <param name = "b">byte to input</param>
|
||||
private void EngineUpdate(byte b)
|
||||
{
|
||||
// compute number of bytes still unhashed; ie. present in buffer
|
||||
int i = (int)(count % BLOCK_LENGTH);
|
||||
count++; // update number of bytes
|
||||
buffer[i] = b;
|
||||
if (i == BLOCK_LENGTH - 1)
|
||||
Transform(ref buffer, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// MD4 block update operation
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Continues an MD4 message digest operation by filling the buffer,
|
||||
/// transform(ing) data in 512-bit message block(s), updating the variables
|
||||
/// context and count, and leaving (buffering) the remaining bytes in buffer
|
||||
/// for the next update or finish.
|
||||
/// </remarks>
|
||||
/// <param name = "input">input block</param>
|
||||
/// <param name = "offset">start of meaningful bytes in input</param>
|
||||
/// <param name = "len">count of bytes in input blcok to consider</param>
|
||||
private void EngineUpdate(byte[] input, int offset, int len)
|
||||
{
|
||||
// make sure we don't exceed input's allocated size/length
|
||||
if (offset < 0 || len < 0 || (long)offset + len > input.Length)
|
||||
throw new ArgumentOutOfRangeException();
|
||||
|
||||
// compute number of bytes still unhashed; ie. present in buffer
|
||||
int bufferNdx = (int)(count % BLOCK_LENGTH);
|
||||
count += len; // update number of bytes
|
||||
int partLen = BLOCK_LENGTH - bufferNdx;
|
||||
int i = 0;
|
||||
if (len >= partLen)
|
||||
{
|
||||
Array.Copy(input, offset + i, buffer, bufferNdx, partLen);
|
||||
|
||||
Transform(ref buffer, 0);
|
||||
|
||||
for (i = partLen; i + BLOCK_LENGTH - 1 < len; i += BLOCK_LENGTH)
|
||||
Transform(ref input, offset + i);
|
||||
bufferNdx = 0;
|
||||
}
|
||||
// buffer remaining input
|
||||
if (i < len)
|
||||
Array.Copy(input, offset + i, buffer, bufferNdx, len - i);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Completes the hash computation by performing final operations such
|
||||
/// as padding. At the return of this engineDigest, the MD engine is
|
||||
/// reset.
|
||||
/// </summary>
|
||||
/// <returns>the array of bytes for the resulting hash value.</returns>
|
||||
private byte[] EngineDigest()
|
||||
{
|
||||
// pad output to 56 mod 64; as RFC1320 puts it: congruent to 448 mod 512
|
||||
int bufferNdx = (int)(count % BLOCK_LENGTH);
|
||||
int padLen = (bufferNdx < 56) ? (56 - bufferNdx) : (120 - bufferNdx);
|
||||
|
||||
// padding is always binary 1 followed by binary 0's
|
||||
byte[] tail = new byte[padLen + 8];
|
||||
tail[0] = 0x80;
|
||||
|
||||
// append length before final transform
|
||||
// save number of bits, casting the long to an array of 8 bytes
|
||||
// save low-order byte first.
|
||||
for (int i = 0; i < 8; i++)
|
||||
tail[padLen + i] = (byte)((count * 8) >> (8 * i));
|
||||
|
||||
EngineUpdate(tail, 0, tail.Length);
|
||||
|
||||
byte[] result = new byte[16];
|
||||
// cast this MD4's context (array of 4 uints) into an array of 16 bytes.
|
||||
for (int i = 0; i < 4; i++)
|
||||
for (int j = 0; j < 4; j++)
|
||||
result[i * 4 + j] = (byte)(context[i] >> (8 * j));
|
||||
|
||||
// reset the engine
|
||||
EngineReset();
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a byte hash from a string
|
||||
/// </summary>
|
||||
/// <param name = "s">string to hash</param>
|
||||
/// <returns>byte-array that contains the hash</returns>
|
||||
public byte[] GetByteHashFromString(string s)
|
||||
{
|
||||
byte[] b = Encoding.UTF8.GetBytes(s);
|
||||
MD4 md4 = new MD4();
|
||||
|
||||
md4.EngineUpdate(b, 0, b.Length);
|
||||
|
||||
return md4.EngineDigest();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a binary hash from an input byte array
|
||||
/// </summary>
|
||||
/// <param name = "b">byte-array to hash</param>
|
||||
/// <returns>binary hash of input</returns>
|
||||
public byte[] GetByteHashFromBytes(byte[] b)
|
||||
{
|
||||
MD4 md4 = new MD4();
|
||||
|
||||
md4.EngineUpdate(b, 0, b.Length);
|
||||
|
||||
return md4.EngineDigest();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a string that contains the hexadecimal hash
|
||||
/// </summary>
|
||||
/// <param name = "b">byte-array to input</param>
|
||||
/// <returns>String that contains the hex of the hash</returns>
|
||||
public string GetHexHashFromBytes(byte[] b)
|
||||
{
|
||||
byte[] e = GetByteHashFromBytes(b);
|
||||
return BytesToHex(e, e.Length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a byte hash from the input byte
|
||||
/// </summary>
|
||||
/// <param name = "b">byte to hash</param>
|
||||
/// <returns>binary hash of the input byte</returns>
|
||||
public byte[] GetByteHashFromByte(byte b)
|
||||
{
|
||||
MD4 md4 = new MD4();
|
||||
|
||||
md4.EngineUpdate(b);
|
||||
|
||||
return md4.EngineDigest();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a string that contains the hexadecimal hash
|
||||
/// </summary>
|
||||
/// <param name = "b">byte to hash</param>
|
||||
/// <returns>String that contains the hex of the hash</returns>
|
||||
public string GetHexHashFromByte(byte b)
|
||||
{
|
||||
byte[] e = GetByteHashFromByte(b);
|
||||
return BytesToHex(e, e.Length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a string that contains the hexadecimal hash
|
||||
/// </summary>
|
||||
/// <param name = "s">string to hash</param>
|
||||
/// <returns>String that contains the hex of the hash</returns>
|
||||
public string GetHexHashFromString(string s)
|
||||
{
|
||||
byte[] b = GetByteHashFromString(s);
|
||||
return BytesToHex(b, b.Length);
|
||||
}
|
||||
|
||||
private static string BytesToHex(byte[] a, int len)
|
||||
{
|
||||
string temp = BitConverter.ToString(a);
|
||||
|
||||
// We need to remove the dashes that come from the BitConverter
|
||||
StringBuilder sb = new StringBuilder((len - 2) / 2); // This should be the final size
|
||||
|
||||
for (int i = 0; i < temp.Length; i++)
|
||||
if (temp[i] != '-')
|
||||
sb.Append(temp[i]);
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
// own methods
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// MD4 basic transformation
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Transforms context based on 512 bits from input block starting
|
||||
/// from the offset'th byte.
|
||||
/// </remarks>
|
||||
/// <param name = "block">input sub-array</param>
|
||||
/// <param name = "offset">starting position of sub-array</param>
|
||||
private void Transform(ref byte[] block, int offset)
|
||||
{
|
||||
// decodes 64 bytes from input block into an array of 16 32-bit
|
||||
// entities. Use A as a temp var.
|
||||
for (int i = 0; i < 16; i++)
|
||||
X[i] = ((uint)block[offset++] & 0xFF) |
|
||||
(((uint)block[offset++] & 0xFF) << 8) |
|
||||
(((uint)block[offset++] & 0xFF) << 16) |
|
||||
(((uint)block[offset++] & 0xFF) << 24);
|
||||
|
||||
|
||||
uint A = context[0];
|
||||
uint B = context[1];
|
||||
uint C = context[2];
|
||||
uint D = context[3];
|
||||
|
||||
A = FF(A, B, C, D, X[0], 3);
|
||||
D = FF(D, A, B, C, X[1], 7);
|
||||
C = FF(C, D, A, B, X[2], 11);
|
||||
B = FF(B, C, D, A, X[3], 19);
|
||||
A = FF(A, B, C, D, X[4], 3);
|
||||
D = FF(D, A, B, C, X[5], 7);
|
||||
C = FF(C, D, A, B, X[6], 11);
|
||||
B = FF(B, C, D, A, X[7], 19);
|
||||
A = FF(A, B, C, D, X[8], 3);
|
||||
D = FF(D, A, B, C, X[9], 7);
|
||||
C = FF(C, D, A, B, X[10], 11);
|
||||
B = FF(B, C, D, A, X[11], 19);
|
||||
A = FF(A, B, C, D, X[12], 3);
|
||||
D = FF(D, A, B, C, X[13], 7);
|
||||
C = FF(C, D, A, B, X[14], 11);
|
||||
B = FF(B, C, D, A, X[15], 19);
|
||||
|
||||
A = GG(A, B, C, D, X[0], 3);
|
||||
D = GG(D, A, B, C, X[4], 5);
|
||||
C = GG(C, D, A, B, X[8], 9);
|
||||
B = GG(B, C, D, A, X[12], 13);
|
||||
A = GG(A, B, C, D, X[1], 3);
|
||||
D = GG(D, A, B, C, X[5], 5);
|
||||
C = GG(C, D, A, B, X[9], 9);
|
||||
B = GG(B, C, D, A, X[13], 13);
|
||||
A = GG(A, B, C, D, X[2], 3);
|
||||
D = GG(D, A, B, C, X[6], 5);
|
||||
C = GG(C, D, A, B, X[10], 9);
|
||||
B = GG(B, C, D, A, X[14], 13);
|
||||
A = GG(A, B, C, D, X[3], 3);
|
||||
D = GG(D, A, B, C, X[7], 5);
|
||||
C = GG(C, D, A, B, X[11], 9);
|
||||
B = GG(B, C, D, A, X[15], 13);
|
||||
|
||||
A = HH(A, B, C, D, X[0], 3);
|
||||
D = HH(D, A, B, C, X[8], 9);
|
||||
C = HH(C, D, A, B, X[4], 11);
|
||||
B = HH(B, C, D, A, X[12], 15);
|
||||
A = HH(A, B, C, D, X[2], 3);
|
||||
D = HH(D, A, B, C, X[10], 9);
|
||||
C = HH(C, D, A, B, X[6], 11);
|
||||
B = HH(B, C, D, A, X[14], 15);
|
||||
A = HH(A, B, C, D, X[1], 3);
|
||||
D = HH(D, A, B, C, X[9], 9);
|
||||
C = HH(C, D, A, B, X[5], 11);
|
||||
B = HH(B, C, D, A, X[13], 15);
|
||||
A = HH(A, B, C, D, X[3], 3);
|
||||
D = HH(D, A, B, C, X[11], 9);
|
||||
C = HH(C, D, A, B, X[7], 11);
|
||||
B = HH(B, C, D, A, X[15], 15);
|
||||
|
||||
context[0] += A;
|
||||
context[1] += B;
|
||||
context[2] += C;
|
||||
context[3] += D;
|
||||
}
|
||||
|
||||
// The basic MD4 atomic functions.
|
||||
|
||||
private uint FF(uint a, uint b, uint c, uint d, uint x, int s)
|
||||
{
|
||||
uint t = a + ((b & c) | (~b & d)) + x;
|
||||
return t << s | t >> (32 - s);
|
||||
}
|
||||
|
||||
private uint GG(uint a, uint b, uint c, uint d, uint x, int s)
|
||||
{
|
||||
uint t = a + ((b & (c | d)) | (c & d)) + x + 0x5A827999;
|
||||
return t << s | t >> (32 - s);
|
||||
}
|
||||
|
||||
private uint HH(uint a, uint b, uint c, uint d, uint x, int s)
|
||||
{
|
||||
uint t = a + (b ^ c ^ d) + x + 0x6ED9EBA1;
|
||||
return t << s | t >> (32 - s);
|
||||
}
|
||||
}
|
||||
|
||||
// class MD4
|
||||
}
|
||||
|
||||
// namespace MD4Hash
|
220
SMBLibrary/Authentication/NTAuthentication.cs
Normal file
220
SMBLibrary/Authentication/NTAuthentication.cs
Normal file
|
@ -0,0 +1,220 @@
|
|||
/* Copyright (C) 2014 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 System.Globalization;
|
||||
using System.Reflection;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using Utilities;
|
||||
|
||||
namespace SMBLibrary.Authentication
|
||||
{
|
||||
public class NTAuthentication
|
||||
{
|
||||
public static byte[] ComputeLMv1Response(byte[] challenge, string password)
|
||||
{
|
||||
byte[] hash = LMOWFv1(password);
|
||||
return DesLongEncrypt(hash, challenge);
|
||||
}
|
||||
|
||||
public static byte[] ComputeNTLMv1Response(byte[] challenge, string password)
|
||||
{
|
||||
byte[] hash = NTOWFv1(password);
|
||||
return DesLongEncrypt(hash, challenge);
|
||||
}
|
||||
|
||||
public static byte[] ComputeNTLMv1ExtendedSecurityResponse(byte[] serverChallenge, byte[] clientChallenge, string password)
|
||||
{
|
||||
byte[] passwordHash = NTOWFv1(password);
|
||||
byte[] challengeHash = MD5.Create().ComputeHash(ByteUtils.Concatenate(serverChallenge, clientChallenge));
|
||||
byte[] challengeHashShort = new byte[8];
|
||||
Array.Copy(challengeHash, 0, challengeHashShort, 0, 8);
|
||||
return DesLongEncrypt(passwordHash, challengeHashShort);
|
||||
}
|
||||
|
||||
public static byte[] ComputeLMv2Response(byte[] serverChallenge, byte[] clientChallenge, string password, string user, string domain)
|
||||
{
|
||||
byte[] key = LMOWFv2(password, user, domain);
|
||||
byte[] bytes = ByteUtils.Concatenate(serverChallenge, clientChallenge);
|
||||
HMACMD5 hmac = new HMACMD5(key);
|
||||
byte[] hash = hmac.ComputeHash(bytes, 0, bytes.Length);
|
||||
|
||||
return ByteUtils.Concatenate(hash, clientChallenge);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// [MS-NLMP] page 60
|
||||
/// 'temp' is the same as ClientChallengeStructure with 4 zero bytes padding
|
||||
/// </summary>
|
||||
public static byte[] ComputeNTLMv2Response(byte[] serverChallenge, byte[] clientChallengeStructurePadded, string password, string user, string domain)
|
||||
{
|
||||
byte[] key = NTOWFv2(password, user, domain);
|
||||
byte[] temp = clientChallengeStructurePadded;
|
||||
|
||||
HMACMD5 hmac = new HMACMD5(key);
|
||||
byte[] _NTProof = hmac.ComputeHash(ByteUtils.Concatenate(serverChallenge, temp), 0, serverChallenge.Length + temp.Length);
|
||||
|
||||
return ByteUtils.Concatenate(_NTProof, temp);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// NTLMv2_CLIENT_CHALLENGE
|
||||
/// </summary>
|
||||
[Obsolete]
|
||||
public static byte[] GetNTLMv2ClientChallengeStructure(byte[] clientChallenge, byte responseVersion, byte responseVersionHigh, byte[] time, byte[] serverAVPair)
|
||||
{
|
||||
byte[] temp = new byte[28 + serverAVPair.Length];
|
||||
temp[0] = responseVersion;
|
||||
temp[1] = responseVersionHigh;
|
||||
Array.Copy(time, 0, temp, 8, 8);
|
||||
Array.Copy(clientChallenge, 0, temp, 16, 8);
|
||||
Array.Copy(serverAVPair, 0, temp, 28, serverAVPair.Length);
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
public static byte[] DesEncrypt(byte[] key, byte[] plainText)
|
||||
{
|
||||
return DesEncrypt(key, plainText, 0, plainText.Length);
|
||||
}
|
||||
|
||||
public static byte[] DesEncrypt(byte[] key, byte[] plainText, int inputOffset, int inputCount)
|
||||
{
|
||||
ICryptoTransform encryptor = CreateWeakDesEncryptor(CipherMode.ECB, key, new byte[key.Length]);
|
||||
byte[] result = new byte[inputCount];
|
||||
encryptor.TransformBlock(plainText, inputOffset, inputCount, result, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static ICryptoTransform CreateWeakDesEncryptor(CipherMode mode, byte[] rgbKey, byte[] rgbIV)
|
||||
{
|
||||
DES des = DES.Create();
|
||||
des.Mode = mode;
|
||||
DESCryptoServiceProvider sm = des as DESCryptoServiceProvider;
|
||||
MethodInfo mi = sm.GetType().GetMethod("_NewEncryptor", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
object[] Par = { rgbKey, mode, rgbIV, sm.FeedbackSize, 0 };
|
||||
ICryptoTransform trans = mi.Invoke(sm, Par) as ICryptoTransform;
|
||||
return trans;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// DESL()
|
||||
/// </summary>
|
||||
public static byte[] DesLongEncrypt(byte[] key, byte[] plainText)
|
||||
{
|
||||
if (key.Length != 16)
|
||||
{
|
||||
throw new ArgumentException("Invalid key length");
|
||||
}
|
||||
|
||||
if (plainText.Length != 8)
|
||||
{
|
||||
throw new ArgumentException("Invalid plain-text length");
|
||||
}
|
||||
byte[] padded = new byte[21];
|
||||
Array.Copy(key, padded, key.Length);
|
||||
|
||||
byte[] k1 = new byte[7];
|
||||
byte[] k2 = new byte[7];
|
||||
byte[] k3 = new byte[7];
|
||||
Array.Copy(padded, 0, k1, 0, 7);
|
||||
Array.Copy(padded, 7, k2, 0, 7);
|
||||
Array.Copy(padded, 14, k3, 0, 7);
|
||||
|
||||
byte[] r1 = DesEncrypt(ExtendDESKey(k1), plainText);
|
||||
byte[] r2 = DesEncrypt(ExtendDESKey(k2), plainText);
|
||||
byte[] r3 = DesEncrypt(ExtendDESKey(k3), plainText);
|
||||
|
||||
byte[] result = new byte[24];
|
||||
Array.Copy(r1, 0, result, 0, 8);
|
||||
Array.Copy(r2, 0, result, 8, 8);
|
||||
Array.Copy(r3, 0, result, 16, 8);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Encoding GetOEMEncoding()
|
||||
{
|
||||
return Encoding.GetEncoding(CultureInfo.CurrentCulture.TextInfo.OEMCodePage);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// LM Hash
|
||||
/// </summary>
|
||||
public static byte[] LMOWFv1(string password)
|
||||
{
|
||||
byte[] plainText = ASCIIEncoding.ASCII.GetBytes("KGS!@#$%");
|
||||
byte[] passwordBytes = GetOEMEncoding().GetBytes(password.ToUpper());
|
||||
byte[] key = new byte[14];
|
||||
Array.Copy(passwordBytes, key, Math.Min(passwordBytes.Length, 14));
|
||||
|
||||
byte[] k1 = new byte[7];
|
||||
byte[] k2 = new byte[7];
|
||||
Array.Copy(key, 0, k1, 0, 7);
|
||||
Array.Copy(key, 7, k2, 0, 7);
|
||||
|
||||
byte[] part1 = DesEncrypt(ExtendDESKey(k1), plainText);
|
||||
byte[] part2 = DesEncrypt(ExtendDESKey(k2), plainText);
|
||||
|
||||
return ByteUtils.Concatenate(part1, part2);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// NTLM hash (NT hash)
|
||||
/// </summary>
|
||||
public static byte[] NTOWFv1(string password)
|
||||
{
|
||||
byte[] passwordBytes = UnicodeEncoding.Unicode.GetBytes(password);
|
||||
return new MD4().GetByteHashFromBytes(passwordBytes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// LMOWFv2 is identical to NTOWFv2
|
||||
/// </summary>
|
||||
public static byte[] LMOWFv2(string password, string user, string domain)
|
||||
{
|
||||
return NTOWFv2(password, user, domain);
|
||||
}
|
||||
|
||||
public static byte[] NTOWFv2(string password, string user, string domain)
|
||||
{
|
||||
byte[] passwordBytes = UnicodeEncoding.Unicode.GetBytes(password);
|
||||
byte[] key = new MD4().GetByteHashFromBytes(passwordBytes);
|
||||
string text = user.ToUpper() + domain;
|
||||
byte[] bytes = UnicodeEncoding.Unicode.GetBytes(text);
|
||||
HMACMD5 hmac = new HMACMD5(key);
|
||||
return hmac.ComputeHash(bytes, 0, bytes.Length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extends a 7-byte key into an 8-byte key.
|
||||
/// Note: The DES key ostensibly consists of 64 bits, however, only 56 of these are actually used by the algorithm.
|
||||
/// Eight bits are used solely for checking parity, and are thereafter discarded
|
||||
/// </summary>
|
||||
private static byte[] ExtendDESKey(byte[] key)
|
||||
{
|
||||
byte[] result = new byte[8];
|
||||
int i;
|
||||
|
||||
result[0] = (byte)((key[0] >> 1) & 0xff);
|
||||
result[1] = (byte)((((key[0] & 0x01) << 6) | (((key[1] & 0xff) >> 2) & 0xff)) & 0xff);
|
||||
result[2] = (byte)((((key[1] & 0x03) << 5) | (((key[2] & 0xff) >> 3) & 0xff)) & 0xff);
|
||||
result[3] = (byte)((((key[2] & 0x07) << 4) | (((key[3] & 0xff) >> 4) & 0xff)) & 0xff);
|
||||
result[4] = (byte)((((key[3] & 0x0F) << 3) | (((key[4] & 0xff) >> 5) & 0xff)) & 0xff);
|
||||
result[5] = (byte)((((key[4] & 0x1F) << 2) | (((key[5] & 0xff) >> 6) & 0xff)) & 0xff);
|
||||
result[6] = (byte)((((key[5] & 0x3F) << 1) | (((key[6] & 0xff) >> 7) & 0xff)) & 0xff);
|
||||
result[7] = (byte)(key[6] & 0x7F);
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
result[i] = (byte)(result[i] << 1);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
69
SMBLibrary/Client/SMBClient.cs
Normal file
69
SMBLibrary/Client/SMBClient.cs
Normal file
|
@ -0,0 +1,69 @@
|
|||
/* Copyright (C) 2014 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 System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using SMBLibrary.NetBios;
|
||||
using SMBLibrary.SMB1;
|
||||
using Utilities;
|
||||
|
||||
namespace SMBLibrary.Client
|
||||
{
|
||||
public class SMBClient
|
||||
{
|
||||
public const int NetBiosOverTCPPort = 139;
|
||||
public const int DirectTCPPort = 445;
|
||||
public const string NTLanManagerDialect = "NT LM 0.12";
|
||||
|
||||
public SMBClient(IPAddress serverAddress, SMBTransportType transport)
|
||||
{
|
||||
NegotiateRequest request = new NegotiateRequest();
|
||||
request.Dialects.Add(NTLanManagerDialect);
|
||||
|
||||
Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
if (transport == SMBTransportType.DirectTCPTransport)
|
||||
{
|
||||
serverSocket.Connect(serverAddress, DirectTCPPort);
|
||||
}
|
||||
else
|
||||
{
|
||||
serverSocket.Connect(serverAddress, NetBiosOverTCPPort);
|
||||
}
|
||||
TrySendMessage(serverSocket, request);
|
||||
}
|
||||
|
||||
public static void TrySendMessage(Socket serverSocket, SMBCommand request)
|
||||
{
|
||||
SMBMessage message = new SMBMessage();
|
||||
message.Commands.Add(request);
|
||||
TrySendMessage(serverSocket, message);
|
||||
}
|
||||
|
||||
public static void TrySendMessage(Socket serverSocket, SMBMessage message)
|
||||
{
|
||||
SessionMessagePacket packet = new SessionMessagePacket();
|
||||
packet.Trailer = message.GetBytes();
|
||||
TrySendPacket(serverSocket, packet);
|
||||
}
|
||||
|
||||
public static void TrySendPacket(Socket serverSocket, SessionPacket response)
|
||||
{
|
||||
try
|
||||
{
|
||||
serverSocket.Send(response.GetBytes());
|
||||
}
|
||||
catch (SocketException)
|
||||
{
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
101
SMBLibrary/EnumStructures/AccessMask.cs
Normal file
101
SMBLibrary/EnumStructures/AccessMask.cs
Normal file
|
@ -0,0 +1,101 @@
|
|||
/* Copyright (C) 2014 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 System.Text;
|
||||
using Utilities;
|
||||
|
||||
namespace SMBLibrary
|
||||
{
|
||||
/// <summary>
|
||||
/// [MS-SMB] 2.2.1.4.1 - File_Pipe_Printer_Access_Mask
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum FileAccessMask : uint
|
||||
{
|
||||
FILE_READ_DATA = 0x00000001,
|
||||
FILE_WRITE_DATA = 0x00000002,
|
||||
FILE_APPEND_DATA = 0x00000004,
|
||||
FILE_READ_EA = 0x00000008,
|
||||
FILE_WRITE_EA = 0x00000010,
|
||||
FILE_EXECUTE = 0x00000020,
|
||||
FILE_READ_ATTRIBUTES = 0x00000080,
|
||||
FILE_WRITE_ATTRIBUTES = 0x00000100,
|
||||
DELETE = 0x00010000,
|
||||
READ_CONTROL = 0x00020000,
|
||||
WRITE_DAC = 0x00040000,
|
||||
WRITE_OWNER = 0x00080000,
|
||||
SYNCHRONIZE = 0x00100000,
|
||||
ACCESS_SYSTEM_SECURITY = 0x01000000,
|
||||
MAXIMUM_ALLOWED = 0x02000000,
|
||||
GENERIC_ALL = 0x20000000,
|
||||
GENERIC_EXECUTE = 0x20000000,
|
||||
GENERIC_WRITE = 0x40000000,
|
||||
GENERIC_READ = 0x80000000,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// [MS-SMB] 2.2.1.4.2 - Directory_Access_Mask
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum DirectoryAccessMask : uint
|
||||
{
|
||||
FILE_LIST_DIRECTORY = 0x00000001,
|
||||
FILE_ADD_FILE = 0x00000002,
|
||||
FILE_ADD_SUBDIRECTORY = 0x00000004,
|
||||
FILE_READ_EA = 0x00000008,
|
||||
FILE_WRITE_EA = 0x00000010,
|
||||
FILE_TRAVERSE = 0x00000020,
|
||||
FILE_DELETE_CHILD = 0x00000040,
|
||||
FILE_READ_ATTRIBUTES = 0x00000080,
|
||||
FILE_WRITE_ATTRIBUTES = 0x00000100,
|
||||
DELETE = 0x00010000,
|
||||
READ_CONTROL = 0x00020000,
|
||||
WRITE_DAC = 0x00040000,
|
||||
WRITE_OWNER = 0x00080000,
|
||||
SYNCHRONIZE = 0x00100000,
|
||||
ACCESS_SYSTEM_SECURITY = 0x01000000,
|
||||
MAXIMUM_ALLOWED = 0x02000000,
|
||||
GENERIC_ALL = 0x20000000,
|
||||
GENERIC_EXECUTE = 0x20000000,
|
||||
GENERIC_WRITE = 0x40000000,
|
||||
GENERIC_READ = 0x80000000,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// [MS-DTYP] 2.4.3 - ACCESS_MASK
|
||||
/// </summary>
|
||||
public struct AccessMask // uint
|
||||
{
|
||||
public FileAccessMask File;
|
||||
public FileAccessMask Directory;
|
||||
|
||||
public AccessMask(byte[] buffer, ref int offset) : this(buffer, offset)
|
||||
{
|
||||
offset += 4;
|
||||
}
|
||||
|
||||
public AccessMask(byte[] buffer, int offset)
|
||||
{
|
||||
uint value = LittleEndianConverter.ToUInt32(buffer, offset);
|
||||
File = (FileAccessMask)value;
|
||||
Directory = (FileAccessMask)value;
|
||||
}
|
||||
|
||||
public void WriteBytes(byte[] buffer, int offset)
|
||||
{
|
||||
uint value = (uint)(this.File | this.Directory);
|
||||
LittleEndianWriter.WriteUInt32(buffer, offset, value);
|
||||
}
|
||||
|
||||
public void WriteBytes(byte[] buffer, ref int offset)
|
||||
{
|
||||
WriteBytes(buffer, offset);
|
||||
offset += 4;
|
||||
}
|
||||
}
|
||||
}
|
36
SMBLibrary/Enums/NTStatus.cs
Normal file
36
SMBLibrary/Enums/NTStatus.cs
Normal file
|
@ -0,0 +1,36 @@
|
|||
|
||||
namespace SMBLibrary
|
||||
{
|
||||
public enum NTStatus : uint
|
||||
{
|
||||
STATUS_SUCCESS = 0x00000000,
|
||||
STATUS_NOT_IMPLEMENTED = 0xC0000002,
|
||||
STATUS_INVALID_HANDLE = 0xC0000008,
|
||||
STATUS_INVALID_PARAMETER = 0xC000000D,
|
||||
STATUS_NO_SUCH_DEVICE = 0xC000000E,
|
||||
STATUS_NO_SUCH_FILE = 0xC000000F,
|
||||
STATUS_MORE_PROCESSING_REQUIRED = 0xC0000016,
|
||||
STATUS_ACCESS_DENIED = 0xC0000022, // The user is not authorized to access the resource.
|
||||
STATUS_OBJECT_NAME_INVALID = 0xC0000033,
|
||||
STATUS_OBJECT_NAME_NOT_FOUND = 0xC0000034,
|
||||
STATUS_OBJECT_NAME_COLLISION = 0xC0000035, // The file already exists
|
||||
STATUS_OBJECT_PATH_INVALID = 0xC0000039,
|
||||
STATUS_OBJECT_PATH_NOT_FOUND = 0xC000003A, // The share path does not reference a valid resource.
|
||||
STATUS_OBJECT_PATH_SYNTAX_BAD = 0xC000003B,
|
||||
STATUS_DATA_ERROR = 0xC000003E, // IO error
|
||||
STATUS_SHARING_VIOLATION = 0xC0000043,
|
||||
STATUS_FILE_LOCK_CONFLICT = 0xC0000054,
|
||||
STATUS_LOGON_FAILURE = 0xC000006D, // Authentication failure.
|
||||
STATUS_ACCOUNT_RESTRICTION = 0xC000006E, // The user has an empty password, which is not allowed
|
||||
STATUS_DISK_FULL = 0xC000007F,
|
||||
STATUS_MEDIA_WRITE_PROTECTED = 0xC00000A2,
|
||||
STATUS_FILE_IS_A_DIRECTORY = 0xC00000BA,
|
||||
STATUS_CANNOT_DELETE = 0xC0000121,
|
||||
|
||||
STATUS_INVALID_SMB = 0x00010002, // CIFS/SMB1: A corrupt or invalid SMB request was received
|
||||
STATUS_SMB_BAD_COMMAND = 0x00160002, // CIFS/SMB1: An unknown SMB command code was received by the server
|
||||
STATUS_SMB_BAD_FID = 0x00060001, // CIFS/SMB1
|
||||
STATUS_SMB_BAD_TID = 0x00050002, // CIFS/SMB1
|
||||
STATUS_OS2_NO_MORE_SIDS = 0x00710001, // CIFS/SMB1
|
||||
}
|
||||
}
|
9
SMBLibrary/Enums/SMBTransportType.cs
Normal file
9
SMBLibrary/Enums/SMBTransportType.cs
Normal file
|
@ -0,0 +1,9 @@
|
|||
|
||||
namespace SMBLibrary
|
||||
{
|
||||
public enum SMBTransportType
|
||||
{
|
||||
NetBiosOverTCP, // Port 139
|
||||
DirectTCPTransport, // Port 445
|
||||
}
|
||||
}
|
16
SMBLibrary/Enums/Win32Error.cs
Normal file
16
SMBLibrary/Enums/Win32Error.cs
Normal file
|
@ -0,0 +1,16 @@
|
|||
|
||||
namespace SMBLibrary
|
||||
{
|
||||
// All Win32 error codes MUST be in the range 0x0000 to 0xFFFF
|
||||
public enum Win32Error : ushort
|
||||
{
|
||||
ERROR_SUCCESS = 0x0000,
|
||||
ERROR_ACCESS_DENIED = 0x0005,
|
||||
ERROR_SHARING_VIOLATION = 0x0020,
|
||||
ERROR_DISK_FULL = 0x0070,
|
||||
ERROR_LOGON_FAILURE = 0x0000052E,
|
||||
ERROR_ACCOUNT_RESTRICTION = 0x0000052F,
|
||||
ERROR_LOGON_TYPE_NOT_GRANTED = 0x00000569,
|
||||
NERR_NetNameNotFound = 0x00000906
|
||||
}
|
||||
}
|
60
SMBLibrary/IOCTL/FileFullEAInformation.cs
Normal file
60
SMBLibrary/IOCTL/FileFullEAInformation.cs
Normal file
|
@ -0,0 +1,60 @@
|
|||
/* Copyright (C) 2014 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 System.Text;
|
||||
using Utilities;
|
||||
|
||||
namespace SMBLibrary
|
||||
{
|
||||
/// <summary>
|
||||
/// [MS-FSCC] FILE_FULL_EA_INFORMATION data element
|
||||
/// </summary>
|
||||
public class FileFullEAInformation
|
||||
{
|
||||
public uint NextEntryOffset;
|
||||
public byte Flags;
|
||||
//byte EaNameLength;
|
||||
//ushort EaValueLength;
|
||||
public string EaName; // ASCII
|
||||
public string EaValue; // ASCII
|
||||
|
||||
public FileFullEAInformation()
|
||||
{
|
||||
}
|
||||
|
||||
public FileFullEAInformation(byte[] buffer, int offset)
|
||||
{
|
||||
NextEntryOffset = LittleEndianReader.ReadUInt32(buffer, ref offset);
|
||||
Flags = ByteReader.ReadByte(buffer, ref offset);
|
||||
byte eaNameLength = ByteReader.ReadByte(buffer, ref offset);
|
||||
ushort eaValueLength = LittleEndianReader.ReadUInt16(buffer, ref offset);
|
||||
EaName = ByteReader.ReadAnsiString(buffer, ref offset, eaNameLength);
|
||||
EaValue = ByteReader.ReadAnsiString(buffer, ref offset, eaValueLength);
|
||||
}
|
||||
|
||||
public void WriteBytes(byte[] buffer, int offset)
|
||||
{
|
||||
byte eaNameLength = (byte)EaName.Length;
|
||||
ushort eaValueLength = (ushort)EaValue.Length;
|
||||
LittleEndianWriter.WriteUInt32(buffer, ref offset, NextEntryOffset);
|
||||
ByteWriter.WriteByte(buffer, ref offset, Flags);
|
||||
ByteWriter.WriteByte(buffer, ref offset, eaNameLength);
|
||||
LittleEndianWriter.WriteUInt16(buffer, ref offset, eaValueLength);
|
||||
ByteWriter.WriteAnsiString(buffer, ref offset, EaName);
|
||||
ByteWriter.WriteAnsiString(buffer, ref offset, EaValue);
|
||||
}
|
||||
|
||||
public int Length
|
||||
{
|
||||
get
|
||||
{
|
||||
return 8 + EaName.Length + EaValue.Length;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
67
SMBLibrary/IOCTL/FileFullEAInformationList.cs
Normal file
67
SMBLibrary/IOCTL/FileFullEAInformationList.cs
Normal file
|
@ -0,0 +1,67 @@
|
|||
/* Copyright (C) 2014 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 System.Text;
|
||||
|
||||
namespace SMBLibrary
|
||||
{
|
||||
/// <summary>
|
||||
/// [MS-FSCC] FILE_FULL_EA_INFORMATION buffer
|
||||
/// </summary>
|
||||
public class FileFullEAInformationList : List<FileFullEAInformation>
|
||||
{
|
||||
public FileFullEAInformationList()
|
||||
{
|
||||
}
|
||||
|
||||
public FileFullEAInformationList(byte[] buffer, int offset)
|
||||
{
|
||||
FileFullEAInformation entry = new FileFullEAInformation(buffer, offset);
|
||||
this.Add(entry);
|
||||
while (entry.NextEntryOffset != 0)
|
||||
{
|
||||
entry = new FileFullEAInformation(buffer, (int)entry.NextEntryOffset);
|
||||
this.Add(entry);
|
||||
}
|
||||
}
|
||||
|
||||
public void WriteBytes(byte[] buffer, int offset)
|
||||
{
|
||||
// When multiple FILE_FULL_EA_INFORMATION data elements are present in the buffer, each MUST be aligned on a 4-byte boundary
|
||||
for (int index = 0; index < this.Count; index++)
|
||||
{
|
||||
this[index].WriteBytes(buffer, offset);
|
||||
offset += this[index].Length;
|
||||
if (index < this.Count - 1)
|
||||
{
|
||||
int padding = (4 - (offset % 4)) % 4;
|
||||
offset += padding;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int Length
|
||||
{
|
||||
get
|
||||
{
|
||||
// When multiple FILE_FULL_EA_INFORMATION data elements are present in the buffer, each MUST be aligned on a 4-byte boundary
|
||||
int length = 0;
|
||||
for(int index = 0; index < this.Count; index++)
|
||||
{
|
||||
length += this[index].Length;
|
||||
if (index < this.Count - 1)
|
||||
{
|
||||
int padding = (4 - (length % 4)) % 4;
|
||||
length += padding;
|
||||
}
|
||||
}
|
||||
return length;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
48
SMBLibrary/IOCTL/ObjectIDBufferType1.cs
Normal file
48
SMBLibrary/IOCTL/ObjectIDBufferType1.cs
Normal file
|
@ -0,0 +1,48 @@
|
|||
/* Copyright (C) 2014 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 System.Text;
|
||||
using Utilities;
|
||||
|
||||
namespace SMBLibrary
|
||||
{
|
||||
/// <summary>
|
||||
/// [MS-FSCC] FILE_OBJECTID_BUFFER Type 1
|
||||
/// </summary>
|
||||
public class ObjectIDBufferType1
|
||||
{
|
||||
public const int Length = 64;
|
||||
|
||||
public Guid ObjectId;
|
||||
public Guid BirthVolumeId;
|
||||
public Guid BirthObjectId;
|
||||
public Guid DomainId;
|
||||
|
||||
public ObjectIDBufferType1()
|
||||
{
|
||||
}
|
||||
|
||||
public ObjectIDBufferType1(byte[] buffer)
|
||||
{
|
||||
ObjectId = LittleEndianConverter.ToGuid(buffer, 0);
|
||||
BirthVolumeId = LittleEndianConverter.ToGuid(buffer, 16);
|
||||
BirthObjectId = LittleEndianConverter.ToGuid(buffer, 32);
|
||||
DomainId = LittleEndianConverter.ToGuid(buffer, 48);
|
||||
}
|
||||
|
||||
public byte[] GetBytes()
|
||||
{
|
||||
byte[] buffer = new byte[Length];
|
||||
LittleEndianWriter.WriteGuidBytes(buffer, 0, ObjectId);
|
||||
LittleEndianWriter.WriteGuidBytes(buffer, 16, BirthVolumeId);
|
||||
LittleEndianWriter.WriteGuidBytes(buffer, 32, BirthObjectId);
|
||||
LittleEndianWriter.WriteGuidBytes(buffer, 48, DomainId);
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Utilities;
|
||||
|
||||
namespace SMBLibrary.NetBios
|
||||
{
|
||||
public enum OwnerNodeType : byte
|
||||
{
|
||||
BNode = 0x00,
|
||||
PNode = 0x01,
|
||||
MNode = 0x10,
|
||||
}
|
||||
|
||||
public struct NameFlags // ushort
|
||||
{
|
||||
public const int Length = 2;
|
||||
|
||||
public OwnerNodeType NodeType;
|
||||
public bool WorkGroup;
|
||||
|
||||
public ushort Value
|
||||
{
|
||||
get
|
||||
{
|
||||
ushort value = (ushort)(((byte)NodeType) << 13);
|
||||
if (WorkGroup)
|
||||
{
|
||||
value |= 0x8000;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
|
||||
namespace SMBLibrary.NetBios
|
||||
{
|
||||
public enum NameRecordType : ushort
|
||||
{
|
||||
NB = 0x0020,
|
||||
NBStat = 0x0021,
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
|
||||
namespace SMBLibrary.NetBios
|
||||
{
|
||||
public enum NameServiceOperation : byte
|
||||
{
|
||||
QueryRequest = 0x00,
|
||||
RegistrationRequest = 0x05,
|
||||
ReleaseRequest = 0x06,
|
||||
WackRequest = 0x07,
|
||||
RefreshRequest = 0x08,
|
||||
QueryResponse = 0x10,
|
||||
RegistrationResponse = 0x15,
|
||||
ReleaseResponse = 0x16,
|
||||
WackResponse = 0x17,
|
||||
RefreshResponse = 0x18,
|
||||
}
|
||||
}
|
20
SMBLibrary/NetBios/NameServicePackets/Enums/NetBiosSuffix.cs
Normal file
20
SMBLibrary/NetBios/NameServicePackets/Enums/NetBiosSuffix.cs
Normal file
|
@ -0,0 +1,20 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace SMBLibrary.NetBios
|
||||
{
|
||||
/// <summary>
|
||||
/// 16th character suffix for netbios name.
|
||||
/// see http://support.microsoft.com/kb/163409/en-us
|
||||
/// </summary>
|
||||
public enum NetBiosSuffix : byte
|
||||
{
|
||||
WorkstationService = 0x00,
|
||||
MessengerService = 0x03,
|
||||
DomainMasterBrowser = 0x1B,
|
||||
MasterBrowser = 0x1D,
|
||||
BrowserServiceElections = 0x1E,
|
||||
FileServiceService = 0x20,
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
using System;
|
||||
|
||||
namespace SMBLibrary.NetBios
|
||||
{
|
||||
/// <summary>
|
||||
/// [RFC 1002] 4.2.1.1. HEADER
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum OperationFlags : byte
|
||||
{
|
||||
Broadcast = 0x01,
|
||||
RecursionAvailable = 0x08,
|
||||
RecursionDesired = 0x10,
|
||||
Truncated = 0x20,
|
||||
AuthoritativeAnswer = 0x40,
|
||||
}
|
||||
}
|
45
SMBLibrary/NetBios/NameServicePackets/NameQueryRequest.cs
Normal file
45
SMBLibrary/NetBios/NameServicePackets/NameQueryRequest.cs
Normal file
|
@ -0,0 +1,45 @@
|
|||
/* Copyright (C) 2014 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 System.IO;
|
||||
using System.Text;
|
||||
using Utilities;
|
||||
|
||||
namespace SMBLibrary.NetBios
|
||||
{
|
||||
/// <summary>
|
||||
/// [RFC 1002] 4.2.12. NAME QUERY REQUEST
|
||||
/// </summary>
|
||||
public class NameQueryRequest
|
||||
{
|
||||
public NameServicePacketHeader Header;
|
||||
public QuestionSection Question;
|
||||
|
||||
public NameQueryRequest()
|
||||
{
|
||||
Header = new NameServicePacketHeader();
|
||||
Header.OpCode = NameServiceOperation.QueryRequest;
|
||||
Header.ARCount = 1;
|
||||
Question = new QuestionSection();
|
||||
}
|
||||
|
||||
public NameQueryRequest(byte[] buffer, int offset)
|
||||
{
|
||||
Header = new NameServicePacketHeader(buffer, ref offset);
|
||||
Question = new QuestionSection(buffer, ref offset);
|
||||
}
|
||||
|
||||
public byte[] GetBytes()
|
||||
{
|
||||
MemoryStream stream = new MemoryStream();
|
||||
Header.WriteBytes(stream);
|
||||
Question.WriteBytes(stream);
|
||||
return stream.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
/* Copyright (C) 2014 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 System.IO;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using Utilities;
|
||||
|
||||
namespace SMBLibrary.NetBios
|
||||
{
|
||||
/// <summary>
|
||||
/// [RFC 1002] 4.2.2. NAME REGISTRATION REQUEST
|
||||
/// </summary>
|
||||
public class NameRegistrationRequest
|
||||
{
|
||||
public const int DataLength = 6;
|
||||
|
||||
public NameServicePacketHeader Header;
|
||||
public QuestionSection Question;
|
||||
public ResourceRecord Resource;
|
||||
public NameFlags NameFlags;
|
||||
public byte[] Address; // IPv4 address
|
||||
|
||||
public NameRegistrationRequest()
|
||||
{
|
||||
Header = new NameServicePacketHeader();
|
||||
Header.OpCode = NameServiceOperation.RegistrationRequest;
|
||||
Header.QDCount = 1;
|
||||
Header.ARCount = 1;
|
||||
Header.Flags = OperationFlags.Broadcast | OperationFlags.RecursionDesired;
|
||||
Question = new QuestionSection();
|
||||
Resource = new ResourceRecord();
|
||||
Address = new byte[4];
|
||||
}
|
||||
|
||||
public NameRegistrationRequest(string machineName, NetBiosSuffix suffix, IPAddress address) : this()
|
||||
{
|
||||
Question.Name = NetBiosUtils.GetMSNetBiosName(machineName, suffix);
|
||||
Address = address.GetAddressBytes();
|
||||
}
|
||||
|
||||
public byte[] GetBytes()
|
||||
{
|
||||
Resource.Data = GetData();
|
||||
|
||||
MemoryStream stream = new MemoryStream();
|
||||
Header.WriteBytes(stream);
|
||||
Question.WriteBytes(stream);
|
||||
Resource.WriteBytes(stream, NameServicePacketHeader.Length);
|
||||
return stream.ToArray();
|
||||
}
|
||||
|
||||
public byte[] GetData()
|
||||
{
|
||||
byte[] data = new byte[DataLength];
|
||||
BigEndianWriter.WriteUInt16(data, 0, NameFlags.Value);
|
||||
ByteWriter.WriteBytes(data, 2, Address, 4);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Utilities;
|
||||
|
||||
namespace SMBLibrary.NetBios
|
||||
{
|
||||
/// <summary>
|
||||
/// [RFC 1002] 4.2.1.1. HEADER
|
||||
/// </summary>
|
||||
public class NameServicePacketHeader
|
||||
{
|
||||
public const int Length = 12;
|
||||
|
||||
public ushort TransactionID;
|
||||
public NameServiceOperation OpCode;
|
||||
public OperationFlags Flags;
|
||||
public byte ResultCode;
|
||||
public ushort QDCount;
|
||||
public ushort ANCount;
|
||||
public ushort NSCount;
|
||||
public ushort ARCount;
|
||||
|
||||
public NameServicePacketHeader()
|
||||
{
|
||||
}
|
||||
|
||||
public NameServicePacketHeader(byte[] buffer, ref int offset) : this(buffer, offset)
|
||||
{
|
||||
offset += Length;
|
||||
}
|
||||
|
||||
public NameServicePacketHeader(byte[] buffer, int offset)
|
||||
{
|
||||
TransactionID = BigEndianConverter.ToUInt16(buffer, offset + 0);
|
||||
ushort temp = BigEndianConverter.ToUInt16(buffer, offset + 2);
|
||||
ResultCode = (byte)(temp & 0xF);
|
||||
Flags = (OperationFlags)((temp >> 4) & 0x7F);
|
||||
OpCode = (NameServiceOperation)((temp >> 11) & 0x1F);
|
||||
QDCount = BigEndianConverter.ToUInt16(buffer, offset + 4);
|
||||
ANCount = BigEndianConverter.ToUInt16(buffer, offset + 6);
|
||||
NSCount = BigEndianConverter.ToUInt16(buffer, offset + 8);
|
||||
ARCount = BigEndianConverter.ToUInt16(buffer, offset + 10);
|
||||
}
|
||||
|
||||
public void WriteBytes(Stream stream)
|
||||
{
|
||||
BigEndianWriter.WriteUInt16(stream, TransactionID);
|
||||
ushort temp = (ushort)(ResultCode & (0xF));
|
||||
temp |= (ushort)((byte)Flags << 4);
|
||||
temp |= (ushort)((byte)OpCode << 11);
|
||||
BigEndianWriter.WriteUInt16(stream, temp);
|
||||
BigEndianWriter.WriteUInt16(stream, QDCount);
|
||||
BigEndianWriter.WriteUInt16(stream, ANCount);
|
||||
BigEndianWriter.WriteUInt16(stream, NSCount);
|
||||
BigEndianWriter.WriteUInt16(stream, ARCount);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
64
SMBLibrary/NetBios/NameServicePackets/NodeStatusResponse.cs
Normal file
64
SMBLibrary/NetBios/NameServicePackets/NodeStatusResponse.cs
Normal file
|
@ -0,0 +1,64 @@
|
|||
/* Copyright (C) 2014 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 System.IO;
|
||||
using System.Text;
|
||||
using Utilities;
|
||||
|
||||
namespace SMBLibrary.NetBios
|
||||
{
|
||||
/// <summary>
|
||||
/// [RFC 1002] 4.2.18. NODE STATUS RESPONSE
|
||||
/// </summary>
|
||||
public class NodeStatusResponse
|
||||
{
|
||||
public NameServicePacketHeader Header;
|
||||
public ResourceRecord Resource;
|
||||
// byte NumberOfNames;
|
||||
public KeyValuePairList<string, NameFlags> Names = new KeyValuePairList<string, NameFlags>();
|
||||
public NodeStatistics Statistics;
|
||||
|
||||
public NodeStatusResponse()
|
||||
{
|
||||
Header = new NameServicePacketHeader();
|
||||
Header.OpCode = NameServiceOperation.QueryResponse;
|
||||
Header.Flags = OperationFlags.AuthoritativeAnswer | OperationFlags.RecursionAvailable;
|
||||
Header.ANCount = 1;
|
||||
Resource = new ResourceRecord();
|
||||
Resource.Type = NameRecordType.NBStat;
|
||||
Statistics = new NodeStatistics();
|
||||
}
|
||||
|
||||
public byte[] GetBytes()
|
||||
{
|
||||
Resource.Data = GetData();
|
||||
|
||||
MemoryStream stream = new MemoryStream();
|
||||
Header.WriteBytes(stream);
|
||||
Resource.WriteBytes(stream);
|
||||
return stream.ToArray();
|
||||
}
|
||||
|
||||
public byte[] GetData()
|
||||
{
|
||||
MemoryStream stream = new MemoryStream();
|
||||
stream.WriteByte((byte)Names.Count);
|
||||
foreach (KeyValuePair<string, NameFlags> entry in Names)
|
||||
{
|
||||
ByteWriter.WriteAnsiString(stream, entry.Key);
|
||||
//byte[] encodedName = NetBiosUtils.EncodeName(entry.Key, String.Empty);
|
||||
//ByteWriter.WriteBytes(stream, encodedName);
|
||||
BigEndianWriter.WriteUInt16(stream, entry.Value.Value);
|
||||
}
|
||||
|
||||
ByteWriter.WriteBytes(stream, Statistics.GetBytes());
|
||||
|
||||
return stream.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/* Copyright (C) 2014 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 System.IO;
|
||||
using System.Text;
|
||||
using Utilities;
|
||||
|
||||
namespace SMBLibrary.NetBios
|
||||
{
|
||||
/// <summary>
|
||||
/// [RFC 1002] 4.2.13. POSITIVE NAME QUERY RESPONSE
|
||||
/// </summary>
|
||||
public class PositiveNameQueryResponse
|
||||
{
|
||||
public const int EntryLength = 6;
|
||||
|
||||
public NameServicePacketHeader Header;
|
||||
public ResourceRecord Resource;
|
||||
public KeyValuePairList<byte[], NameFlags> Addresses = new KeyValuePairList<byte[], NameFlags>();
|
||||
|
||||
public PositiveNameQueryResponse()
|
||||
{
|
||||
Header = new NameServicePacketHeader();
|
||||
Header.Flags = OperationFlags.AuthoritativeAnswer | OperationFlags.RecursionDesired;
|
||||
Header.OpCode = NameServiceOperation.QueryResponse;
|
||||
Header.ANCount = 1;
|
||||
Resource = new ResourceRecord();
|
||||
}
|
||||
|
||||
public byte[] GetBytes()
|
||||
{
|
||||
Resource.Data = GetData();
|
||||
|
||||
MemoryStream stream = new MemoryStream();
|
||||
Header.WriteBytes(stream);
|
||||
Resource.WriteBytes(stream);
|
||||
return stream.ToArray();
|
||||
}
|
||||
|
||||
public byte[] GetData()
|
||||
{
|
||||
byte[] data = new byte[EntryLength * Addresses.Count];
|
||||
int offset = 0;
|
||||
foreach (KeyValuePair<byte[], NameFlags> entry in Addresses)
|
||||
{
|
||||
BigEndianWriter.WriteUInt16(data, ref offset, entry.Value.Value);
|
||||
ByteWriter.WriteBytes(data, ref offset, entry.Key, 4);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
/* Copyright (C) 2014 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 System.Text;
|
||||
using Utilities;
|
||||
|
||||
namespace SMBLibrary.NetBios
|
||||
{
|
||||
public class NodeStatistics
|
||||
{
|
||||
public const int Length = 46;
|
||||
|
||||
public byte[] UnitID; // MAC address, 6 bytes;
|
||||
public byte Jumpers;
|
||||
public byte TestResult;
|
||||
public ushort VersionNumber;
|
||||
public ushort PeriodOfStatistics;
|
||||
public ushort NumberOfCRCs;
|
||||
public ushort NumberOfAlignmentErrors;
|
||||
public ushort NumberOfCollisions;
|
||||
public ushort NumberOfSendAborts;
|
||||
public uint NumberOfGoodSends;
|
||||
public uint NumberOfGoodReceives;
|
||||
public ushort NumberOfRetransmits;
|
||||
public ushort NumberOfNoResourceConditions;
|
||||
public ushort NumberOfFreeCommandBlocks;
|
||||
public ushort TotalNumberOfCommandBlocks;
|
||||
public ushort MaxTotalNumberOfCommandBlocks;
|
||||
public ushort NumberOfPendingSessions;
|
||||
public ushort MaxNumberOfPendingSessions;
|
||||
public ushort MaxTotalsSessionsPossible;
|
||||
public ushort SessionDataPacketSize;
|
||||
|
||||
public NodeStatistics()
|
||||
{
|
||||
UnitID = new byte[6];
|
||||
}
|
||||
|
||||
public void WriteBytes(byte[] buffer, int offset)
|
||||
{
|
||||
ByteWriter.WriteBytes(buffer, ref offset, UnitID, 6);
|
||||
ByteWriter.WriteByte(buffer, ref offset, Jumpers);
|
||||
ByteWriter.WriteByte(buffer, ref offset, TestResult);
|
||||
BigEndianWriter.WriteUInt16(buffer, ref offset, VersionNumber);
|
||||
BigEndianWriter.WriteUInt16(buffer, ref offset, PeriodOfStatistics);
|
||||
BigEndianWriter.WriteUInt16(buffer, ref offset, NumberOfCRCs);
|
||||
BigEndianWriter.WriteUInt16(buffer, ref offset, NumberOfAlignmentErrors);
|
||||
BigEndianWriter.WriteUInt16(buffer, ref offset, NumberOfCollisions);
|
||||
BigEndianWriter.WriteUInt16(buffer, ref offset, NumberOfSendAborts);
|
||||
BigEndianWriter.WriteUInt32(buffer, ref offset, NumberOfGoodSends);
|
||||
BigEndianWriter.WriteUInt32(buffer, ref offset, NumberOfGoodReceives);
|
||||
BigEndianWriter.WriteUInt16(buffer, ref offset, NumberOfRetransmits);
|
||||
BigEndianWriter.WriteUInt16(buffer, ref offset, NumberOfNoResourceConditions);
|
||||
BigEndianWriter.WriteUInt16(buffer, ref offset, NumberOfFreeCommandBlocks);
|
||||
BigEndianWriter.WriteUInt16(buffer, ref offset, TotalNumberOfCommandBlocks);
|
||||
BigEndianWriter.WriteUInt16(buffer, ref offset, MaxTotalNumberOfCommandBlocks);
|
||||
BigEndianWriter.WriteUInt16(buffer, ref offset, NumberOfPendingSessions);
|
||||
BigEndianWriter.WriteUInt16(buffer, ref offset, MaxNumberOfPendingSessions);
|
||||
BigEndianWriter.WriteUInt16(buffer, ref offset, MaxTotalsSessionsPossible);
|
||||
BigEndianWriter.WriteUInt16(buffer, ref offset, SessionDataPacketSize);
|
||||
}
|
||||
|
||||
public byte[] GetBytes()
|
||||
{
|
||||
byte[] buffer = new byte[Length];
|
||||
WriteBytes(buffer, 0);
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/* Copyright (C) 2014 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 System.IO;
|
||||
using System.Text;
|
||||
using Utilities;
|
||||
|
||||
namespace SMBLibrary.NetBios
|
||||
{
|
||||
/// <summary>
|
||||
/// [RFC 1002] 4.2.1.2. QUESTION SECTION
|
||||
/// </summary>
|
||||
public class QuestionSection
|
||||
{
|
||||
public string Name;
|
||||
public NameRecordType Type = NameRecordType.NB; // NB
|
||||
public ushort Class = 0x0001; // IN
|
||||
|
||||
public QuestionSection()
|
||||
{
|
||||
}
|
||||
|
||||
public QuestionSection(byte[] buffer, ref int offset)
|
||||
{
|
||||
Name = NetBiosUtils.DecodeName(buffer, ref offset);
|
||||
Type = (NameRecordType)BigEndianReader.ReadUInt16(buffer, ref offset);
|
||||
Class = BigEndianReader.ReadUInt16(buffer, ref offset);
|
||||
}
|
||||
|
||||
public void WriteBytes(Stream stream)
|
||||
{
|
||||
byte[] encodedName = NetBiosUtils.EncodeName(Name, String.Empty);
|
||||
ByteWriter.WriteBytes(stream, encodedName);
|
||||
BigEndianWriter.WriteUInt16(stream, (ushort)Type);
|
||||
BigEndianWriter.WriteUInt16(stream, Class);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/* Copyright (C) 2014 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 System.IO;
|
||||
using System.Text;
|
||||
using Utilities;
|
||||
|
||||
namespace SMBLibrary.NetBios
|
||||
{
|
||||
/// <summary>
|
||||
/// [RFC 1002] 4.2.1.3. RESOURCE RECORD
|
||||
/// </summary>
|
||||
public class ResourceRecord
|
||||
{
|
||||
public string Name;
|
||||
public NameRecordType Type = NameRecordType.NB; // NB
|
||||
public ushort Class = 0x0001; // IN
|
||||
public uint TTL;
|
||||
// ushort DataLength
|
||||
public byte[] Data;
|
||||
|
||||
public ResourceRecord()
|
||||
{
|
||||
Name = String.Empty;
|
||||
TTL = (uint)new TimeSpan(7, 0, 0, 0).TotalSeconds;
|
||||
Data = new byte[0];
|
||||
}
|
||||
|
||||
public void WriteBytes(Stream stream)
|
||||
{
|
||||
WriteBytes(stream, null);
|
||||
}
|
||||
|
||||
public void WriteBytes(Stream stream, int? nameOffset)
|
||||
{
|
||||
if (nameOffset.HasValue)
|
||||
{
|
||||
NetBiosUtils.WriteNamePointer(stream, nameOffset.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
byte[] encodedName = NetBiosUtils.EncodeName(Name, String.Empty);
|
||||
ByteWriter.WriteBytes(stream, encodedName);
|
||||
}
|
||||
BigEndianWriter.WriteUInt16(stream, (ushort)Type);
|
||||
BigEndianWriter.WriteUInt16(stream, Class);
|
||||
BigEndianWriter.WriteUInt32(stream, TTL);
|
||||
BigEndianWriter.WriteUInt16(stream, (ushort)Data.Length);
|
||||
ByteWriter.WriteBytes(stream, Data);
|
||||
}
|
||||
}
|
||||
}
|
207
SMBLibrary/NetBios/NetBiosUtils.cs
Normal file
207
SMBLibrary/NetBios/NetBiosUtils.cs
Normal file
|
@ -0,0 +1,207 @@
|
|||
/* Copyright (C) 2014 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 System.IO;
|
||||
using System.Text;
|
||||
using Utilities;
|
||||
|
||||
namespace SMBLibrary.NetBios
|
||||
{
|
||||
public class NetBiosUtils
|
||||
{
|
||||
/// <summary>
|
||||
/// The NetBIOS naming convention allows for 16 characters in a NetBIOS name.
|
||||
/// Microsoft, however, limits NetBIOS names to 15 characters and uses the 16th character as a NetBIOS suffix
|
||||
/// See http://support.microsoft.com/kb/163409/en-us
|
||||
/// </summary>
|
||||
public static string GetMSNetBiosName(string name, NetBiosSuffix suffix)
|
||||
{
|
||||
if (name.Length > 15)
|
||||
{
|
||||
name = name.Substring(0, 15);
|
||||
}
|
||||
else if (name.Length < 15)
|
||||
{
|
||||
name = name.PadRight(15);
|
||||
}
|
||||
|
||||
return name + (char)suffix;
|
||||
}
|
||||
|
||||
public static string GetNameFromMSNetBiosName(string netBiosName)
|
||||
{
|
||||
if (netBiosName.Length != 16)
|
||||
{
|
||||
throw new ArgumentException("Invalid MS NetBIOS name");
|
||||
}
|
||||
|
||||
netBiosName = netBiosName.Substring(0, 15);
|
||||
return netBiosName.TrimEnd(' ');
|
||||
}
|
||||
|
||||
public static byte[] EncodeName(string name, NetBiosSuffix suffix, string scopeID)
|
||||
{
|
||||
string netBiosName = GetMSNetBiosName(name, suffix);
|
||||
return EncodeName(netBiosName, scopeID);
|
||||
}
|
||||
|
||||
/// <param name="name">NetBIOS name</param>
|
||||
/// <param name="scopeID">dot-separated labels, formatted per DNS naming rules</param>
|
||||
public static byte[] EncodeName(string netBiosName, string scopeID)
|
||||
{
|
||||
string domainName = FirstLevelEncoding(netBiosName, scopeID);
|
||||
return SecondLevelEncoding(domainName);
|
||||
}
|
||||
|
||||
// The conversion of a NetBIOS name to a format complying with DNS "best practices".
|
||||
// NetBIOS names may contain characters which are not considered valid for use in DNS names,
|
||||
// yet RFC 1001 and RFC 1002 attempted to map the NetBIOS name space into the DNS name space.
|
||||
// To work around this conflict, NetBIOS names are encoded by splitting each byte of the name
|
||||
// into two nibbles and then adding the value of 'A' (0x41).
|
||||
// Thus, the '&' character (0x26) would be encoded as "CG".
|
||||
// NetBIOS names are usually padded with spaces before being encoded.
|
||||
/// <param name="name">NetBIOS name</param>
|
||||
/// <param name="scopeID">dot-separated labels, formatted per DNS naming rules</param>
|
||||
public static string FirstLevelEncoding(string netBiosName, string scopeID)
|
||||
{
|
||||
// RFC 1001: NetBIOS names as seen across the client interface to NetBIOS are exactly 16 bytes long
|
||||
if (netBiosName.Length != 16)
|
||||
{
|
||||
throw new ArgumentException("Invalid MS NetBIOS name");
|
||||
}
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (int index = 0; index < netBiosName.Length; index++)
|
||||
{
|
||||
byte c = (byte)netBiosName[index];
|
||||
byte high = (byte)(0x41 + (c >> 4));
|
||||
byte low = (byte)(0x41 + (c & 0x0F));
|
||||
builder.Append((char)high);
|
||||
builder.Append((char)low);
|
||||
}
|
||||
|
||||
if (scopeID.Length > 0)
|
||||
{
|
||||
builder.Append(".");
|
||||
builder.Append(scopeID);
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
// Domain names messages are expressed in terms of a sequence
|
||||
// of labels. Each label is represented as a one octet length
|
||||
// field followed by that number of octets. Since every domain
|
||||
// name ends with the null label of the root, a compressed
|
||||
// domain name is terminated by a length byte of zero
|
||||
/// <summary>
|
||||
/// The on-the-wire format of an NBT name. The encoding scheme replaces the familiar dot characters
|
||||
/// used in DNS names with a byte containing the length of the next label.
|
||||
/// </summary>
|
||||
public static byte[] SecondLevelEncoding(string domainName)
|
||||
{
|
||||
string[] labels = domainName.Split('.');
|
||||
int length = 1; // null terminator
|
||||
for (int index = 0; index < labels.Length; index++)
|
||||
{
|
||||
length += 1 + labels[index].Length;
|
||||
if (labels[index].Length > 63)
|
||||
{
|
||||
throw new ArgumentException("Invalid NetBIOS label length");
|
||||
}
|
||||
}
|
||||
|
||||
byte[] result = new byte[length];
|
||||
int offset = 0;
|
||||
foreach(string label in labels)
|
||||
{
|
||||
result[offset] = (byte)label.Length;
|
||||
offset++;
|
||||
ByteWriter.WriteAnsiString(result, offset, label, label.Length);
|
||||
offset += label.Length;
|
||||
}
|
||||
|
||||
result[offset] = 0; // null termination
|
||||
return result;
|
||||
}
|
||||
|
||||
public static string DecodeName(byte[] buffer, ref int offset)
|
||||
{
|
||||
string domainName = SecondLevelDecoding(buffer, ref offset);
|
||||
string name = domainName.Split('.')[0];
|
||||
return FirstLevelDecoding(name);
|
||||
}
|
||||
|
||||
public static string SecondLevelDecoding(byte[] buffer, ref int offset)
|
||||
{
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
byte labelLength = ByteReader.ReadByte(buffer, ref offset);
|
||||
while (labelLength > 0)
|
||||
{
|
||||
if (builder.Length > 0)
|
||||
{
|
||||
builder.Append(".");
|
||||
}
|
||||
|
||||
// The high order two bits of the length field must be zero
|
||||
if (labelLength > 63)
|
||||
{
|
||||
throw new ArgumentException("Invalid NetBIOS label length");
|
||||
}
|
||||
|
||||
string label = ByteReader.ReadAnsiString(buffer, offset, labelLength);
|
||||
builder.Append(label);
|
||||
offset += labelLength;
|
||||
|
||||
labelLength = ByteReader.ReadByte(buffer, ref offset);
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
public static string FirstLevelDecoding(string name)
|
||||
{
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
for(int index = 0; index < name.Length; index += 2)
|
||||
{
|
||||
byte c0 = (byte)name[index];
|
||||
byte c1 = (byte)name[index + 1];
|
||||
byte high = (byte)(((c0 - 0x41) & 0xF) << 4);
|
||||
byte low = (byte)((c1 - 0x41) & 0xF);
|
||||
byte c = (byte)(high | low);
|
||||
builder.Append((char)c);
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
public static void WriteNamePointer(byte[] buffer, ref int offset, int nameOffset)
|
||||
{
|
||||
WriteNamePointer(buffer, offset, nameOffset);
|
||||
offset += 2;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Will write a 2 bytes pointer to a name
|
||||
/// Note: NetBIOS implementations can only use label string pointers in Name Service packets
|
||||
/// </summary>
|
||||
public static void WriteNamePointer(byte[] buffer, int offset, int nameOffset)
|
||||
{
|
||||
ushort pointer = (ushort)(0xC000 | (nameOffset & 0x3FFF));
|
||||
BigEndianWriter.WriteUInt16(buffer, offset, pointer);
|
||||
}
|
||||
|
||||
public static void WriteNamePointer(Stream stream, int nameOffset)
|
||||
{
|
||||
ushort pointer = (ushort)(0xC000 | (nameOffset & 0x3FFF));
|
||||
BigEndianWriter.WriteUInt16(stream, pointer);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/* Copyright (C) 2014 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.
|
||||
*/
|
||||
namespace SMBLibrary.NetBios
|
||||
{
|
||||
/// <summary>
|
||||
/// [RFC 1002] 4.2.1.1. HEADER
|
||||
/// </summary>
|
||||
public enum SessionPacketTypeName : byte
|
||||
{
|
||||
SessionMessage = 0x00,
|
||||
SessionRequest = 0x81,
|
||||
PositiveSessionResponse = 0x82,
|
||||
NegativeSessionResponse = 0x83,
|
||||
RetargetSessionResponse = 0x84,
|
||||
SessionKeepAlive = 0x85,
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/* Copyright (C) 2014 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 System.Text;
|
||||
using Utilities;
|
||||
|
||||
namespace SMBLibrary.NetBios
|
||||
{
|
||||
public class NegativeSessionResponsePacket : SessionPacket
|
||||
{
|
||||
public byte ErrorCode;
|
||||
|
||||
public NegativeSessionResponsePacket() : base()
|
||||
{
|
||||
this.Type = SessionPacketTypeName.NegativeSessionResponse;
|
||||
}
|
||||
|
||||
public NegativeSessionResponsePacket(byte[] buffer) : base(buffer)
|
||||
{
|
||||
ErrorCode = ByteReader.ReadByte(this.Trailer, 0);
|
||||
}
|
||||
|
||||
public override byte[] GetBytes()
|
||||
{
|
||||
this.Trailer = new byte[1];
|
||||
this.Trailer[0] = ErrorCode;
|
||||
|
||||
return base.GetBytes();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/* Copyright (C) 2014 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 System.Text;
|
||||
using Utilities;
|
||||
|
||||
namespace SMBLibrary.NetBios
|
||||
{
|
||||
public class PositiveSessionResponsePacket : SessionPacket
|
||||
{
|
||||
public PositiveSessionResponsePacket() : base()
|
||||
{
|
||||
this.Type = SessionPacketTypeName.PositiveSessionResponse;
|
||||
}
|
||||
|
||||
public PositiveSessionResponsePacket(byte[] buffer) : base(buffer)
|
||||
{
|
||||
}
|
||||
|
||||
public override byte[] GetBytes()
|
||||
{
|
||||
this.Trailer = new byte[0];
|
||||
return base.GetBytes();
|
||||
}
|
||||
}
|
||||
}
|
31
SMBLibrary/NetBios/SessionPackets/SessionKeepAlivePacket.cs
Normal file
31
SMBLibrary/NetBios/SessionPackets/SessionKeepAlivePacket.cs
Normal file
|
@ -0,0 +1,31 @@
|
|||
/* Copyright (C) 2014 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 System.Text;
|
||||
using Utilities;
|
||||
|
||||
namespace SMBLibrary.NetBios
|
||||
{
|
||||
public class SessionKeepAlivePacket : SessionPacket
|
||||
{
|
||||
public SessionKeepAlivePacket()
|
||||
{
|
||||
this.Type = SessionPacketTypeName.SessionKeepAlive;
|
||||
}
|
||||
|
||||
public SessionKeepAlivePacket(byte[] buffer) : base(buffer)
|
||||
{
|
||||
}
|
||||
|
||||
public override byte[] GetBytes()
|
||||
{
|
||||
this.Trailer = new byte[0];
|
||||
return base.GetBytes();
|
||||
}
|
||||
}
|
||||
}
|
25
SMBLibrary/NetBios/SessionPackets/SessionMessagePacket.cs
Normal file
25
SMBLibrary/NetBios/SessionPackets/SessionMessagePacket.cs
Normal file
|
@ -0,0 +1,25 @@
|
|||
/* Copyright (C) 2014 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 System.Text;
|
||||
using Utilities;
|
||||
|
||||
namespace SMBLibrary.NetBios
|
||||
{
|
||||
public class SessionMessagePacket : SessionPacket
|
||||
{
|
||||
public SessionMessagePacket() : base()
|
||||
{
|
||||
this.Type = SessionPacketTypeName.SessionMessage;
|
||||
}
|
||||
|
||||
public SessionMessagePacket(byte[] buffer) : base(buffer)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
75
SMBLibrary/NetBios/SessionPackets/SessionPacket.cs
Normal file
75
SMBLibrary/NetBios/SessionPackets/SessionPacket.cs
Normal file
|
@ -0,0 +1,75 @@
|
|||
/* Copyright (C) 2014 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 System.Text;
|
||||
using Utilities;
|
||||
|
||||
namespace SMBLibrary.NetBios
|
||||
{
|
||||
public abstract class SessionPacket
|
||||
{
|
||||
public SessionPacketTypeName Type;
|
||||
public byte Flags;
|
||||
public int Length; // 2 bytes + length extension bit
|
||||
public byte[] Trailer;
|
||||
|
||||
public SessionPacket()
|
||||
{
|
||||
}
|
||||
|
||||
public SessionPacket(byte[] buffer)
|
||||
{
|
||||
Type = (SessionPacketTypeName)ByteReader.ReadByte(buffer, 0);
|
||||
Flags = ByteReader.ReadByte(buffer, 1);
|
||||
Length = (Flags & 0x01) << 16 | BigEndianConverter.ToUInt16(buffer, 2);
|
||||
|
||||
this.Trailer = ByteReader.ReadBytes(buffer, 4, Length);
|
||||
}
|
||||
|
||||
public virtual byte[] GetBytes()
|
||||
{
|
||||
Length = this.Trailer.Length;
|
||||
if (Length > 0x1FFFF)
|
||||
{
|
||||
throw new ArgumentException("Invalid NBT packet length");
|
||||
}
|
||||
|
||||
Flags = Convert.ToByte(Length > 0xFFFF);
|
||||
|
||||
byte[] buffer = new byte[4 + Trailer.Length];
|
||||
ByteWriter.WriteByte(buffer, 0, (byte)this.Type);
|
||||
ByteWriter.WriteByte(buffer, 1, Flags);
|
||||
BigEndianWriter.WriteUInt16(buffer, 2, (ushort)(Length & 0xFFFF));
|
||||
ByteWriter.WriteBytes(buffer, 4, this.Trailer);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public static SessionPacket GetSessionPacket(byte[] buffer)
|
||||
{
|
||||
SessionPacketTypeName type = (SessionPacketTypeName)ByteReader.ReadByte(buffer, 0);
|
||||
switch (type)
|
||||
{
|
||||
case SessionPacketTypeName.SessionMessage:
|
||||
return new SessionMessagePacket(buffer);
|
||||
case SessionPacketTypeName.SessionRequest:
|
||||
return new SessionRequestPacket(buffer);
|
||||
case SessionPacketTypeName.PositiveSessionResponse:
|
||||
return new PositiveSessionResponsePacket(buffer);
|
||||
case SessionPacketTypeName.NegativeSessionResponse:
|
||||
return new NegativeSessionResponsePacket(buffer);
|
||||
case SessionPacketTypeName.RetargetSessionResponse:
|
||||
return new SessionRetargetResponsePacket(buffer);
|
||||
case SessionPacketTypeName.SessionKeepAlive:
|
||||
return new SessionKeepAlivePacket(buffer);
|
||||
default:
|
||||
throw new InvalidRequestException("Invalid NetBIOS Session Packet");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
41
SMBLibrary/NetBios/SessionPackets/SessionRequestPacket.cs
Normal file
41
SMBLibrary/NetBios/SessionPackets/SessionRequestPacket.cs
Normal file
|
@ -0,0 +1,41 @@
|
|||
/* Copyright (C) 2014 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 System.Text;
|
||||
using Utilities;
|
||||
|
||||
namespace SMBLibrary.NetBios
|
||||
{
|
||||
public class SessionRequestPacket : SessionPacket
|
||||
{
|
||||
public string CalledName;
|
||||
public string CallingName;
|
||||
|
||||
public SessionRequestPacket()
|
||||
{
|
||||
this.Type = SessionPacketTypeName.SessionRequest;
|
||||
}
|
||||
|
||||
public SessionRequestPacket(byte[] buffer) : base(buffer)
|
||||
{
|
||||
int offset = 0;
|
||||
CalledName = NetBiosUtils.DecodeName(this.Trailer, ref offset);
|
||||
CallingName = NetBiosUtils.DecodeName(this.Trailer, ref offset);
|
||||
}
|
||||
|
||||
public override byte[] GetBytes()
|
||||
{
|
||||
byte[] part1 = NetBiosUtils.EncodeName(CalledName, String.Empty);
|
||||
byte[] part2 = NetBiosUtils.EncodeName(CallingName, String.Empty);
|
||||
this.Trailer = new byte[part1.Length + part2.Length];
|
||||
ByteWriter.WriteBytes(this.Trailer, 0, part1);
|
||||
ByteWriter.WriteBytes(this.Trailer, part1.Length, part2);
|
||||
return base.GetBytes();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/* Copyright (C) 2014 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 System.Text;
|
||||
using Utilities;
|
||||
|
||||
namespace SMBLibrary.NetBios
|
||||
{
|
||||
public class SessionRetargetResponsePacket : SessionPacket
|
||||
{
|
||||
uint IPAddress;
|
||||
ushort Port;
|
||||
|
||||
public SessionRetargetResponsePacket() : base()
|
||||
{
|
||||
this.Type = SessionPacketTypeName.RetargetSessionResponse;
|
||||
}
|
||||
|
||||
public SessionRetargetResponsePacket(byte[] buffer) : base(buffer)
|
||||
{
|
||||
IPAddress = BigEndianConverter.ToUInt32(this.Trailer, 0);
|
||||
Port = BigEndianConverter.ToUInt16(this.Trailer, 4);
|
||||
}
|
||||
|
||||
public override byte[] GetBytes()
|
||||
{
|
||||
this.Trailer = new byte[6];
|
||||
BigEndianWriter.WriteUInt32(this.Trailer, 0, IPAddress);
|
||||
BigEndianWriter.WriteUInt16(this.Trailer, 4, Port);
|
||||
return base.GetBytes();
|
||||
}
|
||||
}
|
||||
}
|
35
SMBLibrary/Properties/AssemblyInfo.cs
Normal file
35
SMBLibrary/Properties/AssemblyInfo.cs
Normal file
|
@ -0,0 +1,35 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("SMBLibrary")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("Tal Aloni")]
|
||||
[assembly: AssemblyProduct("SMBLibrary")]
|
||||
[assembly: AssemblyCopyright("Copyright © Tal Aloni 2014-2016")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("301890e4-fc53-448e-8070-79d17086f922")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Revision and Build Numbers
|
||||
// by using the '*' as shown below:
|
||||
[assembly: AssemblyVersion("1.0.5.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.5.0")]
|
16
SMBLibrary/RPC/Enum/NegotiationResult.cs
Normal file
16
SMBLibrary/RPC/Enum/NegotiationResult.cs
Normal file
|
@ -0,0 +1,16 @@
|
|||
|
||||
namespace SMBLibrary.RPC
|
||||
{
|
||||
public enum NegotiationResult : ushort
|
||||
{
|
||||
Acceptance,
|
||||
UserRejection,
|
||||
ProviderRejection,
|
||||
|
||||
/// <summary>
|
||||
/// Microsoft extension:
|
||||
/// [MS-RPCE] 2.2.2.4 - negotiate_ack
|
||||
/// </summary>
|
||||
NegotiateAck
|
||||
}
|
||||
}
|
16
SMBLibrary/RPC/Enum/PacketFlags.cs
Normal file
16
SMBLibrary/RPC/Enum/PacketFlags.cs
Normal file
|
@ -0,0 +1,16 @@
|
|||
using System;
|
||||
|
||||
namespace SMBLibrary.RPC
|
||||
{
|
||||
[Flags]
|
||||
public enum PacketFlags : byte
|
||||
{
|
||||
FirstFragment = 0x01, // PFC_FIRST_FRAG
|
||||
LastFragment = 0x02, // PFC_LAST_FRAG
|
||||
PendingCancel = 0x04, // PFC_PENDING_CANCEL
|
||||
ConcurrntMultiplexing = 0x10, // PFC_CONC_MPX
|
||||
DidNotExecute = 0x20, // PFC_DID_NOT_EXECUTE
|
||||
Maybe = 0x40, // PFC_MAYBE
|
||||
ObjectUUID = 0x80, // PFC_OBJECT_UUID
|
||||
}
|
||||
}
|
27
SMBLibrary/RPC/Enum/PacketTypeName.cs
Normal file
27
SMBLibrary/RPC/Enum/PacketTypeName.cs
Normal file
|
@ -0,0 +1,27 @@
|
|||
|
||||
namespace SMBLibrary.RPC
|
||||
{
|
||||
// Commented out packet types are connectionless-only
|
||||
public enum PacketTypeName : byte
|
||||
{
|
||||
Request = 0x00,
|
||||
// Ping = 0x01,
|
||||
Response = 0x02,
|
||||
Fault = 0x03,
|
||||
//Working = 0x04,
|
||||
//NoCall = 0x05,
|
||||
//Reject = 0x06,
|
||||
//Ack = 0x07,
|
||||
//CLCancel = 0x08, // cl_cancel
|
||||
//FAck = 0x09,
|
||||
//CancelAck = 0x0A, // cancel_ack
|
||||
Bind = 0x0B,
|
||||
BindAck = 0x0C,
|
||||
BindNak = 0x0D, // bind_nak
|
||||
AlterContext = 0x0E, // alter_context
|
||||
AlterContextResponse = 0x0F, // alter_context_resp
|
||||
Shutdown = 0x11,
|
||||
COCancel = 0x12, // co_cancel
|
||||
Orphaned = 0x13,
|
||||
}
|
||||
}
|
11
SMBLibrary/RPC/Enum/RejectionReason.cs
Normal file
11
SMBLibrary/RPC/Enum/RejectionReason.cs
Normal file
|
@ -0,0 +1,11 @@
|
|||
|
||||
namespace SMBLibrary.RPC
|
||||
{
|
||||
public enum RejectionReason : ushort
|
||||
{
|
||||
NotSpecified,
|
||||
AbstractSyntaxNotSupported,
|
||||
ProposedTransferSyntaxesNotSupported,
|
||||
LocalLimitExceeded,
|
||||
}
|
||||
}
|
52
SMBLibrary/RPC/EnumStructures/DataRepresentationFormat.cs
Normal file
52
SMBLibrary/RPC/EnumStructures/DataRepresentationFormat.cs
Normal file
|
@ -0,0 +1,52 @@
|
|||
/* Copyright (C) 2014 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;
|
||||
|
||||
namespace SMBLibrary.RPC
|
||||
{
|
||||
// See DCE 1.1: Remote Procedure Call, Chapter 14.1 - Data Representation Format Label
|
||||
public enum CharacterFormat : byte
|
||||
{
|
||||
ASCII = 0x00,
|
||||
EBCDIC = 0x01,
|
||||
}
|
||||
|
||||
public enum ByteOrder : byte
|
||||
{
|
||||
BigEndian = 0x00,
|
||||
LittleEndian = 0x01,
|
||||
}
|
||||
|
||||
public enum FloatingPointRepresentation : byte
|
||||
{
|
||||
IEEE = 0x00,
|
||||
VAX = 0x01,
|
||||
Cray = 0x02,
|
||||
IBM = 0x03,
|
||||
}
|
||||
|
||||
public struct DataRepresentationFormat // uint
|
||||
{
|
||||
public CharacterFormat CharacterFormat;
|
||||
public ByteOrder ByteOrder;
|
||||
public FloatingPointRepresentation FloatingPointRepresentation;
|
||||
|
||||
public DataRepresentationFormat(byte[] buffer, int offset)
|
||||
{
|
||||
CharacterFormat = (CharacterFormat)(buffer[offset + 0] & 0x0F);
|
||||
ByteOrder = (ByteOrder)(buffer[offset + 0] >> 4);
|
||||
FloatingPointRepresentation = (FloatingPointRepresentation)(buffer[offset + 1]);
|
||||
}
|
||||
|
||||
public void WriteBytes(byte[] buffer, int offset)
|
||||
{
|
||||
buffer[offset + 0] = (byte)CharacterFormat;
|
||||
buffer[offset + 0] |= (byte)((byte)ByteOrder << 4);
|
||||
buffer[offset + 1] = (byte)FloatingPointRepresentation;
|
||||
}
|
||||
}
|
||||
}
|
21
SMBLibrary/RPC/NDR/INDRStructure.cs
Normal file
21
SMBLibrary/RPC/NDR/INDRStructure.cs
Normal file
|
@ -0,0 +1,21 @@
|
|||
/* Copyright (C) 2014 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 System.Text;
|
||||
|
||||
namespace SMBLibrary.RPC
|
||||
{
|
||||
/// <summary>
|
||||
/// Serializable Structure / Union / Array
|
||||
/// </summary>
|
||||
public interface INDRStructure
|
||||
{
|
||||
void Read(NDRParser parser);
|
||||
void Write(NDRWriter writer);
|
||||
}
|
||||
}
|
45
SMBLibrary/RPC/NDR/NDRConformantArray.cs
Normal file
45
SMBLibrary/RPC/NDR/NDRConformantArray.cs
Normal file
|
@ -0,0 +1,45 @@
|
|||
/* Copyright (C) 2014 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 System.Text;
|
||||
|
||||
namespace SMBLibrary.RPC
|
||||
{
|
||||
public class NDRConformantArray<T> : List<T>, INDRStructure where T : INDRStructure, new()
|
||||
{
|
||||
/// <summary>
|
||||
/// See DCE 1.1: Remote Procedure Call - 14.3.3.2 - Uni-dimensional Conformant Arrays
|
||||
/// </summary>
|
||||
/// <param name="parser"></param>
|
||||
public void Read(NDRParser parser)
|
||||
{
|
||||
parser.BeginStructure();
|
||||
uint maxCount = parser.ReadUInt32();
|
||||
for (int index = 0; index < maxCount; index++)
|
||||
{
|
||||
T entry = new T();
|
||||
entry.Read(parser);
|
||||
this.Add(entry);
|
||||
}
|
||||
|
||||
parser.EndStructure();
|
||||
}
|
||||
|
||||
public void Write(NDRWriter writer)
|
||||
{
|
||||
writer.BeginStructure();
|
||||
uint maxCount = (uint)this.Count;
|
||||
writer.WriteUInt32(maxCount);
|
||||
for (int index = 0; index < this.Count; index++)
|
||||
{
|
||||
this[index].Write(writer);
|
||||
}
|
||||
writer.EndStructure();
|
||||
}
|
||||
}
|
||||
}
|
140
SMBLibrary/RPC/NDR/NDRParser.cs
Normal file
140
SMBLibrary/RPC/NDR/NDRParser.cs
Normal file
|
@ -0,0 +1,140 @@
|
|||
/* Copyright (C) 2014 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 System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using Utilities;
|
||||
|
||||
namespace SMBLibrary.RPC
|
||||
{
|
||||
/// <summary>
|
||||
/// NDR - Native Data Representation
|
||||
/// See DCE 1.1: Remote Procedure Call, Chapter 14 - Transfer Syntax NDR
|
||||
/// </summary>
|
||||
public class NDRParser
|
||||
{
|
||||
private byte[] m_buffer;
|
||||
private int m_offset;
|
||||
private int m_depth;
|
||||
private List<INDRStructure> m_deferredStructures = new List<INDRStructure>();
|
||||
private Dictionary<uint, INDRStructure> m_referentToInstance = new Dictionary<uint, INDRStructure>();
|
||||
|
||||
public NDRParser(byte[] buffer)
|
||||
{
|
||||
m_buffer = buffer;
|
||||
m_offset = 0;
|
||||
m_depth = 0;
|
||||
}
|
||||
|
||||
public void BeginStructure()
|
||||
{
|
||||
m_depth++;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add embedded pointer deferred structure (referent) parser
|
||||
/// </summary>
|
||||
private void AddDeferredStructure(INDRStructure structure)
|
||||
{
|
||||
m_deferredStructures.Add(structure);
|
||||
}
|
||||
|
||||
public void EndStructure()
|
||||
{
|
||||
m_depth--;
|
||||
// 14.3.12.3 - Algorithm for Deferral of Referents
|
||||
// Representations of (embedded) pointer referents are ordered according to a left-to-right, depth-first traversal of the embedding construction.
|
||||
// referent representations for the embedded construction are further deferred to a position in the octet stream that
|
||||
// follows the representation of the embedding construction. The set of referent representations for the embedded construction
|
||||
// is inserted among the referent representations for any pointers in the embedding construction, according to the order of elements or
|
||||
// members in the embedding construction
|
||||
if (m_depth == 0)
|
||||
{
|
||||
// Make a copy of all the deferred structures, additional deferred structures will be inserted to m_deferredStructures
|
||||
// as we process the existing list
|
||||
List<INDRStructure> deferredStructures = new List<INDRStructure>(m_deferredStructures);
|
||||
m_deferredStructures.Clear();
|
||||
// Read all deferred types:
|
||||
foreach (INDRStructure deferredStructure in deferredStructures)
|
||||
{
|
||||
deferredStructure.Read(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string ReadUnicodeString()
|
||||
{
|
||||
NDRUnicodeString unicodeString = new NDRUnicodeString(this);
|
||||
return unicodeString.Value;
|
||||
}
|
||||
|
||||
public void ReadStructure(INDRStructure structure)
|
||||
{
|
||||
structure.Read(this);
|
||||
}
|
||||
|
||||
// 14.3.11.1 - Top-level Full Pointers
|
||||
public string ReadTopLevelUnicodeStringPointer()
|
||||
{
|
||||
uint referentID = ReadUInt32();
|
||||
if (referentID == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (m_referentToInstance.ContainsKey(referentID))
|
||||
{
|
||||
NDRUnicodeString unicodeString = (NDRUnicodeString)m_referentToInstance[referentID];
|
||||
return unicodeString.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
NDRUnicodeString unicodeString = new NDRUnicodeString(this);
|
||||
m_referentToInstance.Add(referentID, unicodeString);
|
||||
return unicodeString.Value;
|
||||
}
|
||||
}
|
||||
|
||||
public void ReadEmbeddedStructureFullPointer(ref NDRUnicodeString structure)
|
||||
{
|
||||
ReadEmbeddedStructureFullPointer<NDRUnicodeString>(ref structure);
|
||||
}
|
||||
|
||||
public void ReadEmbeddedStructureFullPointer<T>(ref T structure) where T : INDRStructure, new ()
|
||||
{
|
||||
uint referentID = ReadUInt32();
|
||||
if (referentID != 0) // not null
|
||||
{
|
||||
if (structure == null)
|
||||
{
|
||||
structure = new T();
|
||||
}
|
||||
AddDeferredStructure(structure);
|
||||
}
|
||||
else
|
||||
{
|
||||
structure = default(T);
|
||||
}
|
||||
}
|
||||
|
||||
// 14.2.2 - Alignment of Primitive Types
|
||||
public uint ReadUInt16()
|
||||
{
|
||||
m_offset += (2 - (m_offset % 2)) % 2;
|
||||
return LittleEndianReader.ReadUInt16(m_buffer, ref m_offset);
|
||||
}
|
||||
|
||||
// 14.2.2 - Alignment of Primitive Types
|
||||
public uint ReadUInt32()
|
||||
{
|
||||
m_offset += (4 - (m_offset % 4)) % 4;
|
||||
return LittleEndianReader.ReadUInt32(m_buffer, ref m_offset);
|
||||
}
|
||||
}
|
||||
}
|
16
SMBLibrary/RPC/NDR/NDRTypeName.cs
Normal file
16
SMBLibrary/RPC/NDR/NDRTypeName.cs
Normal file
|
@ -0,0 +1,16 @@
|
|||
/* Copyright (C) 2014 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.
|
||||
*/
|
||||
namespace SMBLibrary.RPC
|
||||
{
|
||||
/// <summary>
|
||||
/// Primitive and construced types
|
||||
/// </summary>
|
||||
public enum NDRTypeName
|
||||
{
|
||||
UnicodeString,
|
||||
}
|
||||
}
|
74
SMBLibrary/RPC/NDR/NDRUnicodeString.cs
Normal file
74
SMBLibrary/RPC/NDR/NDRUnicodeString.cs
Normal file
|
@ -0,0 +1,74 @@
|
|||
/* Copyright (C) 2014 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 System.Text;
|
||||
using Utilities;
|
||||
|
||||
namespace SMBLibrary.RPC
|
||||
{
|
||||
public class NDRUnicodeString : INDRStructure
|
||||
{
|
||||
public string Value;
|
||||
|
||||
public NDRUnicodeString()
|
||||
{
|
||||
Value = String.Empty;
|
||||
}
|
||||
|
||||
public NDRUnicodeString(string value)
|
||||
{
|
||||
Value = value;
|
||||
}
|
||||
|
||||
public NDRUnicodeString(NDRParser parser)
|
||||
{
|
||||
Read(parser);
|
||||
}
|
||||
|
||||
// 14.3.4.2 - Conformant and Varying Strings
|
||||
public void Read(NDRParser parser)
|
||||
{
|
||||
uint maxCount = parser.ReadUInt32();
|
||||
// the offset from the first index of the string to the first index of the actual subset being passed
|
||||
uint index = parser.ReadUInt32();
|
||||
// actualCount includes the null terminator
|
||||
uint actualCount = parser.ReadUInt32();
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (int position = 0; position < actualCount - 1; position++)
|
||||
{
|
||||
builder.Append((char)parser.ReadUInt16());
|
||||
}
|
||||
this.Value = builder.ToString();
|
||||
parser.ReadUInt16(); // null terminator
|
||||
}
|
||||
|
||||
public void Write(NDRWriter writer)
|
||||
{
|
||||
int length = 0;
|
||||
if (Value != null)
|
||||
{
|
||||
length = Value.Length;
|
||||
}
|
||||
|
||||
// maxCount includes the null terminator
|
||||
uint maxCount = (uint)(length + 1);
|
||||
writer.WriteUInt32(maxCount);
|
||||
// the offset from the first index of the string to the first index of the actual subset being passed
|
||||
uint index = 0;
|
||||
writer.WriteUInt32(index);
|
||||
// actualCount includes the null terminator
|
||||
uint actualCount = (uint)(length + 1);
|
||||
writer.WriteUInt32(actualCount);
|
||||
for (int position = 0; position < length; position++)
|
||||
{
|
||||
writer.WriteUInt16((ushort)Value[position]);
|
||||
}
|
||||
writer.WriteUInt16(0); // null terminator
|
||||
}
|
||||
}
|
||||
}
|
140
SMBLibrary/RPC/NDR/NDRWriter.cs
Normal file
140
SMBLibrary/RPC/NDR/NDRWriter.cs
Normal file
|
@ -0,0 +1,140 @@
|
|||
/* Copyright (C) 2014 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 System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using Utilities;
|
||||
|
||||
namespace SMBLibrary.RPC
|
||||
{
|
||||
/// <summary>
|
||||
/// NDR - Native Data Representation
|
||||
/// See DCE 1.1: Remote Procedure Call, Chapter 14 - Transfer Syntax NDR
|
||||
/// </summary>
|
||||
public class NDRWriter
|
||||
{
|
||||
private MemoryStream m_stream = new MemoryStream();
|
||||
private int m_depth;
|
||||
private List<INDRStructure> m_deferredStructures = new List<INDRStructure>();
|
||||
private Dictionary<uint, INDRStructure> m_referentToInstance = new Dictionary<uint, INDRStructure>();
|
||||
private uint m_nextReferentID = 0x00020000;
|
||||
|
||||
public void BeginStructure()
|
||||
{
|
||||
m_depth++;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add embedded pointer deferred structure (referent) writer
|
||||
/// </summary>
|
||||
private void AddDeferredStructure(INDRStructure structure)
|
||||
{
|
||||
m_deferredStructures.Add(structure);
|
||||
}
|
||||
|
||||
public void EndStructure()
|
||||
{
|
||||
m_depth--;
|
||||
// 14.3.12.3 - Algorithm for Deferral of Referents
|
||||
// Representations of (embedded) pointer referents are ordered according to a left-to-right, depth-first traversal of the embedding construction.
|
||||
// referent representations for the embedded construction are further deferred to a position in the octet stream that
|
||||
// follows the representation of the embedding construction. The set of referent representations for the embedded construction
|
||||
// is inserted among the referent representations for any pointers in the embedding construction, according to the order of elements or
|
||||
// members in the embedding construction
|
||||
if (m_depth == 0)
|
||||
{
|
||||
// Make a copy of all the deferred structures, additional deferred structures will be inserted to m_deferredStructures
|
||||
// as we process the existing list
|
||||
List<INDRStructure> deferredStructures = new List<INDRStructure>(m_deferredStructures);
|
||||
m_deferredStructures.Clear();
|
||||
// Write all deferred types:
|
||||
foreach (INDRStructure deferredStructure in deferredStructures)
|
||||
{
|
||||
deferredStructure.Write(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void WriteUnicodeString(string value)
|
||||
{
|
||||
NDRUnicodeString unicodeString = new NDRUnicodeString(value);
|
||||
unicodeString.Write(this);
|
||||
}
|
||||
|
||||
public void WriteStructure(INDRStructure structure)
|
||||
{
|
||||
structure.Write(this);
|
||||
}
|
||||
|
||||
public void WriteTopLevelUnicodeStringPointer(string value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
WriteUInt32(0);
|
||||
return;
|
||||
}
|
||||
|
||||
// Note: We do not bother searching for existing values
|
||||
uint referentID = GetNextReferentID();
|
||||
WriteUInt32(referentID);
|
||||
NDRUnicodeString unicodeString = new NDRUnicodeString(value);
|
||||
unicodeString.Write(this);
|
||||
m_referentToInstance.Add(referentID, unicodeString);
|
||||
}
|
||||
|
||||
// 14.3.12.1 Embedded Full Pointers
|
||||
public void WriteEmbeddedStructureFullPointer(INDRStructure structure)
|
||||
{
|
||||
if (structure == null)
|
||||
{
|
||||
WriteUInt32(0); // null
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Note: We do not bother searching for existing values
|
||||
uint referentID = GetNextReferentID();
|
||||
WriteUInt32(referentID);
|
||||
AddDeferredStructure(structure);
|
||||
m_referentToInstance.Add(referentID, structure);
|
||||
}
|
||||
}
|
||||
|
||||
// 14.2.2 - Alignment of Primitive Types
|
||||
public void WriteUInt16(ushort value)
|
||||
{
|
||||
uint padding = (uint)(2 - (m_stream.Position % 2)) % 2;
|
||||
m_stream.Position += padding;
|
||||
LittleEndianWriter.WriteUInt16(m_stream, value);
|
||||
}
|
||||
|
||||
// 14.2.2 - Alignment of Primitive Types
|
||||
public void WriteUInt32(uint value)
|
||||
{
|
||||
uint padding = (uint)(4 - (m_stream.Position % 4)) % 4;
|
||||
m_stream.Position += padding;
|
||||
LittleEndianWriter.WriteUInt32(m_stream, value);
|
||||
}
|
||||
|
||||
public byte[] GetBytes()
|
||||
{
|
||||
byte[] buffer = new byte[m_stream.Length];
|
||||
m_stream.Seek(0, SeekOrigin.Begin);
|
||||
m_stream.Read(buffer, 0, buffer.Length);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
private uint GetNextReferentID()
|
||||
{
|
||||
uint result = m_nextReferentID;
|
||||
m_nextReferentID++;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
68
SMBLibrary/RPC/PDU/BindAckPDU.cs
Normal file
68
SMBLibrary/RPC/PDU/BindAckPDU.cs
Normal file
|
@ -0,0 +1,68 @@
|
|||
/* Copyright (C) 2014 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 System.Text;
|
||||
using Utilities;
|
||||
|
||||
namespace SMBLibrary.RPC
|
||||
{
|
||||
/// <summary>
|
||||
/// rpcconn_bind_ack_hdr_t
|
||||
/// </summary>
|
||||
public class BindAckPDU : RPCPDU
|
||||
{
|
||||
public ushort MaxTransmitFragmentSize; // max_xmit_frag
|
||||
public ushort MaxReceiveFragmentSize; // max_recv_frag
|
||||
public uint AssociationGroupID; // assoc_group_id
|
||||
public string SecondaryAddress; // sec_addr (port_any_t)
|
||||
// Padding (alignment to 4 byte boundary)
|
||||
public ResultList ResultList; // p_result_list
|
||||
public byte[] AuthVerifier;
|
||||
|
||||
public BindAckPDU() : base()
|
||||
{
|
||||
PacketType = PacketTypeName.BindAck;
|
||||
SecondaryAddress = String.Empty;
|
||||
ResultList = new ResultList();
|
||||
AuthVerifier = new byte[0];
|
||||
}
|
||||
|
||||
public BindAckPDU(byte[] buffer) : base(buffer)
|
||||
{
|
||||
int offset = RPCPDU.CommonFieldsLength;
|
||||
MaxTransmitFragmentSize = LittleEndianReader.ReadUInt16(buffer, ref offset);
|
||||
MaxReceiveFragmentSize = LittleEndianReader.ReadUInt16(buffer, ref offset);
|
||||
AssociationGroupID = LittleEndianReader.ReadUInt32(buffer, ref offset);
|
||||
SecondaryAddress = RPCHelper.ReadPortAddress(buffer, ref offset);
|
||||
int padding = (4 - (offset % 4)) % 4;
|
||||
offset += padding;
|
||||
ResultList = new ResultList(buffer, offset);
|
||||
offset += ResultList.Length;
|
||||
AuthVerifier = ByteReader.ReadBytes(buffer, offset, AuthLength);
|
||||
}
|
||||
|
||||
public override byte[] GetBytes()
|
||||
{
|
||||
AuthLength = (ushort)AuthVerifier.Length;
|
||||
int padding = (4 - ((SecondaryAddress.Length + 3) % 4)) % 4;
|
||||
FragmentLength = (ushort)(RPCPDU.CommonFieldsLength + 8 + SecondaryAddress.Length + 3 + padding + ResultList.Length + AuthLength);
|
||||
byte[] buffer = new byte[FragmentLength];
|
||||
WriteCommonFieldsBytes(buffer);
|
||||
int offset = RPCPDU.CommonFieldsLength;
|
||||
LittleEndianWriter.WriteUInt16(buffer, ref offset, MaxTransmitFragmentSize);
|
||||
LittleEndianWriter.WriteUInt16(buffer, ref offset, MaxReceiveFragmentSize);
|
||||
LittleEndianWriter.WriteUInt32(buffer, ref offset, AssociationGroupID);
|
||||
RPCHelper.WritePortAddress(buffer, ref offset, SecondaryAddress);
|
||||
offset += padding;
|
||||
ResultList.WriteBytes(buffer, ref offset);
|
||||
ByteWriter.WriteBytes(buffer, offset, AuthVerifier);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
}
|
60
SMBLibrary/RPC/PDU/BindPDU.cs
Normal file
60
SMBLibrary/RPC/PDU/BindPDU.cs
Normal file
|
@ -0,0 +1,60 @@
|
|||
/* Copyright (C) 2014 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 System.Text;
|
||||
using Utilities;
|
||||
|
||||
namespace SMBLibrary.RPC
|
||||
{
|
||||
/// <summary>
|
||||
/// rpcconn_bind_hdr_t
|
||||
/// </summary>
|
||||
public class BindPDU : RPCPDU
|
||||
{
|
||||
public ushort MaxTransmitFragmentSize; // max_xmit_frag
|
||||
public ushort MaxReceiveFragmentSize; // max_recv_frag
|
||||
public uint AssociationGroupID; // assoc_group_id
|
||||
public ContextList ContextList;
|
||||
public byte[] AuthVerifier;
|
||||
|
||||
public BindPDU() : base()
|
||||
{
|
||||
PacketType = PacketTypeName.Bind;
|
||||
ContextList = new ContextList();
|
||||
AuthVerifier = new byte[0];
|
||||
}
|
||||
|
||||
public BindPDU(byte[] buffer) : base(buffer)
|
||||
{
|
||||
int offset = RPCPDU.CommonFieldsLength;
|
||||
MaxTransmitFragmentSize = LittleEndianReader.ReadUInt16(buffer, ref offset);
|
||||
MaxReceiveFragmentSize = LittleEndianReader.ReadUInt16(buffer, ref offset);
|
||||
AssociationGroupID = LittleEndianReader.ReadUInt32(buffer, ref offset);
|
||||
ContextList = new ContextList(buffer, offset);
|
||||
offset += ContextList.Length;
|
||||
AuthVerifier = ByteReader.ReadBytes(buffer, offset, AuthLength);
|
||||
}
|
||||
|
||||
public override byte[] GetBytes()
|
||||
{
|
||||
AuthLength =(ushort)AuthVerifier.Length;
|
||||
FragmentLength = (ushort)(RPCPDU.CommonFieldsLength + 8 + ContextList.Length + AuthLength);
|
||||
byte[] buffer = new byte[FragmentLength];
|
||||
WriteCommonFieldsBytes(buffer);
|
||||
int offset = RPCPDU.CommonFieldsLength;
|
||||
LittleEndianWriter.WriteUInt16(buffer, ref offset, MaxTransmitFragmentSize);
|
||||
LittleEndianWriter.WriteUInt16(buffer, ref offset, MaxReceiveFragmentSize);
|
||||
LittleEndianWriter.WriteUInt32(buffer, ref offset, AssociationGroupID);
|
||||
ContextList.WriteBytes(buffer, ref offset);
|
||||
ByteWriter.WriteBytes(buffer, offset, AuthVerifier);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
66
SMBLibrary/RPC/PDU/FaultPDU.cs
Normal file
66
SMBLibrary/RPC/PDU/FaultPDU.cs
Normal file
|
@ -0,0 +1,66 @@
|
|||
/* Copyright (C) 2014 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 System.Text;
|
||||
using Utilities;
|
||||
|
||||
namespace SMBLibrary.RPC
|
||||
{
|
||||
/// <summary>
|
||||
/// rpcconn_fault_hdr_t
|
||||
/// </summary>
|
||||
public class FaultPDU : RPCPDU
|
||||
{
|
||||
public uint AllocationHint;
|
||||
public ushort ContextID;
|
||||
public byte CancelCount;
|
||||
public byte Reserved;
|
||||
public uint Status;
|
||||
public uint Reserved2;
|
||||
public byte[] Data;
|
||||
public byte[] AuthVerifier;
|
||||
|
||||
public FaultPDU() : base()
|
||||
{
|
||||
PacketType = PacketTypeName.Fault;
|
||||
AuthVerifier = new byte[0];
|
||||
}
|
||||
|
||||
public FaultPDU(byte[] buffer) : base(buffer)
|
||||
{
|
||||
int offset = RPCPDU.CommonFieldsLength;
|
||||
AllocationHint = LittleEndianReader.ReadUInt32(buffer, ref offset);
|
||||
ContextID = LittleEndianReader.ReadUInt16(buffer, ref offset);
|
||||
CancelCount = ByteReader.ReadByte(buffer, ref offset);
|
||||
Reserved = ByteReader.ReadByte(buffer, ref offset);
|
||||
Status = LittleEndianReader.ReadUInt32(buffer, ref offset);
|
||||
Reserved2 = LittleEndianReader.ReadUInt32(buffer, ref offset);
|
||||
int dataLength = FragmentLength - AuthLength - offset;
|
||||
Data = ByteReader.ReadBytes(buffer, ref offset, dataLength);
|
||||
AuthVerifier = ByteReader.ReadBytes(buffer, offset, AuthLength);
|
||||
}
|
||||
|
||||
public override byte[] GetBytes()
|
||||
{
|
||||
AuthLength = (ushort)AuthVerifier.Length;
|
||||
FragmentLength = (ushort)(RPCPDU.CommonFieldsLength + 16 + Data.Length + AuthVerifier.Length);
|
||||
byte[] buffer = new byte[FragmentLength];
|
||||
WriteCommonFieldsBytes(buffer);
|
||||
int offset = RPCPDU.CommonFieldsLength;
|
||||
LittleEndianWriter.WriteUInt32(buffer, ref offset, AllocationHint);
|
||||
LittleEndianWriter.WriteUInt16(buffer, ref offset, ContextID);
|
||||
ByteWriter.WriteByte(buffer, ref offset, CancelCount);
|
||||
ByteWriter.WriteByte(buffer, ref offset, Reserved);
|
||||
LittleEndianWriter.WriteUInt32(buffer, ref offset, Status);
|
||||
LittleEndianWriter.WriteUInt32(buffer, ref offset, Reserved2);
|
||||
ByteWriter.WriteBytes(buffer, ref offset, Data);
|
||||
ByteWriter.WriteBytes(buffer, ref offset, AuthVerifier);
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
}
|
83
SMBLibrary/RPC/PDU/RPCPDU.cs
Normal file
83
SMBLibrary/RPC/PDU/RPCPDU.cs
Normal file
|
@ -0,0 +1,83 @@
|
|||
/* Copyright (C) 2014 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 System.Text;
|
||||
using Utilities;
|
||||
|
||||
namespace SMBLibrary.RPC
|
||||
{
|
||||
/// <summary>
|
||||
/// See DCE 1.1: Remote Procedure Call, Chapter 12.6 - Connection-oriented RPC PDUs
|
||||
/// </summary>
|
||||
public abstract class RPCPDU
|
||||
{
|
||||
public const int CommonFieldsLength = 16;
|
||||
|
||||
// The common header fields, which appear in all (connection oriented) PDU types:
|
||||
public byte VersionMajor; // rpc_vers
|
||||
public byte VersionMinor; // rpc_vers_minor
|
||||
public PacketTypeName PacketType;
|
||||
public PacketFlags Flags;
|
||||
public DataRepresentationFormat DataRepresentation;
|
||||
public ushort FragmentLength;
|
||||
public ushort AuthLength;
|
||||
public uint CallID;
|
||||
|
||||
public RPCPDU()
|
||||
{
|
||||
VersionMajor = 5;
|
||||
VersionMinor = 0;
|
||||
}
|
||||
|
||||
public RPCPDU(byte[] buffer)
|
||||
{
|
||||
VersionMajor = ByteReader.ReadByte(buffer, 0);
|
||||
VersionMinor = ByteReader.ReadByte(buffer, 1);
|
||||
PacketType = (PacketTypeName)ByteReader.ReadByte(buffer, 2);
|
||||
Flags = (PacketFlags)ByteReader.ReadByte(buffer, 3);
|
||||
DataRepresentation = new DataRepresentationFormat(buffer, 4);
|
||||
FragmentLength = LittleEndianConverter.ToUInt16(buffer, 8);
|
||||
AuthLength = LittleEndianConverter.ToUInt16(buffer, 10);
|
||||
CallID = LittleEndianConverter.ToUInt32(buffer, 12);
|
||||
}
|
||||
|
||||
public abstract byte[] GetBytes();
|
||||
|
||||
public void WriteCommonFieldsBytes(byte[] buffer)
|
||||
{
|
||||
ByteWriter.WriteByte(buffer, 0, VersionMajor);
|
||||
ByteWriter.WriteByte(buffer, 1, VersionMinor);
|
||||
ByteWriter.WriteByte(buffer, 2, (byte)PacketType);
|
||||
ByteWriter.WriteByte(buffer, 3, (byte)Flags);
|
||||
DataRepresentation.WriteBytes(buffer, 4);
|
||||
LittleEndianWriter.WriteUInt16(buffer, 8, FragmentLength);
|
||||
LittleEndianWriter.WriteUInt16(buffer, 10, AuthLength);
|
||||
LittleEndianWriter.WriteUInt32(buffer, 12, CallID);
|
||||
}
|
||||
|
||||
public static RPCPDU GetPDU(byte[] buffer)
|
||||
{
|
||||
PacketTypeName packetType = (PacketTypeName)ByteReader.ReadByte(buffer, 2);
|
||||
switch (packetType)
|
||||
{
|
||||
case PacketTypeName.Request:
|
||||
return new RequestPDU(buffer);
|
||||
case PacketTypeName.Response:
|
||||
return new ResponsePDU(buffer);
|
||||
case PacketTypeName.Fault:
|
||||
return new FaultPDU(buffer);
|
||||
case PacketTypeName.Bind:
|
||||
return new BindPDU(buffer);
|
||||
case PacketTypeName.BindAck:
|
||||
return new BindAckPDU(buffer);
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
72
SMBLibrary/RPC/PDU/RequestPDU.cs
Normal file
72
SMBLibrary/RPC/PDU/RequestPDU.cs
Normal file
|
@ -0,0 +1,72 @@
|
|||
/* Copyright (C) 2014 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 System.Text;
|
||||
using Utilities;
|
||||
|
||||
namespace SMBLibrary.RPC
|
||||
{
|
||||
/// <summary>
|
||||
/// rpcconn_request_hdr_t
|
||||
/// </summary>
|
||||
public class RequestPDU : RPCPDU
|
||||
{
|
||||
public uint AllocationHint; // alloc_hint
|
||||
public ushort ContextID;
|
||||
public ushort OpNum;
|
||||
public Guid ObjectGuid; // Optional field
|
||||
public byte[] Data;
|
||||
public byte[] AuthVerifier;
|
||||
|
||||
public RequestPDU() : base()
|
||||
{
|
||||
PacketType = PacketTypeName.Request;
|
||||
AuthVerifier = new byte[0];
|
||||
}
|
||||
|
||||
public RequestPDU(byte[] buffer) : base(buffer)
|
||||
{
|
||||
int offset = RPCPDU.CommonFieldsLength;
|
||||
AllocationHint = LittleEndianReader.ReadUInt32(buffer, ref offset);
|
||||
ContextID = LittleEndianReader.ReadUInt16(buffer, ref offset);
|
||||
OpNum = LittleEndianReader.ReadUInt16(buffer, ref offset);
|
||||
if ((Flags & PacketFlags.ObjectUUID) > 0)
|
||||
{
|
||||
ObjectGuid = LittleEndianReader.ReadGuid(buffer, ref offset);
|
||||
}
|
||||
int dataLength = FragmentLength - AuthLength - offset;
|
||||
Data = ByteReader.ReadBytes(buffer, ref offset, dataLength);
|
||||
AuthVerifier = ByteReader.ReadBytes(buffer, offset, AuthLength);
|
||||
}
|
||||
|
||||
public override byte[] GetBytes()
|
||||
{
|
||||
AuthLength = (ushort)AuthVerifier.Length;
|
||||
FragmentLength = (ushort)(RPCPDU.CommonFieldsLength + 8 + Data.Length + AuthVerifier.Length);
|
||||
if ((Flags & PacketFlags.ObjectUUID) > 0)
|
||||
{
|
||||
FragmentLength += 16;
|
||||
}
|
||||
byte[] buffer = new byte[FragmentLength];
|
||||
WriteCommonFieldsBytes(buffer);
|
||||
int offset = RPCPDU.CommonFieldsLength;
|
||||
LittleEndianWriter.WriteUInt32(buffer, ref offset, AllocationHint);
|
||||
LittleEndianWriter.WriteUInt16(buffer, ref offset, ContextID);
|
||||
LittleEndianWriter.WriteUInt16(buffer, ref offset, OpNum);
|
||||
if ((Flags & PacketFlags.ObjectUUID) > 0)
|
||||
{
|
||||
LittleEndianWriter.WriteGuidBytes(buffer, ref offset, ObjectGuid);
|
||||
}
|
||||
ByteWriter.WriteBytes(buffer, ref offset, Data);
|
||||
ByteWriter.WriteBytes(buffer, ref offset, AuthVerifier);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
62
SMBLibrary/RPC/PDU/ResponsePDU.cs
Normal file
62
SMBLibrary/RPC/PDU/ResponsePDU.cs
Normal file
|
@ -0,0 +1,62 @@
|
|||
/* Copyright (C) 2014 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 System.Text;
|
||||
using Utilities;
|
||||
|
||||
namespace SMBLibrary.RPC
|
||||
{
|
||||
/// <summary>
|
||||
/// rpcconn_response_hdr_t
|
||||
/// </summary>
|
||||
public class ResponsePDU : RPCPDU
|
||||
{
|
||||
private uint AllocationHint;
|
||||
public ushort ContextID;
|
||||
public byte CancelCount;
|
||||
public byte Reserved;
|
||||
public byte[] Data;
|
||||
public byte[] AuthVerifier;
|
||||
|
||||
public ResponsePDU() : base()
|
||||
{
|
||||
PacketType = PacketTypeName.Response;
|
||||
AuthVerifier = new byte[0];
|
||||
}
|
||||
|
||||
public ResponsePDU(byte[] buffer) : base(buffer)
|
||||
{
|
||||
int offset = RPCPDU.CommonFieldsLength;
|
||||
AllocationHint = LittleEndianReader.ReadUInt32(buffer, ref offset);
|
||||
ContextID = LittleEndianReader.ReadUInt16(buffer, ref offset);
|
||||
CancelCount = ByteReader.ReadByte(buffer, ref offset);
|
||||
Reserved = ByteReader.ReadByte(buffer, ref offset);
|
||||
int dataLength = FragmentLength - AuthLength - offset;
|
||||
Data = ByteReader.ReadBytes(buffer, ref offset, dataLength);
|
||||
AuthVerifier = ByteReader.ReadBytes(buffer, offset, AuthLength);
|
||||
}
|
||||
|
||||
public override byte[] GetBytes()
|
||||
{
|
||||
AuthLength = (ushort)AuthVerifier.Length;
|
||||
FragmentLength = (ushort)(RPCPDU.CommonFieldsLength + 8 + Data.Length + AuthVerifier.Length);
|
||||
AllocationHint = (ushort)Data.Length;
|
||||
|
||||
byte[] buffer = new byte[FragmentLength];
|
||||
WriteCommonFieldsBytes(buffer);
|
||||
int offset = RPCPDU.CommonFieldsLength;
|
||||
LittleEndianWriter.WriteUInt32(buffer, ref offset, AllocationHint);
|
||||
LittleEndianWriter.WriteUInt16(buffer, ref offset, ContextID);
|
||||
ByteWriter.WriteByte(buffer, ref offset, CancelCount);
|
||||
ByteWriter.WriteByte(buffer, ref offset, Reserved);
|
||||
ByteWriter.WriteBytes(buffer, ref offset, Data);
|
||||
ByteWriter.WriteBytes(buffer, ref offset, AuthVerifier);
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
}
|
46
SMBLibrary/RPC/RPCHelper.cs
Normal file
46
SMBLibrary/RPC/RPCHelper.cs
Normal file
|
@ -0,0 +1,46 @@
|
|||
/* Copyright (C) 2014 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 System.Text;
|
||||
using Utilities;
|
||||
|
||||
namespace SMBLibrary.RPC
|
||||
{
|
||||
public class RPCHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Read port_any_t string structure
|
||||
/// </summary>
|
||||
public static string ReadPortAddress(byte[] buffer, int offset)
|
||||
{
|
||||
ushort length = LittleEndianConverter.ToUInt16(buffer, offset + 0);
|
||||
// The length includes the C NULL string termination
|
||||
return ByteReader.ReadAnsiString(buffer, offset + 2, length - 1);
|
||||
}
|
||||
|
||||
public static string ReadPortAddress(byte[] buffer, ref int offset)
|
||||
{
|
||||
string result = ReadPortAddress(buffer, offset);
|
||||
offset += result.Length + 3;
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void WritePortAddress(byte[] buffer, int offset, string value)
|
||||
{
|
||||
ushort length = (ushort)(value.Length + 1);
|
||||
LittleEndianWriter.WriteUInt16(buffer, offset + 0, length);
|
||||
ByteWriter.WriteNullTerminatedAnsiString(buffer, offset + 2, value);
|
||||
}
|
||||
|
||||
public static void WritePortAddress(byte[] buffer, ref int offset, string value)
|
||||
{
|
||||
WritePortAddress(buffer, offset, value);
|
||||
offset += value.Length + 3;
|
||||
}
|
||||
}
|
||||
}
|
65
SMBLibrary/RPC/Structures/ContextElement.cs
Normal file
65
SMBLibrary/RPC/Structures/ContextElement.cs
Normal file
|
@ -0,0 +1,65 @@
|
|||
/* Copyright (C) 2014 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 System.Text;
|
||||
using Utilities;
|
||||
|
||||
namespace SMBLibrary.RPC
|
||||
{
|
||||
/// <summary>
|
||||
/// p_cont_elem_t
|
||||
/// </summary>
|
||||
public class ContextElement // Presentation Context Element
|
||||
{
|
||||
public ushort ContextID;
|
||||
//byte NumberOfTransferSyntaxItems;
|
||||
public byte Reserved;
|
||||
public SyntaxID AbstractSyntax;
|
||||
public List<SyntaxID> TransferSyntaxList = new List<SyntaxID>();
|
||||
|
||||
public ContextElement(byte[] buffer, int offset)
|
||||
{
|
||||
ContextID = LittleEndianConverter.ToUInt16(buffer, offset + 0);
|
||||
byte numberOfTransferSyntaxItems = ByteReader.ReadByte(buffer, offset + 2);
|
||||
Reserved = ByteReader.ReadByte(buffer, offset + 3);
|
||||
AbstractSyntax = new SyntaxID(buffer, offset + 4);
|
||||
offset += 4 + SyntaxID.Length;
|
||||
for (int index = 0; index < numberOfTransferSyntaxItems; index++)
|
||||
{
|
||||
SyntaxID syntax = new SyntaxID(buffer, offset);
|
||||
TransferSyntaxList.Add(syntax);
|
||||
offset += SyntaxID.Length;
|
||||
}
|
||||
}
|
||||
|
||||
public void WriteBytes(byte[] buffer, int offset)
|
||||
{
|
||||
byte numberOfTransferSyntaxItems = (byte)TransferSyntaxList.Count;
|
||||
|
||||
LittleEndianWriter.WriteUInt16(buffer, offset + 0, ContextID);
|
||||
ByteWriter.WriteByte(buffer, offset + 2, numberOfTransferSyntaxItems);
|
||||
ByteWriter.WriteByte(buffer, offset + 3, Reserved);
|
||||
AbstractSyntax.WriteBytes(buffer, offset + 4);
|
||||
offset += 4 + SyntaxID.Length;
|
||||
|
||||
for (int index = 0; index < numberOfTransferSyntaxItems; index++)
|
||||
{
|
||||
TransferSyntaxList[index].WriteBytes(buffer, offset);
|
||||
offset += SyntaxID.Length;
|
||||
}
|
||||
}
|
||||
|
||||
public int Length
|
||||
{
|
||||
get
|
||||
{
|
||||
return 4 + SyntaxID.Length * (TransferSyntaxList.Count + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
76
SMBLibrary/RPC/Structures/ContextList.cs
Normal file
76
SMBLibrary/RPC/Structures/ContextList.cs
Normal file
|
@ -0,0 +1,76 @@
|
|||
/* Copyright (C) 2014 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 System.Text;
|
||||
using Utilities;
|
||||
|
||||
namespace SMBLibrary.RPC
|
||||
{
|
||||
/// <summary>
|
||||
/// p_cont_list_t
|
||||
/// Presentation Context List
|
||||
/// </summary>
|
||||
public class ContextList : List<ContextElement>
|
||||
{
|
||||
//byte NumberOfContextElements;
|
||||
public byte Reserved1;
|
||||
public ushort Reserved2;
|
||||
|
||||
public ContextList() : base()
|
||||
{
|
||||
}
|
||||
|
||||
public ContextList(byte[] buffer, int offset) : base()
|
||||
{
|
||||
byte numberOfContextElements = ByteReader.ReadByte(buffer, offset + 0);
|
||||
Reserved1 = ByteReader.ReadByte(buffer, offset + 1);
|
||||
Reserved2 = LittleEndianConverter.ToUInt16(buffer, offset + 2);
|
||||
offset += 4;
|
||||
for (int index = 0; index < numberOfContextElements; index++)
|
||||
{
|
||||
ContextElement element = new ContextElement(buffer, offset);
|
||||
this.Add(element);
|
||||
offset += element.Length;
|
||||
}
|
||||
}
|
||||
|
||||
public void WriteBytes(byte[] buffer, int offset)
|
||||
{
|
||||
byte numberOfContextElements = (byte)this.Count;
|
||||
|
||||
ByteWriter.WriteByte(buffer, offset + 0, numberOfContextElements);
|
||||
ByteWriter.WriteByte(buffer, offset + 1, Reserved1);
|
||||
LittleEndianWriter.WriteUInt16(buffer, offset + 2, Reserved2);
|
||||
offset += 4;
|
||||
for (int index = 0; index < numberOfContextElements; index++)
|
||||
{
|
||||
this[index].WriteBytes(buffer, offset);
|
||||
offset += this[index].Length;
|
||||
}
|
||||
}
|
||||
|
||||
public void WriteBytes(byte[] buffer, ref int offset)
|
||||
{
|
||||
WriteBytes(buffer, offset);
|
||||
offset += this.Length;
|
||||
}
|
||||
|
||||
public int Length
|
||||
{
|
||||
get
|
||||
{
|
||||
int length = 4;
|
||||
for (int index = 0; index < this.Count; index++)
|
||||
{
|
||||
length += this[index].Length;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
39
SMBLibrary/RPC/Structures/ResultElement.cs
Normal file
39
SMBLibrary/RPC/Structures/ResultElement.cs
Normal file
|
@ -0,0 +1,39 @@
|
|||
/* Copyright (C) 2014 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 System.Text;
|
||||
using Utilities;
|
||||
|
||||
namespace SMBLibrary.RPC
|
||||
{
|
||||
/// <summary>
|
||||
/// p_result_t
|
||||
/// </summary>
|
||||
public struct ResultElement
|
||||
{
|
||||
public const int Length = 24;
|
||||
|
||||
public NegotiationResult Result;
|
||||
public RejectionReason Reason;
|
||||
public SyntaxID TransferSyntax;
|
||||
|
||||
public ResultElement(byte[] buffer, int offset)
|
||||
{
|
||||
Result = (NegotiationResult)LittleEndianConverter.ToUInt16(buffer, offset + 0);
|
||||
Reason = (RejectionReason)LittleEndianConverter.ToUInt16(buffer, offset + 2);
|
||||
TransferSyntax = new SyntaxID(buffer, offset + 4);
|
||||
}
|
||||
|
||||
public void WriteBytes(byte[] buffer, int offset)
|
||||
{
|
||||
LittleEndianWriter.WriteUInt16(buffer, offset + 0, (ushort)Result);
|
||||
LittleEndianWriter.WriteUInt16(buffer, offset + 2, (ushort)Reason);
|
||||
TransferSyntax.WriteBytes(buffer, offset + 4);
|
||||
}
|
||||
}
|
||||
}
|
69
SMBLibrary/RPC/Structures/ResultList.cs
Normal file
69
SMBLibrary/RPC/Structures/ResultList.cs
Normal file
|
@ -0,0 +1,69 @@
|
|||
/* Copyright (C) 2014 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 System.Text;
|
||||
using Utilities;
|
||||
|
||||
namespace SMBLibrary.RPC
|
||||
{
|
||||
/// <summary>
|
||||
/// p_result_list_t
|
||||
/// </summary>
|
||||
public class ResultList : List<ResultElement>
|
||||
{
|
||||
//byte NumberOfResults;
|
||||
public byte Reserved;
|
||||
public ushort Reserved2;
|
||||
|
||||
public ResultList() : base()
|
||||
{}
|
||||
|
||||
public ResultList(byte[] buffer, int offset) : base()
|
||||
{
|
||||
byte numberOfResults = ByteReader.ReadByte(buffer, offset + 0);
|
||||
Reserved = ByteReader.ReadByte(buffer, offset + 1);
|
||||
Reserved2 = LittleEndianConverter.ToUInt16(buffer, offset + 2);
|
||||
offset += 4;
|
||||
for (int index = 0; index < numberOfResults; index++)
|
||||
{
|
||||
ResultElement element = new ResultElement(buffer, offset);
|
||||
this.Add(element);
|
||||
offset += ResultElement.Length;
|
||||
}
|
||||
}
|
||||
|
||||
public void WriteBytes(byte[] buffer, int offset)
|
||||
{
|
||||
byte numberOfResults = (byte)this.Count;
|
||||
|
||||
ByteWriter.WriteByte(buffer, offset + 0, numberOfResults);
|
||||
ByteWriter.WriteByte(buffer, offset + 1, Reserved);
|
||||
LittleEndianWriter.WriteUInt16(buffer, offset + 2, Reserved2);
|
||||
offset += 4;
|
||||
for (int index = 0; index < numberOfResults; index++)
|
||||
{
|
||||
this[index].WriteBytes(buffer, offset);
|
||||
offset += ResultElement.Length;
|
||||
}
|
||||
}
|
||||
|
||||
public void WriteBytes(byte[] buffer, ref int offset)
|
||||
{
|
||||
WriteBytes(buffer, offset);
|
||||
offset += this.Length;
|
||||
}
|
||||
|
||||
public int Length
|
||||
{
|
||||
get
|
||||
{
|
||||
return 4 + ResultElement.Length * this.Count;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
56
SMBLibrary/RPC/Structures/SyntaxID.cs
Normal file
56
SMBLibrary/RPC/Structures/SyntaxID.cs
Normal file
|
@ -0,0 +1,56 @@
|
|||
/* Copyright (C) 2014 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 System.Text;
|
||||
using Utilities;
|
||||
|
||||
namespace SMBLibrary.RPC
|
||||
{
|
||||
/// <summary>
|
||||
/// p_syntax_id_t
|
||||
/// </summary>
|
||||
public struct SyntaxID
|
||||
{
|
||||
public const int Length = 20;
|
||||
|
||||
public Guid InterfaceUUID; // if_uuid
|
||||
public uint InterfaceVersion; // if_version
|
||||
|
||||
public SyntaxID(Guid interfaceUUID, uint interfaceVersion)
|
||||
{
|
||||
InterfaceUUID = interfaceUUID;
|
||||
InterfaceVersion = interfaceVersion;
|
||||
}
|
||||
|
||||
public SyntaxID(byte[] buffer, int offset)
|
||||
{
|
||||
InterfaceUUID = LittleEndianConverter.ToGuid(buffer, offset + 0);
|
||||
InterfaceVersion = LittleEndianConverter.ToUInt32(buffer, offset + 16);
|
||||
}
|
||||
|
||||
public void WriteBytes(byte[] buffer, int offset)
|
||||
{
|
||||
LittleEndianWriter.WriteGuidBytes(buffer, offset + 0, InterfaceUUID);
|
||||
LittleEndianWriter.WriteUInt32(buffer, offset + 16, InterfaceVersion);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj is SyntaxID)
|
||||
{
|
||||
return this.InterfaceUUID.Equals(((SyntaxID)obj).InterfaceUUID) && this.InterfaceVersion.Equals(((SyntaxID)obj).InterfaceVersion);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return InterfaceUUID.GetHashCode() * InterfaceVersion.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
43
SMBLibrary/Readme.txt
Normal file
43
SMBLibrary/Readme.txt
Normal file
|
@ -0,0 +1,43 @@
|
|||
About SMBLibrary:
|
||||
=================
|
||||
SMBLibrary is an open-source C# SMB 1.0/CIFS 1.0 server implementation.
|
||||
SMBLibrary gives .NET developers an easy way to share a directory / file system / virtual file system, with any operating system that supports the SMB protocol.
|
||||
SMBLibrary shares can be accessed from any Windows version since Windows NT 4.0.
|
||||
|
||||
Supported SMB / CIFS transport methods:
|
||||
=======================================
|
||||
NetBIOS over TCP (port 139)
|
||||
Direct TCP hosting (port 445)
|
||||
|
||||
Notes:
|
||||
------
|
||||
1. Windows bind port 139 on a per-adapter basis, while port 445 is bound globally.
|
||||
This means that you can't use direct TCP hosting without disabling Windows File and Printer Sharing server completely.
|
||||
However, NetBIOS over TCP is almost identical, and for this reason, it's recommended to use port 139.
|
||||
|
||||
2. To free port 139 for a given adapter, go to 'Internet Protocol (TCP/IP) Properties' > Advanced > WINS,
|
||||
and select 'Disable NetBIOS over TCP/IP'. in addition you need to uncheck 'File and Printer Sharing for Microsoft Networks'.
|
||||
|
||||
3. It's important to note that disabling NetBIOS over TCP/IP will also disable NetBIOS name service for that adapter (a.k.a. WINS),
|
||||
This service uses UDP port 137. SMBLibrary offers a name service of its own.
|
||||
|
||||
4. You can install a virtual network adapter driver for Windows to be used solely with SMBLibrary:
|
||||
- You can install the 'Microsoft Loopback adapter' and use it for server-only communication with SMBLibrary.
|
||||
- A limited alternative is 'OpenVPN TAP-Windows Adapter' that can be used for client communication with SMBLibrary,
|
||||
However, you will have to configure this adapter to use a separate network segment.
|
||||
The driver installation can be downloaded from: https://openvpn.net/index.php/open-source/downloads.html
|
||||
To get started, go to Adapter properties > 'Advanced' and set 'Media Status' to 'Always Connected'.
|
||||
|
||||
5. The differences between 'Direct TCP hosting' and 'NetBIOS over TCP' are:
|
||||
- A 'session request' packet is initiating the NBT connection.
|
||||
- A 'keep alive' packet is sent from time to time over NBT connections.
|
||||
|
||||
Using SMBLibrary:
|
||||
=================
|
||||
Any directory / filesystem / object you wish to share must implement the IFileSystem interface.
|
||||
You can share anything from actual directories to custom objects, as long as they expose a directory structure.
|
||||
|
||||
Contact:
|
||||
========
|
||||
If you have any question, feel free to contact me.
|
||||
Tal Aloni <tal.aloni.il@gmail.com>
|
14
SMBLibrary/RevisionHistory.txt
Normal file
14
SMBLibrary/RevisionHistory.txt
Normal file
|
@ -0,0 +1,14 @@
|
|||
Revision History:
|
||||
-----------------
|
||||
1.0.0 - Initial release.
|
||||
|
||||
1.0.1 - Better handling of invalid read / write operations.
|
||||
|
||||
1.0.2 - Improved documentation and updated SMB_COM_TRANSACTION2 request (Technical Specifications Errata was found).
|
||||
|
||||
1.0.3 - Search handles (SID) are now properly closed.
|
||||
|
||||
1.0.4 - Added support for IPv6.
|
||||
|
||||
1.0.5 - bugfix: SMB_COM_OPEN_ANDX was not returning the requested response format.
|
||||
File buffering logic logic was moved to a separate class.
|
95
SMBLibrary/SMB1/EnumStructures/NamedPipeStatus.cs
Normal file
95
SMBLibrary/SMB1/EnumStructures/NamedPipeStatus.cs
Normal file
|
@ -0,0 +1,95 @@
|
|||
/* Copyright (C) 2014 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;
|
||||
|
||||
namespace SMBLibrary.SMB1
|
||||
{
|
||||
public enum ReadMode : byte
|
||||
{
|
||||
ByteMode = 0x00,
|
||||
MessageMode = 0x01,
|
||||
}
|
||||
|
||||
public enum NamedPipeType : byte
|
||||
{
|
||||
ByteNamedPipe = 0x00,
|
||||
MessageNodePipe = 0x01,
|
||||
}
|
||||
|
||||
public enum Endpoint : byte
|
||||
{
|
||||
ClientSideEnd = 0x00,
|
||||
ServerSideEnd = 0x01,
|
||||
}
|
||||
|
||||
public enum NonBlocking : byte
|
||||
{
|
||||
Block = 0x00,
|
||||
DoNotBlock = 0x01,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// SMB_NMPIPE_STATUS
|
||||
/// </summary>
|
||||
public struct NamedPipeStatus // ushort
|
||||
{
|
||||
public byte ICount;
|
||||
public ReadMode ReadMode;
|
||||
public NamedPipeType NamedPipeType;
|
||||
public Endpoint Endpoint;
|
||||
public NonBlocking NonBlocking;
|
||||
|
||||
public NamedPipeStatus(byte[] buffer, int offset)
|
||||
{
|
||||
ICount = buffer[offset];
|
||||
ReadMode = (ReadMode)(buffer[offset + 1] & 0x03);
|
||||
NamedPipeType = (NamedPipeType)((buffer[offset + 1] & 0x0C) >> 2);
|
||||
Endpoint = (Endpoint)((buffer[offset + 1] & 0x40) >> 6);
|
||||
NonBlocking = (NonBlocking)((buffer[offset + 1] & 0x80) >> 7);
|
||||
}
|
||||
|
||||
public NamedPipeStatus(ushort value)
|
||||
{
|
||||
ICount = (byte)(value & 0xFF);
|
||||
ReadMode = (ReadMode)((value & 0x0300) >> 8);
|
||||
NamedPipeType = (NamedPipeType)((value & 0x0C00) >> 10);
|
||||
Endpoint = (Endpoint)((value & 0x4000) >> 14);
|
||||
NonBlocking = (NonBlocking)((value & 0x80) >> 15);
|
||||
}
|
||||
|
||||
public void WriteBytes(byte[] buffer, int offset)
|
||||
{
|
||||
buffer[offset + 0] = ICount;
|
||||
buffer[offset + 1] = (byte)((byte)ReadMode & 0x03);
|
||||
buffer[offset + 1] |= (byte)(((byte)NamedPipeType << 2) & 0x0C);
|
||||
buffer[offset + 1] |= (byte)(((byte)Endpoint << 6) & 0x40);
|
||||
buffer[offset + 1] |= (byte)(((byte)NonBlocking << 7) & 0x80);
|
||||
}
|
||||
|
||||
public void WriteBytes(byte[] buffer, ref int offset)
|
||||
{
|
||||
WriteBytes(buffer, offset);
|
||||
offset += 2;
|
||||
}
|
||||
|
||||
public ushort ToUInt16()
|
||||
{
|
||||
ushort result = ICount;
|
||||
result |= (ushort)(((byte)ReadMode << 8) & 0x0300);
|
||||
result |= (ushort)(((byte)NamedPipeType << 10) & 0x0C00);
|
||||
result |= (ushort)(((byte)Endpoint << 14) & 0x4000);
|
||||
result |= (ushort)(((byte)NonBlocking << 15) & 0x8000);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static NamedPipeStatus Read(byte[] buffer, ref int offset)
|
||||
{
|
||||
offset += 2;
|
||||
return new NamedPipeStatus(buffer, offset - 2);
|
||||
}
|
||||
}
|
||||
}
|
50
SMBLibrary/SMB1/EnumStructures/OpenResults.cs
Normal file
50
SMBLibrary/SMB1/EnumStructures/OpenResults.cs
Normal file
|
@ -0,0 +1,50 @@
|
|||
/* Copyright (C) 2014 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 System.Text;
|
||||
using Utilities;
|
||||
|
||||
namespace SMBLibrary.SMB1
|
||||
{
|
||||
public struct OpenResults // 2 bytes
|
||||
{
|
||||
public OpenResult OpenResult;
|
||||
public bool OpLockGranted;
|
||||
|
||||
public OpenResults(byte[] buffer, int offset)
|
||||
{
|
||||
OpenResult = (OpenResult)(buffer[offset] & 0x3);
|
||||
OpLockGranted = (buffer[offset + 1] & 0x80) > 0;
|
||||
}
|
||||
|
||||
public void WriteBytes(byte[] buffer, int offset)
|
||||
{
|
||||
buffer[0] = (byte)OpenResult;
|
||||
if (OpLockGranted)
|
||||
{
|
||||
buffer[1] = 0x80;
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer[1] = 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
public void WriteBytes(byte[] buffer, ref int offset)
|
||||
{
|
||||
WriteBytes(buffer, offset);
|
||||
offset += 2;
|
||||
}
|
||||
|
||||
public static OpenResults Read(byte[] buffer, ref int offset)
|
||||
{
|
||||
offset += 2;
|
||||
return new OpenResults(buffer, offset - 2);
|
||||
}
|
||||
}
|
||||
}
|
40
SMBLibrary/SMB1/Enums/CommandName.cs
Normal file
40
SMBLibrary/SMB1/Enums/CommandName.cs
Normal file
|
@ -0,0 +1,40 @@
|
|||
|
||||
namespace SMBLibrary.SMB1
|
||||
{
|
||||
public enum CommandName : byte
|
||||
{
|
||||
SMB_COM_CREATE_DIRECTORY = 0x00,
|
||||
SMB_COM_DELETE_DIRECTORY = 0x01,
|
||||
SMB_COM_CLOSE = 0x04,
|
||||
SMB_COM_FLUSH = 0x05,
|
||||
SMB_COM_DELETE = 0x06,
|
||||
SMB_COM_RENAME = 0x07,
|
||||
SMB_COM_QUERY_INFORMATION = 0x08,
|
||||
SMB_COM_SET_INFORMATION = 0x09,
|
||||
SMB_COM_READ = 0x0A,
|
||||
SMB_COM_WRITE = 0x0B,
|
||||
SMB_COM_CHECK_DIRECTORY = 0x10,
|
||||
SMB_COM_WRITE_RAW = 0x1D,
|
||||
SMB_COM_WRITE_COMPLETE = 0x20, // Write RAW final response
|
||||
SMB_COM_SET_INFORMATION2 = 0x22,
|
||||
SMB_COM_LOCKING_ANDX = 0x24,
|
||||
SMB_COM_TRANSACTION = 0x25,
|
||||
SMB_COM_TRANSACTION_SECONDARY = 0x26,
|
||||
SMB_COM_ECHO = 0x2B,
|
||||
SMB_COM_OPEN_ANDX = 0x2D,
|
||||
SMB_COM_READ_ANDX = 0x2E,
|
||||
SMB_COM_WRITE_ANDX = 0x2F,
|
||||
SMB_COM_TRANSACTION2 = 0x32,
|
||||
SMB_COM_TRANSACTION2_SECONDARY = 0x33,
|
||||
SMB_COM_FIND_CLOSE2 = 0x34,
|
||||
SMB_COM_TREE_DISCONNECT = 0x71,
|
||||
SMB_COM_NEGOTIATE = 0x72,
|
||||
SMB_COM_SESSION_SETUP_ANDX = 0x73,
|
||||
SMB_COM_LOGOFF_ANDX = 0x74,
|
||||
SMB_COM_TREE_CONNECT_ANDX = 0x75,
|
||||
SMB_COM_NT_TRANSACT = 0xA0,
|
||||
SMB_COM_NT_TRANSACT_SECONDARY = 0xA1,
|
||||
SMB_COM_NT_CREATE_ANDX = 0xA2,
|
||||
SMB_COM_NO_ANDX_COMMAND = 0xFF,
|
||||
}
|
||||
}
|
36
SMBLibrary/SMB1/Enums/ExtendedFileAttributes.cs
Normal file
36
SMBLibrary/SMB1/Enums/ExtendedFileAttributes.cs
Normal file
|
@ -0,0 +1,36 @@
|
|||
using System;
|
||||
|
||||
namespace SMBLibrary.SMB1
|
||||
{
|
||||
/// <summary>
|
||||
/// SMB_EXT_FILE_ATTR
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum ExtendedFileAttributes : uint
|
||||
{
|
||||
Readonly = 0x001, // ATTR_READONLY
|
||||
Hidden = 0x0002, // ATTR_HIDDEN
|
||||
System = 0x0004, // ATTR_SYSTEM
|
||||
Directory = 0x0010, // ATTR_DIRECTORY
|
||||
Archive = 0x0020, // ATTR_ARCHIVE
|
||||
|
||||
/// <summary>
|
||||
/// The file has no other attributes set. This attribute is valid only if used alone.
|
||||
/// </summary>
|
||||
Normal = 0x0080, // ATTR_NORMAL
|
||||
Temporary = 0x0100, // ATTR_TEMPORARY
|
||||
Sparse = 0x0200, // ATTR_SPARSE, SMB 1.0 Addition
|
||||
ReparsePoint = 0x0400, // ATTR_REPARSE_POINT, SMB 1.0 Addition
|
||||
Compressed = 0x0800, // ATTR_COMPRESSED
|
||||
Offline = 0x1000, // ATTR_OFFLINE, SMB 1.0 Addition
|
||||
NotIndexed = 0x2000, // ATTR_NOT_CONTENT_INDEXED, SMB 1.0 Addition
|
||||
Encrypted = 0x4000, // ATTR_ENCRYPTED, SMB 1.0 Addition
|
||||
PosixSemantics = 0x01000000, // POSIX_SEMANTICS
|
||||
BackupSemantics = 0x02000000, // BACKUP_SEMANTICS
|
||||
DeleteOnClose = 0x04000000, // DELETE_ON_CLOSE
|
||||
SequentialScan = 0x08000000, // SEQUENTIAL_SCAN
|
||||
RandomAccess = 0x10000000, // RANDOM_ACCESS
|
||||
NoBuffering = 0x10000000, // NO_BUFFERING
|
||||
WriteThrough = 0x80000000, // WRITE_THROUGH
|
||||
}
|
||||
}
|
24
SMBLibrary/SMB1/Enums/FileAttributes.cs
Normal file
24
SMBLibrary/SMB1/Enums/FileAttributes.cs
Normal file
|
@ -0,0 +1,24 @@
|
|||
using System;
|
||||
|
||||
namespace SMBLibrary.SMB1
|
||||
{
|
||||
/// <summary>
|
||||
/// SMB_FILE_ATTRIBUTES
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum FileAttributes : ushort
|
||||
{
|
||||
Normal = 0x0000, // SMB_FILE_ATTRIBUTE_NORMAL
|
||||
ReadOnly = 0x0001, // SMB_FILE_ATTRIBUTE_READONLY
|
||||
Hidden = 0x0002, // SMB_FILE_ATTRIBUTE_HIDDEN
|
||||
System = 0x0004, // SMB_FILE_ATTRIBUTE_SYSTEM
|
||||
Volume = 0x0008, // SMB_FILE_ATTRIBUTE_VOLUME
|
||||
Directory = 0x0010, // SMB_FILE_ATTRIBUTE_DIRECTORY
|
||||
Archive = 0x0020, // SMB_FILE_ATTRIBUTE_ARCHIVE
|
||||
SearchReadOnly = 0x0100, // SMB_SEARCH_ATTRIBUTE_READONLY
|
||||
SearchHidden = 0x0200, // SMB_SEARCH_ATTRIBUTE_HIDDEN
|
||||
SearchSystem = 0x0400, // SMB_SEARCH_ATTRIBUTE_SYSTEM
|
||||
SearchDirectory = 0x1000, // SMB_SEARCH_ATTRIBUTE_DIRECTORY
|
||||
SearchArchive = 0x2000, // SMB_SEARCH_ATTRIBUTE_ARCHIVE
|
||||
}
|
||||
}
|
14
SMBLibrary/SMB1/Enums/HeaderFlags.cs
Normal file
14
SMBLibrary/SMB1/Enums/HeaderFlags.cs
Normal file
|
@ -0,0 +1,14 @@
|
|||
using System;
|
||||
|
||||
namespace SMBLibrary.SMB1
|
||||
{
|
||||
[Flags]
|
||||
public enum HeaderFlags : byte
|
||||
{
|
||||
LockAndRead = 0x01, // SMB_FLAGS_LOCK_AND_READ_OK
|
||||
CaseInsensitive = 0x08, // SMB_FLAGS_CASE_INSENSITIVE
|
||||
CanonicalizedPaths = 0x10, // SMB_FLAGS_CANONICALIZED_PATHS
|
||||
Oplock = 0x20, // SMB_FLAGS_OPLOCK
|
||||
Reply = 0x80, // SMB_FLAGS_REPLY
|
||||
}
|
||||
}
|
25
SMBLibrary/SMB1/Enums/HeaderFlags2.cs
Normal file
25
SMBLibrary/SMB1/Enums/HeaderFlags2.cs
Normal file
|
@ -0,0 +1,25 @@
|
|||
using System;
|
||||
|
||||
namespace SMBLibrary.SMB1
|
||||
{
|
||||
[Flags]
|
||||
public enum HeaderFlags2 : ushort
|
||||
{
|
||||
LongNamesAllowed = 0x0001, // SMB_FLAGS2_LONG_NAMES
|
||||
ExtendedAttributes = 0x0002, // SMB_FLAGS2_EAS
|
||||
SecuritySignature = 0x0004, // SMB_FLAGS2_SMB_SECURITY_SIGNATURE
|
||||
CompressedData = 0x0008, // SMB_FLAGS2_COMPRESSED
|
||||
SecuritySignatureRequired = 0x0010, // SMB_FLAGS2_SMB_SECURITY_SIGNATURE_REQUIRED
|
||||
LongNameUsed = 0x0040, // SMB_FLAGS2_IS_LONG_NAME
|
||||
ReparsePath = 0x400, // SMB_FLAGS2_REPARSE_PATH
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the client or server supports extended security
|
||||
/// </summary>
|
||||
ExtendedSecurity = 0x0800, // SMB_FLAGS2_EXTENDED_SECURITY
|
||||
DFS = 0x1000, // SMB_FLAGS2_DFS
|
||||
ReadIfExecute = 0x2000, // SMB_FLAGS2_PAGING_IO
|
||||
NTStatusCode = 0x4000, // SMB_FLAGS2_NT_STATUS
|
||||
Unicode = 0x8000, // SMB_FLAGS2_UNICODE
|
||||
}
|
||||
}
|
24
SMBLibrary/SMB1/Enums/Locking/LockType.cs
Normal file
24
SMBLibrary/SMB1/Enums/Locking/LockType.cs
Normal file
|
@ -0,0 +1,24 @@
|
|||
using System;
|
||||
|
||||
namespace SMBLibrary.SMB1
|
||||
{
|
||||
[Flags]
|
||||
public enum LockType : byte
|
||||
{
|
||||
READ_WRITE_LOCK = 0x00,
|
||||
SHARED_LOCK = 0x01,
|
||||
OPLOCK_RELEASE = 0x02,
|
||||
CHANGE_LOCKTYPE = 0x04,
|
||||
|
||||
/// <summary>
|
||||
/// Request to cancel all outstanding lock requests for the specified FID and PID.
|
||||
/// </summary>
|
||||
CANCEL_LOCK = 0x08,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the LOCKING_ANDX_RANGE format is the 64-bit file offset version.
|
||||
/// If this flag is not set, then the LOCKING_ANDX_RANGE format is the 32-bit file offset version
|
||||
/// </summary>
|
||||
LARGE_FILES = 0x10,
|
||||
}
|
||||
}
|
45
SMBLibrary/SMB1/Enums/NTCreate/CreateDisposition.cs
Normal file
45
SMBLibrary/SMB1/Enums/NTCreate/CreateDisposition.cs
Normal file
|
@ -0,0 +1,45 @@
|
|||
|
||||
namespace SMBLibrary.SMB1
|
||||
{
|
||||
public enum CreateDisposition : uint
|
||||
{
|
||||
/// <summary>
|
||||
/// If the file already exists, it SHOULD be superseded (overwritten).
|
||||
/// If it does not already exist, then it SHOULD be created.
|
||||
/// </summary>
|
||||
FILE_SUPERSEDE = 0x0000,
|
||||
|
||||
/// <summary>
|
||||
/// If the file already exists, it SHOULD be opened rather than created.
|
||||
/// If the file does not already exist, the operation MUST fail.
|
||||
/// </summary>
|
||||
FILE_OPEN = 0x0001,
|
||||
|
||||
/// <summary>
|
||||
/// If the file already exists, the operation MUST fail.
|
||||
/// If the file does not already exist, it SHOULD be created.
|
||||
/// </summary>
|
||||
FILE_CREATE = 0x0002,
|
||||
|
||||
/// <summary>
|
||||
/// If the file already exists, it SHOULD be opened.
|
||||
/// If the file does not already exist, then it SHOULD be created.
|
||||
/// This value is equivalent to (FILE_OPEN | FILE_CREATE).
|
||||
/// </summary>
|
||||
FILE_OPEN_IF = 0x0003,
|
||||
|
||||
/// <summary>
|
||||
/// If the file already exists, it SHOULD be opened and truncated.
|
||||
/// If the file does not already exist, the operation MUST fail.
|
||||
/// The client MUST open the file with at least GENERIC_WRITE access for the command to succeed.
|
||||
/// </summary>
|
||||
FILE_OVERWRITE = 0x0004,
|
||||
|
||||
/// <summary>
|
||||
/// If the file already exists, it SHOULD be opened and truncated.
|
||||
/// If the file does not already exist, it SHOULD be created.
|
||||
/// The client MUST open the file with at least GENERIC_WRITE access.
|
||||
/// </summary>
|
||||
FILE_OVERWRITE_IF = 0x0005,
|
||||
}
|
||||
}
|
101
SMBLibrary/SMB1/Enums/NTCreate/CreateOptions.cs
Normal file
101
SMBLibrary/SMB1/Enums/NTCreate/CreateOptions.cs
Normal file
|
@ -0,0 +1,101 @@
|
|||
using System;
|
||||
|
||||
namespace SMBLibrary.SMB1
|
||||
{
|
||||
[Flags]
|
||||
public enum CreateOptions : uint
|
||||
{
|
||||
/// <summary>
|
||||
/// The file being created or opened is a directory file.
|
||||
/// With this option, the CreateDisposition field MUST be set to FILE_CREATE, FILE_OPEN, or FILE_OPEN_IF.
|
||||
/// </summary>
|
||||
FILE_DIRECTORY_FILE = 0x0001,
|
||||
|
||||
/// <summary>
|
||||
/// Applications that write data to the file MUST actually transfer the data into the file before any write request is considered complete.
|
||||
/// If FILE_NO_INTERMEDIATE_BUFFERING is set, the server MUST perform as if FILE_WRITE_THROUGH is set in the create request.
|
||||
/// </summary>
|
||||
FILE_WRITE_THROUGH = 0x0002,
|
||||
|
||||
/// <summary>
|
||||
/// This option indicates that access to the file can be sequential.
|
||||
/// The server can use this information to influence its caching and read-ahead strategy for this file.
|
||||
/// The file MAY in fact be accessed randomly, but the server can optimize its caching and read-ahead policy for sequential access.
|
||||
/// </summary>
|
||||
FILE_SEQUENTIAL_ONLY = 0x0004,
|
||||
|
||||
/// <summary>
|
||||
/// The file SHOULD NOT be cached or buffered in an internal buffer by the server.
|
||||
/// This option is incompatible when the FILE_APPEND_DATA bit field is set in the DesiredAccess field.
|
||||
/// </summary>
|
||||
FILE_NO_INTERMEDIATE_BUFFERING = 0x0008,
|
||||
|
||||
FILE_SYNCHRONOUS_IO_ALERT = 0x0010,
|
||||
|
||||
FILE_SYNCHRONOUS_IO_NONALERT = 0x0020,
|
||||
|
||||
/// <summary>
|
||||
/// If the file being opened is a directory, the server MUST fail the request with STATUS_FILE_IS_A_DIRECTORY
|
||||
/// </summary>
|
||||
FILE_NON_DIRECTORY_FILE = 0x0040,
|
||||
|
||||
FILE_CREATE_TREE_CONNECTION = 0x0080,
|
||||
|
||||
FILE_COMPLETE_IF_OPLOCKED = 0x0100,
|
||||
|
||||
/// <summary>
|
||||
/// The application that initiated the client's request does not support extended attributes (EAs).
|
||||
/// If the EAs on an existing file being opened indicate that the caller SHOULD support EAs to correctly interpret the file, the server SHOULD fail this request with STATUS_ACCESS_DENIED.
|
||||
/// </summary>
|
||||
FILE_NO_EA_KNOWLEDGE = 0x0200,
|
||||
|
||||
FILE_OPEN_FOR_RECOVERY = 0x0400,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that access to the file can be random.
|
||||
/// The server MAY use this information to influence its caching and read-ahead strategy for this file.
|
||||
/// This is a hint to the server that sequential read-ahead operations might not be appropriate on the file.
|
||||
/// </summary>
|
||||
FILE_RANDOM_ACCESS = 0x0800,
|
||||
|
||||
/// <summary>
|
||||
/// The file SHOULD be automatically deleted when the last open request on this file is closed.
|
||||
/// When this option is set, the DesiredAccess field MUST include the DELETE flag.
|
||||
/// This option is often used for temporary files.
|
||||
/// </summary>
|
||||
FILE_DELETE_ON_CLOSE = 0x1000,
|
||||
|
||||
/// <summary>
|
||||
/// Opens a file based on the FileId.
|
||||
/// If this option is set, the server MUST fail the request with STATUS_NOT_SUPPORTED in the Status field of the SMB Header in the server response.
|
||||
/// </summary>
|
||||
FILE_OPEN_BY_FILE_ID = 0x2000,
|
||||
|
||||
/// <summary>
|
||||
/// The file is being opened or created for the purposes of either a backup or a restore operation.
|
||||
/// Thus, the server can make appropriate checks to ensure that the caller is capable of overriding
|
||||
/// whatever security checks have been placed on the file to allow a backup or restore operation to occur.
|
||||
/// The server can check for certain access rights to the file before checking the DesiredAccess field.
|
||||
/// </summary>
|
||||
FILE_OPEN_FOR_BACKUP_INTENT = 0x4000,
|
||||
|
||||
/// <summary>
|
||||
/// When a new file is created, the file MUST NOT be compressed, even if it is on a compressed volume.
|
||||
/// The flag MUST be ignored when opening an existing file.
|
||||
/// </summary>
|
||||
FILE_NO_COMPRESSION = 0x8000,
|
||||
|
||||
FILE_RESERVE_OPFILTER = 0x00100000,
|
||||
|
||||
FILE_OPEN_REPARSE_POINT = 0x00200000,
|
||||
|
||||
/// <summary>
|
||||
/// In a hierarchical storage management environment, this option requests that the file SHOULD NOT be recalled from tertiary storage such as tape.
|
||||
/// A file recall can take up to several minutes in a hierarchical storage management environment.
|
||||
/// The clients can specify this option to avoid such delays.
|
||||
/// </summary>
|
||||
FILE_OPEN_NO_RECALL = 0x00400000,
|
||||
|
||||
FILE_OPEN_FOR_FREE_SPACE_QUERY = 0x00800000,
|
||||
}
|
||||
}
|
27
SMBLibrary/SMB1/Enums/NTCreate/DesiredAccess.cs
Normal file
27
SMBLibrary/SMB1/Enums/NTCreate/DesiredAccess.cs
Normal file
|
@ -0,0 +1,27 @@
|
|||
using System;
|
||||
|
||||
namespace SMBLibrary.SMB1
|
||||
{
|
||||
[Flags]
|
||||
public enum DesiredAccess : uint
|
||||
{
|
||||
FILE_READ_DATA = 0x0001,
|
||||
FILE_WRITE_DATA = 0x0002,
|
||||
FILE_APPEND_DATA = 0x0004,
|
||||
FILE_READ_EA = 0x0008,
|
||||
FILE_WRITE_EA = 0x0010,
|
||||
FILE_EXECUTE = 0x0020,
|
||||
FILE_READ_ATTRIBUTES = 0x0080,
|
||||
FILE_WRITE_ATTRIBUTES = 0x0100,
|
||||
DELETE = 0x00010000,
|
||||
READ_CONTROL = 0x00020000,
|
||||
WRITE_DAC = 0x00040000,
|
||||
WRITE_OWNER = 0x00080000,
|
||||
SYNCHRONIZE = 0x00100000,
|
||||
ACCESS_SYSTEM_SECURITY = 0x01000000,
|
||||
MAXIMUM_ALLOWED = 0x02000000,
|
||||
GENERIC_ALL = 0x10000000,
|
||||
GENERIC_EXECUTE = 0x20000000,
|
||||
GENERIC_WRITE = 0x40000000,
|
||||
}
|
||||
}
|
12
SMBLibrary/SMB1/Enums/NTCreate/FileStatus.cs
Normal file
12
SMBLibrary/SMB1/Enums/NTCreate/FileStatus.cs
Normal file
|
@ -0,0 +1,12 @@
|
|||
using System;
|
||||
|
||||
namespace SMBLibrary.SMB1
|
||||
{
|
||||
[Flags]
|
||||
public enum FileStatus : ushort
|
||||
{
|
||||
NO_EAS = 0x01,
|
||||
NO_SUBSTREAMS = 0x02,
|
||||
NO_REPARSETAG = 0x04,
|
||||
}
|
||||
}
|
11
SMBLibrary/SMB1/Enums/NTCreate/ImpersonationLevel.cs
Normal file
11
SMBLibrary/SMB1/Enums/NTCreate/ImpersonationLevel.cs
Normal file
|
@ -0,0 +1,11 @@
|
|||
|
||||
namespace SMBLibrary.SMB1
|
||||
{
|
||||
public enum ImpersonationLevel : uint
|
||||
{
|
||||
SEC_ANONYMOUS = 0x00,
|
||||
SEC_IDENTIFY = 0x01,
|
||||
SEC_IMPERSONATE = 0x02,
|
||||
SECURITY_DELEGATION = 0x04, // SMB 1.0 addition
|
||||
}
|
||||
}
|
20
SMBLibrary/SMB1/Enums/NTCreate/NTCreateFlags.cs
Normal file
20
SMBLibrary/SMB1/Enums/NTCreate/NTCreateFlags.cs
Normal file
|
@ -0,0 +1,20 @@
|
|||
using System;
|
||||
|
||||
namespace SMBLibrary.SMB1
|
||||
{
|
||||
[Flags]
|
||||
public enum NTCreateFlags : uint
|
||||
{
|
||||
/// <summary>
|
||||
/// If set, the client requests an exclusive OpLock.
|
||||
/// </summary>
|
||||
NT_CREATE_REQUEST_OPLOCK = 0x0002,
|
||||
|
||||
/// <summary>
|
||||
/// If set, the client requests an exclusive batch OpLock.
|
||||
/// </summary>
|
||||
NT_CREATE_REQUEST_OPBATCH = 0x0004,
|
||||
NT_CREATE_OPEN_TARGET_DIR = 0x0008,
|
||||
NT_CREATE_REQUEST_EXTENDED_RESPONSE = 0x0010, // SMB 1.0 addition
|
||||
}
|
||||
}
|
11
SMBLibrary/SMB1/Enums/NTCreate/OpLockLevel.cs
Normal file
11
SMBLibrary/SMB1/Enums/NTCreate/OpLockLevel.cs
Normal file
|
@ -0,0 +1,11 @@
|
|||
|
||||
namespace SMBLibrary.SMB1
|
||||
{
|
||||
public enum OpLockLevel : byte
|
||||
{
|
||||
NoOpLockGranted = 0x00,
|
||||
ExclusiveOpLockGranted = 0x01,
|
||||
BatchOpLockGranted = 0x02,
|
||||
Level2OpLockGranted = 0x03,
|
||||
}
|
||||
}
|
10
SMBLibrary/SMB1/Enums/NTCreate/SecurityFlags.cs
Normal file
10
SMBLibrary/SMB1/Enums/NTCreate/SecurityFlags.cs
Normal file
|
@ -0,0 +1,10 @@
|
|||
using System;
|
||||
|
||||
namespace SMBLibrary.SMB1
|
||||
{
|
||||
public enum SecurityFlags : byte
|
||||
{
|
||||
SMB_SECURITY_CONTEXT_TRACKING = 0x01,
|
||||
SMB_SECURITY_EFFECTIVE_ONLY = 0x02,
|
||||
}
|
||||
}
|
15
SMBLibrary/SMB1/Enums/NTCreate/ShareAccess.cs
Normal file
15
SMBLibrary/SMB1/Enums/NTCreate/ShareAccess.cs
Normal file
|
@ -0,0 +1,15 @@
|
|||
using System;
|
||||
|
||||
namespace SMBLibrary.SMB1
|
||||
{
|
||||
/// <summary>
|
||||
/// No bits set = Prevents the file from being shared
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum ShareAccess : uint
|
||||
{
|
||||
FILE_SHARE_READ = 0x0001,
|
||||
FILE_SHARE_WRITE = 0x0002,
|
||||
FILE_SHARE_DELETE = 0x0004,
|
||||
}
|
||||
}
|
23
SMBLibrary/SMB1/Enums/Negotiate/SecurityMode.cs
Normal file
23
SMBLibrary/SMB1/Enums/Negotiate/SecurityMode.cs
Normal file
|
@ -0,0 +1,23 @@
|
|||
using System;
|
||||
|
||||
namespace SMBLibrary.SMB1
|
||||
{
|
||||
[Flags]
|
||||
public enum SecurityMode : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// If clear, the server supports only Share Level access control.
|
||||
/// If set, the server supports only User Level access control.
|
||||
/// </summary>
|
||||
UserSecurityMode = 0x01, // NEGOTIATE_USER_SECURITY
|
||||
|
||||
/// <summary>
|
||||
/// If clear, the server supports only plaintext password authentication.
|
||||
/// If set, the server supports challenge/response authentication.
|
||||
/// Note: Windows 2000 and above do not support plain-text passwords by default.
|
||||
/// </summary>
|
||||
EncryptPasswords = 0x02, // NEGOTIATE_ENCRYPT_PASSWORDS
|
||||
SecuritySignaturesEnabled = 0x04, // NEGOTIATE_SECURITY_SIGNATURES_ENABLED
|
||||
SecuritySignaturesRequired = 0x08, // NEGOTIATE_SECURITY_SIGNATURES_REQUIRED
|
||||
}
|
||||
}
|
31
SMBLibrary/SMB1/Enums/Negotiate/ServerCapabilities.cs
Normal file
31
SMBLibrary/SMB1/Enums/Negotiate/ServerCapabilities.cs
Normal file
|
@ -0,0 +1,31 @@
|
|||
using System;
|
||||
|
||||
namespace SMBLibrary.SMB1
|
||||
{
|
||||
[Flags]
|
||||
public enum ServerCapabilities : uint
|
||||
{
|
||||
RawMode = 0x00000001, // CAP_RAW_MODE
|
||||
MPXMode = 0x00000002, // SMB_COM_READ_MPX
|
||||
Unicode = 0x00000004, // CAP_UNICODE
|
||||
LargeFiles = 0x00000008, // CAP_LARGE_FILES
|
||||
NTSMB = 0x00000010, // CAP_NT_SMBS
|
||||
RpcRemoteApi = 0x00000020, // CAP_RPC_REMOTE_APIS
|
||||
NTStatusCode = 0x00000040, // CAP_STATUS32
|
||||
Level2Oplocks = 0x00000080, // CAP_LEVEL_II_OPLOCKS
|
||||
LockAndRead = 0x00000100, // CAP_LOCK_AND_READ
|
||||
NTFind = 0x00000200, // CAP_NT_FIND
|
||||
DFS = 0x00001000, // CAP_DFS
|
||||
InfoLevelPassthrough = 0x00002000, // CAP_INFOLEVEL_PASSTHRU
|
||||
LargeRead = 0x00004000, // CAP_LARGE_READX
|
||||
LargeWrite = 0x00008000, // CAP_LARGE_WRITEX
|
||||
LightWeightIO = 0x00010000, // CAP_LWIO
|
||||
Unix = 0x00800000, // CAP_UNIX
|
||||
DynamicReauthentication = 0x20000000, // CAP_DYNAMIC_REAUTH
|
||||
|
||||
/// <summary>
|
||||
/// The server supports extended security for authentication
|
||||
/// </summary>
|
||||
ExtendedSecurity = 0x80000000, // CAP_EXTENDED_SECURITY
|
||||
}
|
||||
}
|
10
SMBLibrary/SMB1/Enums/Open/AccessRights.cs
Normal file
10
SMBLibrary/SMB1/Enums/Open/AccessRights.cs
Normal file
|
@ -0,0 +1,10 @@
|
|||
|
||||
namespace SMBLibrary.SMB1
|
||||
{
|
||||
public enum AccessRights : ushort
|
||||
{
|
||||
SMB_DA_ACCESS_READ = 0x00,
|
||||
SMB_DA_ACCESS_WRITE = 0x01,
|
||||
SMB_DA_ACCESS_READ_WRITE = 0x02,
|
||||
}
|
||||
}
|
31
SMBLibrary/SMB1/Enums/Open/OpenFlags.cs
Normal file
31
SMBLibrary/SMB1/Enums/Open/OpenFlags.cs
Normal file
|
@ -0,0 +1,31 @@
|
|||
using System;
|
||||
|
||||
namespace SMBLibrary.SMB1
|
||||
{
|
||||
[Flags]
|
||||
public enum OpenFlags : ushort
|
||||
{
|
||||
/// <summary>
|
||||
/// If this bit is set, the client requests that the file attribute data in the response be populated.
|
||||
/// All fields after the FID in the response are also populated. If this bit is not set,
|
||||
/// all fields after the FID in the response are zero.
|
||||
/// </summary>
|
||||
REQ_ATTRIB = 0x0001,
|
||||
|
||||
/// <summary>
|
||||
/// Client requests an exclusive OpLock on the file.
|
||||
/// </summary>
|
||||
REQ_OPLOCK = 0x0002,
|
||||
|
||||
/// <summary>
|
||||
/// Client requests a Batch OpLock on the file.
|
||||
/// </summary>
|
||||
REQ_OPLOCK_BATCH = 0x0004,
|
||||
|
||||
/// <summary>
|
||||
/// SMB 1.0 Addition.
|
||||
/// If set, the client is requesting the extended format of the response.
|
||||
/// </summary>
|
||||
SMB_OPEN_EXTENDED_RESPONSE = 0x0010,
|
||||
}
|
||||
}
|
11
SMBLibrary/SMB1/Enums/Open/OpenResult.cs
Normal file
11
SMBLibrary/SMB1/Enums/Open/OpenResult.cs
Normal file
|
@ -0,0 +1,11 @@
|
|||
|
||||
namespace SMBLibrary.SMB1
|
||||
{
|
||||
public enum OpenResult : byte
|
||||
{
|
||||
Reserved = 0x00,
|
||||
FileExistedAndWasOpened = 0x01,
|
||||
NotExistedAndWasCreated = 0x02,
|
||||
FileExistedAndWasTruncated = 0x03,
|
||||
}
|
||||
}
|
28
SMBLibrary/SMB1/Enums/ResourceType.cs
Normal file
28
SMBLibrary/SMB1/Enums/ResourceType.cs
Normal file
|
@ -0,0 +1,28 @@
|
|||
|
||||
namespace SMBLibrary.SMB1
|
||||
{
|
||||
public enum ResourceType : ushort
|
||||
{
|
||||
FileTypeDisk = 0x0000,
|
||||
FileTypeByteModePipe = 0x0001,
|
||||
FileTypeMessageModePipe = 0x0002,
|
||||
FileTypePrinter = 0x0003,
|
||||
|
||||
/// <summary>
|
||||
/// OpenAndX Response: Valid.
|
||||
/// OpenAndX Extended Response: Invalid (SMB 1.0).
|
||||
/// NTCreateAndX Response: Valid.
|
||||
/// NTCreateAndX Extended Response: Invalid (SMB 1.0).
|
||||
/// Transact2Open2: Was never valid
|
||||
/// </summary>
|
||||
FileTypeCommDevice = 0x0004,
|
||||
|
||||
/// <summary>
|
||||
/// OpenAndX Response: Valid
|
||||
/// NTCreateAndX Response: Invalid
|
||||
/// Transact2Open2 Response: Valid
|
||||
/// TransactCreate Response: Valid
|
||||
/// </summary>
|
||||
FileTypeUnknown = 0xFFFF,
|
||||
}
|
||||
}
|
11
SMBLibrary/SMB1/Enums/SessionSetup/SessionSetupAction.cs
Normal file
11
SMBLibrary/SMB1/Enums/SessionSetup/SessionSetupAction.cs
Normal file
|
@ -0,0 +1,11 @@
|
|||
using System;
|
||||
|
||||
namespace SMBLibrary.SMB1
|
||||
{
|
||||
[Flags]
|
||||
public enum SessionSetupAction : ushort
|
||||
{
|
||||
SetupGuest = 0x01, // SMB_SETUP_GUEST
|
||||
UseLanmanKey = 0x02, // SMB_SETUP_USE_LANMAN_KEY
|
||||
}
|
||||
}
|
11
SMBLibrary/SMB1/Enums/Transaction/TransactionFlags.cs
Normal file
11
SMBLibrary/SMB1/Enums/Transaction/TransactionFlags.cs
Normal file
|
@ -0,0 +1,11 @@
|
|||
using System;
|
||||
|
||||
namespace SMBLibrary.SMB1
|
||||
{
|
||||
[Flags]
|
||||
public enum TransactionFlags : ushort
|
||||
{
|
||||
DISCONNECT_TID = 0x0001,
|
||||
NO_RESPONSE = 0x0002,
|
||||
}
|
||||
}
|
13
SMBLibrary/SMB1/Enums/TreeConnect/OptionalSupportFlags.cs
Normal file
13
SMBLibrary/SMB1/Enums/TreeConnect/OptionalSupportFlags.cs
Normal file
|
@ -0,0 +1,13 @@
|
|||
using System;
|
||||
|
||||
namespace SMBLibrary.SMB1
|
||||
{
|
||||
[Flags]
|
||||
public enum OptionalSupportFlags : ushort
|
||||
{
|
||||
/// <summary>
|
||||
/// The server supports the use of SMB_FILE_ATTRIBUTES exclusive search attributes in client requests.
|
||||
/// </summary>
|
||||
SMB_SUPPORT_SEARCH_BITS = 0x01,
|
||||
}
|
||||
}
|
16
SMBLibrary/SMB1/Enums/TreeConnect/ServiceName.cs
Normal file
16
SMBLibrary/SMB1/Enums/TreeConnect/ServiceName.cs
Normal file
|
@ -0,0 +1,16 @@
|
|||
|
||||
namespace SMBLibrary.SMB1
|
||||
{
|
||||
public enum ServiceName
|
||||
{
|
||||
DiskShare,
|
||||
PrinterShare,
|
||||
NamedPipe,
|
||||
SerialCommunicationsDevice,
|
||||
|
||||
/// <summary>
|
||||
/// Valid only for request
|
||||
/// </summary>
|
||||
AnyType,
|
||||
}
|
||||
}
|
27
SMBLibrary/SMB1/Enums/TreeConnect/TreeConnectFlags.cs
Normal file
27
SMBLibrary/SMB1/Enums/TreeConnect/TreeConnectFlags.cs
Normal file
|
@ -0,0 +1,27 @@
|
|||
using System;
|
||||
|
||||
namespace SMBLibrary.SMB1
|
||||
{
|
||||
[Flags]
|
||||
public enum TreeConnectFlags : ushort
|
||||
{
|
||||
/// <summary>
|
||||
/// If set and SMB_Header.TID is valid, the tree connect specified by the TID in the SMB
|
||||
/// header of the request SHOULD be disconnected when the server sends the response. If this tree disconnect fails, then the error SHOULD be ignored
|
||||
/// If set and TID is invalid, the server MUST ignore this bit.
|
||||
/// </summary>
|
||||
DisconnectTID = 0x0001, // TREE_CONNECT_ANDX_DISCONNECT_TID
|
||||
|
||||
/// <summary>
|
||||
/// SMB 1.0 addition.
|
||||
/// If set, then the client is requesting signing key protection.
|
||||
/// </summary>
|
||||
ExtendedSignatures = 0x0004, // TREE_CONNECT_ANDX_EXTENDED_SIGNATURES
|
||||
|
||||
/// <summary>
|
||||
/// SMB 1.0 addition.
|
||||
/// If set, then the client is requesting extended information in the SMB_COM_TREE_CONNECT_ANDX response.
|
||||
/// </summary>
|
||||
ExtendedResponse = 0x0008, // TREE_CONNECT_ANDX_EXTENDED_RESPONSE
|
||||
}
|
||||
}
|
13
SMBLibrary/SMB1/Enums/Write/WriteMode.cs
Normal file
13
SMBLibrary/SMB1/Enums/Write/WriteMode.cs
Normal file
|
@ -0,0 +1,13 @@
|
|||
using System;
|
||||
|
||||
namespace SMBLibrary.SMB1
|
||||
{
|
||||
[Flags]
|
||||
public enum WriteMode : ushort
|
||||
{
|
||||
WritethroughMode = 0x0001,
|
||||
ReadBytesAvailable = 0x0002,
|
||||
RAW_MODE = 0x0004,
|
||||
MSG_START = 0x0008,
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
|
||||
namespace SMBLibrary.SMB1
|
||||
{
|
||||
public enum CompletionFilter : uint
|
||||
{
|
||||
FILE_NOTIFY_CHANGE_FILE_NAME = 0x00000001,
|
||||
FILE_NOTIFY_CHANGE_DIR_NAME = 0x00000002,
|
||||
FILE_NOTIFY_CHANGE_NAME = 0x00000003,
|
||||
FILE_NOTIFY_CHANGE_ATTRIBUTES = 0x00000004,
|
||||
FILE_NOTIFY_CHANGE_SIZE = 0x00000008,
|
||||
FILE_NOTIFY_CHANGE_LAST_WRITE = 0x00000010,
|
||||
FILE_NOTIFY_CHANGE_LAST_ACCESS = 0x00000020,
|
||||
FILE_NOTIFY_CHANGE_CREATION = 0x00000040,
|
||||
FILE_NOTIFY_CHANGE_EA = 0x00000080,
|
||||
FILE_NOTIFY_CHANGE_SECURITY = 0x00000100,
|
||||
FILE_NOTIFY_CHANGE_STREAM_NAME = 0x00000200,
|
||||
FILE_NOTIFY_CHANGE_STREAM_SIZE = 0x00000400,
|
||||
FILE_NOTIFY_CHANGE_STREAM_WRITE = 0x00000800,
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
|
||||
namespace SMBLibrary.SMB1
|
||||
{
|
||||
/// <summary>
|
||||
/// This is the Function field in NTTransactRequest
|
||||
/// </summary>
|
||||
public enum NTTransactSubcommandName : ushort
|
||||
{
|
||||
NT_TRANSACT_CREATE = 0x0001,
|
||||
NT_TRANSACT_IOCTL = 0x0002,
|
||||
NT_TRANSACT_SET_SECURITY_DESC = 0x0003,
|
||||
NT_TRANSACT_NOTIFY_CHANGE = 0x0004,
|
||||
// NT_TRANSACT_RENAME = 0x0005,
|
||||
NT_TRANSACT_QUERY_SECURITY_DESC = 0x0006,
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
using System;
|
||||
|
||||
namespace SMBLibrary.SMB1
|
||||
{
|
||||
[Flags]
|
||||
public enum SecurityInfoFields : uint
|
||||
{
|
||||
OWNER_SECURITY_INFORMATION = 0x00000001,
|
||||
GROUP_SECURITY_INFORMATION = 0x00000002,
|
||||
DACL_SECURITY_INFORMATION = 0x00000004,
|
||||
SACL_SECURITY_INFORMATION = 0x00000008,
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue