Exemple #1
0
        /// <summary>
        /// Verify the signature of a Smb2CompoundPacket
        /// </summary>
        /// <param name="packet">The compound packet to be verified</param>
        private void TryVerifySignature(Smb2CompoundPacket packet, byte[] messageBytes)
        {
            try
            {
                ulong firstSessionId = packet.Packets[0].Header.SessionId;

                uint offset = 0;
                for (int i = 0; i < packet.Packets.Count; i++)
                {
                    Smb2SinglePacket singlePacket = packet.Packets[i];
                    // NextCommand is the offset, in bytes, from the beginning of this SMB2 header to the start of the subsequent 8-byte aligned SMB2 header.
                    uint   packetLen   = singlePacket.Header.NextCommand != 0 ? singlePacket.Header.NextCommand : (uint)(messageBytes.Length - offset);
                    byte[] packetBytes = new byte[packetLen];
                    Array.Copy(messageBytes, offset, packetBytes, 0, packetLen);
                    offset += packetLen;

                    // For Related operations, the sessinId is in the first packet of the compound packet.
                    ulong sessionId = singlePacket.Header.Flags.HasFlag(Packet_Header_Flags_Values.FLAGS_RELATED_OPERATIONS) ? firstSessionId : singlePacket.Header.SessionId;

                    TryVerifySignature(singlePacket, sessionId, packetBytes);
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Error happened during signature verification of compound packet: " + packet.ToString() + ". Exception message:" + ex.Message);
            }
        }
Exemple #2
0
        /// <summary>
        /// Decode the message as smb2 compound packet
        /// </summary>
        /// <param name="messageBytes">The received packet</param>
        /// <param name="role">The role of this decoder, client or server</param>
        /// <param name="consumedLength">[OUT]The consumed length of the message</param>
        /// <param name="expectedLength">[OUT]The expected length</param>
        /// <returns>A Smb2Packet</returns>
        public Smb2Packet DecodeCompoundPacket(
            byte[] messageBytes,
            Smb2Role role,
            out int consumedLength,
            out int expectedLength
            )
        {
            Smb2CompoundPacket compoundPacket = new Smb2CompoundPacket();

            compoundPacket.decoder = this;

            compoundPacket.FromBytes(messageBytes, out consumedLength, out expectedLength);

            return(compoundPacket);
        }
Exemple #3
0
        /// <summary>
        /// Check if the compound packet needs to be encrypted but actually not encrypted.
        /// </summary>
        private void CheckIfNeedEncrypt(Smb2CompoundPacket packet)
        {
            if (!CheckEncrypt)
            {
                return;
            }
            ulong firstSessionId = packet.Packets[0].Header.SessionId;

            for (int i = 0; i < packet.Packets.Count; i++)
            {
                Smb2SinglePacket singlePacket = packet.Packets[i];

                // For Related operations, the sessionId is in the first packet of the compound packet.
                ulong sessionId = singlePacket.Header.Flags.HasFlag(Packet_Header_Flags_Values.FLAGS_RELATED_OPERATIONS) ? firstSessionId : singlePacket.Header.SessionId;
                CheckIfNeedEncrypt(singlePacket, sessionId);
            }
        }
        /// <summary>
        /// Decode the message as smb2 compound packet
        /// </summary>
        /// <param name="messageBytes">The received packet</param>
        /// <param name="role">The role of this decoder, client or server</param>
        /// <param name="consumedLength">[OUT]The consumed length of the message</param>
        /// <param name="expectedLength">[OUT]The expected length</param>
        /// <param name="transformHeader">The optional transform header</param>
        /// <returns>A Smb2Packet</returns>
        public Smb2Packet DecodeCompoundPacket(
            byte[] messageBytes,
            Smb2Role role,
            out int consumedLength,
            out int expectedLength,
            Transform_Header?transformHeader
            )
        {
            Smb2CompoundPacket compoundPacket = new Smb2CompoundPacket();

            compoundPacket.decoder = this;

            compoundPacket.FromBytes(messageBytes, out consumedLength, out expectedLength);

            VerifyCompoundPacket(compoundPacket, role, transformHeader);

            return(compoundPacket);
        }
        /// <summary>
        /// Verify the signature of a Smb2CompoundPacket
        /// </summary>
        /// <param name="packet">The compound packet to be verified</param>
        /// <returns>True when signature verification succeeds and false when fails</returns>
        private bool TryVerifySignature(Smb2CompoundPacket packet)
        {
            try
            {
                Packet_Header header = TypeMarshal.ToStruct <Packet_Header>(packet.ToBytes());

                if ((header.Flags & Packet_Header_Flags_Values.FLAGS_RELATED_OPERATIONS)
                    == Packet_Header_Flags_Values.FLAGS_RELATED_OPERATIONS)
                {
                    //The realSessionId is the sessionId in the first pacekt of the compoundpacket for related packets.
                    ulong realSessionId = packet.Packets[0].Header.SessionId;
                    for (int i = 0; i < packet.Packets.Count; i++)
                    {
                        Smb2SinglePacket singlePacket = packet.Packets[i];
                        if (!TryVerifySignature(singlePacket, realSessionId))
                        {
                            break;
                        }
                    }
                }
                else
                {
                    for (int i = 0; i < packet.Packets.Count; i++)
                    {
                        Smb2SinglePacket singlePacket = packet.Packets[i];
                        if (!TryVerifySignature(singlePacket, singlePacket.Header.SessionId))
                        {
                            break;
                        }
                    }
                }
                return(true);
            }
            catch (Exception ex)
            {
                throw new Exception("Error happened during signature verification of compound packet: " + packet.ToString() + ". Exception message:" + ex.Message);
            }
        }
        /// <summary>
        /// Verify the signature of a Smb2CompoundPacket
        /// </summary>
        /// <param name="packet">The compound packet to be verified</param>        
        private void TryVerifySignature(Smb2CompoundPacket packet, byte[] messageBytes)
        {
            try
            {

                ulong firstSessionId = packet.Packets[0].Header.SessionId;

                uint offset = 0;
                for (int i = 0; i < packet.Packets.Count; i++)
                {
                    Smb2SinglePacket singlePacket = packet.Packets[i];
                    // NextCommand is the offset, in bytes, from the beginning of this SMB2 header to the start of the subsequent 8-byte aligned SMB2 header.
                    uint packetLen = singlePacket.Header.NextCommand != 0 ? singlePacket.Header.NextCommand : (uint)(messageBytes.Length - offset);
                    byte[] packetBytes = new byte[packetLen];
                    Array.Copy(messageBytes, offset, packetBytes, 0, packetLen);
                    offset += packetLen;

                    // For Related operations, the sessinId is in the first packet of the compound packet.
                    ulong sessionId = singlePacket.Header.Flags.HasFlag(Packet_Header_Flags_Values.FLAGS_RELATED_OPERATIONS) ? firstSessionId : singlePacket.Header.SessionId;

                    TryVerifySignature(singlePacket, sessionId, packetBytes);
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Error happened during signature verification of compound packet: " + packet.ToString() + ". Exception message:" + ex.Message);
            }
        }
        /// <summary>
        /// Decode the message as smb2 compound packet
        /// </summary>
        /// <param name="messageBytes">The received packet</param>
        /// <param name="role">The role of this decoder, client or server</param>
        /// <param name="consumedLength">[OUT]The consumed length of the message</param>
        /// <param name="expectedLength">[OUT]The expected length</param>
        /// <returns>A Smb2Packet</returns>
        public Smb2Packet DecodeCompoundPacket(
            byte[] messageBytes,
            Smb2Role role,
            out int consumedLength,
            out int expectedLength
            )
        {
            Smb2CompoundPacket compoundPacket = new Smb2CompoundPacket();
            compoundPacket.decoder = this;

            compoundPacket.FromBytes(messageBytes, out consumedLength, out expectedLength);

            return compoundPacket;
        }
        private void VerifyCompoundPacket(Smb2CompoundPacket compoundPacket, Smb2Role role, Transform_Header?transformHeader)
        {
            for (int i = 0; i < compoundPacket.Packets.Count; i++)
            {
                var packet = compoundPacket.Packets[i];

                if (packet.Header.NextCommand % 8 != 0)
                {
                    throw new InvalidOperationException("NextCommand is not a 8-byte aligned offset!");
                }

                switch (role)
                {
                case Smb2Role.Client:
                {
                    if (transformHeader != null)
                    {
                        // For each response in a compounded response, if the SessionId field of SMB2 header is not equal to the SessionId field in the SMB2 TRANSFORM_HEADER,
                        // the client SHOULD<139> discard the entire compounded response and stop processing.
                        if (packet.Header.SessionId != transformHeader.Value.SessionId)
                        {
                            throw new InvalidOperationException("SessionId is inconsistent for encrypted compounded response.");
                        }
                    }
                }
                break;

                case Smb2Role.Server:
                {
                    // The server MUST verify if any of the following conditions returns TRUE and, if so, the server MUST disconnect the connection:
                    // For the first operation of a compounded request,
                    // - SMB2_FLAGS_RELATED_OPERATIONS is set in the Flags field of the SMB2 header of the request
                    // - The SessionId field in the SMB2 header of the request is not equal to Request.TransformSessionId.
                    // In a compounded request, for each operation in the compounded chain except the first one,
                    // - SMB2_FLAGS_RELATED_OPERATIONS is not set in the Flags field of the SMB2 header of the operation and SessionId in the SMB2 header of the operation is not equal to Request.TransformSessionId.
                    if (i == 0)
                    {
                        if (packet.Header.Flags.HasFlag(Packet_Header_Flags_Values.FLAGS_RELATED_OPERATIONS))
                        {
                            throw new InvalidOperationException("FLAGS_RELATED_OPERATIONS should not be set for the first compounded request.");
                        }
                        if (transformHeader != null)
                        {
                            if (packet.Header.SessionId != transformHeader.Value.SessionId)
                            {
                                throw new InvalidOperationException("SessionId is inconsistent for encrypted compounded request.");
                            }
                        }
                    }
                    else
                    {
                        if (transformHeader != null)
                        {
                            if (!packet.Header.Flags.HasFlag(Packet_Header_Flags_Values.FLAGS_RELATED_OPERATIONS))
                            {
                                if (packet.Header.SessionId != transformHeader.Value.SessionId)
                                {
                                    throw new InvalidOperationException("SessionId is inconsistent for encrypted compounded request.");
                                }
                            }
                        }
                    }
                }
                break;
                }
            }
        }
        /// <summary>
        /// Verify the signature of a Smb2CompoundPacket
        /// </summary>
        /// <param name="packet">The compound packet to be verified</param>        
        /// <returns>True when signature verification succeeds and false when fails</returns>
        private bool TryVerifySignature(Smb2CompoundPacket packet)
        {
            try
            {
                Packet_Header header = TypeMarshal.ToStruct<Packet_Header>(packet.ToBytes());

                if ((header.Flags & Packet_Header_Flags_Values.FLAGS_RELATED_OPERATIONS)
                == Packet_Header_Flags_Values.FLAGS_RELATED_OPERATIONS)
                {
                    //The realSessionId is the sessionId in the first pacekt of the compoundpacket for related packets.
                    ulong realSessionId = packet.Packets[0].Header.SessionId;
                    for (int i = 0; i < packet.Packets.Count; i++)
                    {
                        Smb2SinglePacket singlePacket = packet.Packets[i];
                        if (!TryVerifySignature(singlePacket, realSessionId))
                        {
                            break;
                        }
                    }
                }
                else
                {
                    for (int i = 0; i < packet.Packets.Count; i++)
                    {
                        Smb2SinglePacket singlePacket = packet.Packets[i];
                        if (!TryVerifySignature(singlePacket, singlePacket.Header.SessionId))
                        {
                            break;
                        }
                    }
                }
                return true;
            }
            catch (Exception ex)
            {
                throw new Exception("Error happened during signature verification of compound packet: " + packet.ToString() + ". Exception message:" + ex.Message);
            }
        }
        /// <summary>
        /// Create Smb2CompoundPacket
        /// </summary>
        /// <param name="endpoint">represents where this packet will be sent</param>
        /// <param name="packets">Variable number of Single packets</param>
        /// <returns>A Smb2CompoundPacket</returns>
        public Smb2CompoundPacket CreateCompoundResponse(
            Smb2Endpoint endpoint,
            params Smb2SinglePacket[] packets
            )
        {
            if (packets == null)
            {
                throw new ArgumentNullException("packets");
            }

            if (packets.Length < 2)
            {
                throw new ArgumentException("The number of packet should be larger than 1", "packets");
            }

            Smb2CompoundPacket packet = new Smb2CompoundPacket();
            packet.Packets = new List<Smb2SinglePacket>();

            //The endpoint of the compoundpacket comes from innerPacket.
            packet.Endpoint = packets[0].Endpoint;

            for (int i = 0; i < packets.Length; i++)
            {
                if (((packets[0].Header.Flags & Packet_Header_Flags_Values.FLAGS_RELATED_OPERATIONS)
                    == Packet_Header_Flags_Values.FLAGS_RELATED_OPERATIONS))
                {
                    packets[i].OuterCompoundPacket = packet;
                }

                if (i != (packets.Length - 1))
                {

                    packets[i].Header.NextCommand = (uint)Smb2Utility.AlignBy8Bytes(packets[i].ToBytes().Length);
                }
                else
                {
                    packets[i].IsLast = true;
                }

                packets[i].IsInCompoundPacket = true;

                packet.Packets.Add(packets[i]);
            }

            packet.Sign();

            return packet;
        }