/// <summary> /// Build a Smb2Packet from a byte array /// </summary> /// <param name="data">The byte array</param> /// <param name="consumedLen">The consumed data length</param> /// <param name="expectedLen">The expected data length</param> internal override void FromBytes(byte[] data, out int consumedLen, out int expectedLen) { consumedLen = 0; this.NegotiateContext_ENCRYPTION = null; this.NegotiateContext_PREAUTH = null; this.Header = TypeMarshal.ToStruct <Packet_Header>(data, ref consumedLen); byte[] tempData = data.Skip(consumedLen).ToArray(); this.PayLoad = Smb2Utility.UnmarshalStructure <NEGOTIATE_Response>(tempData); consumedLen += Marshal.SizeOf(this.PayLoad); if (this.PayLoad.SecurityBufferLength > 0) { this.Buffer = data.Skip(this.PayLoad.SecurityBufferOffset).Take(this.PayLoad.SecurityBufferLength).ToArray(); consumedLen += this.Buffer.Length; } while (data.Length > consumedLen) { // Skip padding int paddingLen = 8 - (consumedLen) % 8; if (paddingLen != 8) { if (data.Length - consumedLen <= paddingLen) { break; } consumedLen += paddingLen; } if (data.Length - consumedLen < 8) { break; } SMB2_NEGOTIATE_CONTEXT_Type_Values contextType = (SMB2_NEGOTIATE_CONTEXT_Type_Values)BitConverter.ToUInt16(data, consumedLen); if (contextType == SMB2_NEGOTIATE_CONTEXT_Type_Values.SMB2_PREAUTH_INTEGRITY_CAPABILITIES) { if (this.NegotiateContext_PREAUTH != null) { throw new Exception("More than one SMB2_PREAUTH_INTEGRITY_CAPABILITIES are present."); } this.NegotiateContext_PREAUTH = TypeMarshal.ToStruct <SMB2_PREAUTH_INTEGRITY_CAPABILITIES>(data, ref consumedLen); } else if (contextType == SMB2_NEGOTIATE_CONTEXT_Type_Values.SMB2_ENCRYPTION_CAPABILITIES) { if (this.NegotiateContext_ENCRYPTION != null) { throw new Exception("More than one SMB2_ENCRYPTION_CAPABILITIES are present."); } this.NegotiateContext_ENCRYPTION = TypeMarshal.ToStruct <SMB2_ENCRYPTION_CAPABILITIES>(data, ref consumedLen); } else { throw new Exception(string.Format("Unknow Negotiate Context: {0}.", (ushort)contextType)); } } expectedLen = 0; }
/// <summary> /// Build a Smb2Packet from a byte array /// </summary> /// <param name="data">The byte array</param> /// <param name="consumedLen">The consumed data length</param> /// <param name="expectedLen">The expected data length</param> internal override void FromBytes(byte[] data, out int consumedLen, out int expectedLen) { consumedLen = 0; this.Header = TypeMarshal.ToStruct <Packet_Header>(data, ref consumedLen); byte[] tempData = data.Skip(consumedLen).ToArray(); this.PayLoad = Smb2Utility.UnmarshalStructure <NEGOTIATE_Request>(tempData); consumedLen += Marshal.SizeOf(this.PayLoad); this.Buffer = data.Skip(consumedLen).ToArray(); //Dialects + Padding + NegotiateContextList if (PayLoad.DialectCount > 0) { this.Dialects = Smb2Utility.UnmarshalStructArray <DialectRevision>(Buffer, PayLoad.DialectCount); consumedLen += PayLoad.DialectCount * sizeof(DialectRevision); } while (data.Length > consumedLen) { // Skip padding int paddingLen = 8 - (consumedLen) % 8; if (paddingLen != 8) { if (data.Length - consumedLen <= paddingLen) { break; } consumedLen += paddingLen; } if (data.Length - consumedLen < 8) { break; } SMB2_NEGOTIATE_CONTEXT_Type_Values contextType = (SMB2_NEGOTIATE_CONTEXT_Type_Values)BitConverter.ToUInt16(data, consumedLen); if (contextType == SMB2_NEGOTIATE_CONTEXT_Type_Values.SMB2_PREAUTH_INTEGRITY_CAPABILITIES) { this.NegotiateContext_PREAUTH = TypeMarshal.ToStruct <SMB2_PREAUTH_INTEGRITY_CAPABILITIES>(data, ref consumedLen); } else if (contextType == SMB2_NEGOTIATE_CONTEXT_Type_Values.SMB2_ENCRYPTION_CAPABILITIES) { this.NegotiateContext_ENCRYPTION = TypeMarshal.ToStruct <SMB2_ENCRYPTION_CAPABILITIES>(data, ref consumedLen); } else if (contextType == SMB2_NEGOTIATE_CONTEXT_Type_Values.SMB2_COMPRESSION_CAPABILITIES) { this.NegotiateContext_COMPRESSION = TypeMarshal.ToStruct <SMB2_COMPRESSION_CAPABILITIES>(data, ref consumedLen); } else if (contextType == SMB2_NEGOTIATE_CONTEXT_Type_Values.SMB2_NETNAME_NEGOTIATE_CONTEXT_ID) { this.NegotiateContext_NETNAME = SMB2_NETNAME_NEGOTIATE_CONTEXT_ID.Unmarshal(data, ref consumedLen); } } expectedLen = 0; }
/// <summary> /// Build a Smb2TreeConnectRequestPacket from a byte array /// </summary> /// <param name="data">The byte array</param> /// <param name="consumedLen">The consumed data length</param> /// <param name="expectedLen">The expected data length</param> internal override void FromBytes(byte[] data, out int consumedLen, out int expectedLen) { consumedLen = 0; this.Header = TypeMarshal.ToStruct <Packet_Header>(data, ref consumedLen); this.PayLoad = Smb2Utility.UnmarshalStructure <TREE_CONNECT_Request>(data.Skip(consumedLen).ToArray()); //based on .net unmarshal consumedLen += Marshal.SizeOf(typeof(TREE_CONNECT_Request)); var packetBuffer = this as IPacketBuffer; int bufferLength = (int)packetBuffer.BufferLength; this.Buffer = data.Skip(consumedLen).Take(bufferLength).ToArray(); consumedLen += bufferLength; expectedLen = 0; }
public static byte[] Decrypt(byte[] bytes, Dictionary <ulong, Smb2CryptoInfo> cryptoInfoTable, Smb2Role role) { // Client: If the size of the message received from the server is not greater than the size of SMB2 TRANSFORM_HEADER as specified, the client MUST discard the message. // Server: If the size of the message received from the client is not greater than the size of the SMB2 TRANSFORM_HEADER, the server MUST disconnect the connection. int minimumLength = Marshal.SizeOf(typeof(Transform_Header)); if (bytes.Length < minimumLength) { throw new InvalidOperationException( String.Format( "Too less data for encrypted message. Expected length more than {0}, actual {1}.", minimumLength, bytes.Length ) ); } Transform_Header transformHeader = Smb2Utility.UnmarshalStructure <Transform_Header>(bytes); // Client: If the Flags/EncryptionAlgorithm in the SMB2 TRANSFORM_HEADER is not 0x0001, the client MUST discard the message. // Server: If the Flags/EncryptionAlgorithm in the SMB2 TRANSFORM_HEADER is not 0x0001, the server MUST disconnect the connection. if (transformHeader.Flags != TransformHeaderFlags.Encrypted) { throw new InvalidOperationException( String.Format( "Flags/EncryptionAlgorithm field is invalid for encrypted message. Expected value 0x0001, actual {0}.", (ushort)transformHeader.Flags ) ); } if (transformHeader.SessionId == 0 || !cryptoInfoTable.ContainsKey(transformHeader.SessionId)) { throw new InvalidOperationException("Invalid SessionId in TRANSFORM_HEADER."); } Smb2CryptoInfo cryptoInfo = cryptoInfoTable[transformHeader.SessionId]; using (var bcrypt = new BCryptAlgorithm("AES")) { int nonceLength = 0; BCryptCipherMode mode = BCryptCipherMode.NotAvailable; GetCryptoParams(cryptoInfo, CryptoOperationType.Decrypt, out mode, out nonceLength); bcrypt.Mode = mode; bcrypt.Key = role == Smb2Role.Server ? cryptoInfo.ServerInKey : cryptoInfo.ServerOutKey; return(bcrypt.Decrypt(bytes.Skip(52).ToArray(), transformHeader.Nonce.ToByteArray().Take(nonceLength).ToArray(), bytes.Skip(20).Take(32).ToArray(), transformHeader.Signature)); } }
/// <summary> /// Build a Smb2CompressedPacket from a byte array. /// </summary> /// <param name="data">The byte array.</param> /// <param name="consumedLen">The consumed data length.</param> /// <param name="expectedLen">The expected data length.</param> internal override void FromBytes(byte[] data, out int consumedLen, out int expectedLen) { int minimumLength = Marshal.SizeOf(Header); if (data.Length < minimumLength) { throw new InvalidOleVariantTypeException("Not enough data for Transform_Header!"); } Header = Smb2Utility.UnmarshalStructure <Transform_Header>(data.Take(minimumLength).ToArray()); EncryptdData = data.Skip(minimumLength).ToArray(); consumedLen = data.Length; expectedLen = 0; }
/// <summary> /// Build a Smb2CompressedPacket from a byte array. /// </summary> /// <param name="data">The byte array.</param> /// <param name="consumedLen">The consumed data length.</param> /// <param name="expectedLen">The expected data length.</param> internal override void FromBytes(byte[] data, out int consumedLen, out int expectedLen) { int minimumLength = Marshal.SizeOf(Header); if (data.Length < minimumLength) { throw new InvalidOperationException("[MS-SMB2] section 3.3.5.2.1.1 If the size of the message received from the client is not greater than" + "the size of the SMB2 TRANSFORM_HEADER, the server MUST disconnect the connection."); } Header = Smb2Utility.UnmarshalStructure <Transform_Header>(data.Take(minimumLength).ToArray()); EncryptdData = data.Skip(minimumLength).ToArray(); consumedLen = data.Length; expectedLen = 0; }
public static byte[] Decrypt(byte[] bytes, Dictionary <ulong, Smb2CryptoInfo> cryptoInfoTable, Smb2Role role) { Transform_Header transformHeader = Smb2Utility.UnmarshalStructure <Transform_Header>(bytes); if (transformHeader.SessionId == 0 || !cryptoInfoTable.ContainsKey(transformHeader.SessionId)) { throw new InvalidOperationException("Invalid SessionId in TRANSFORM_HEADER."); } Smb2CryptoInfo cryptoInfo = cryptoInfoTable[transformHeader.SessionId]; using (var bcrypt = new BCryptAlgorithm("AES")) { int nonceLength = 0; BCryptCipherMode mode = BCryptCipherMode.NotAvailable; GetCryptoParams(cryptoInfo, CryptoOperationType.Decrypt, out mode, out nonceLength); bcrypt.Mode = mode; bcrypt.Key = role == Smb2Role.Server ? cryptoInfo.ServerInKey : cryptoInfo.ServerOutKey; return(bcrypt.Decrypt(bytes.Skip(52).ToArray(), transformHeader.Nonce.ToByteArray().Take(nonceLength).ToArray(), bytes.Skip(20).Take(32).ToArray(), transformHeader.Signature)); } }