예제 #1
0
        /// <summary>
        /// Compress SMB2 packet.
        /// </summary>
        /// <param name="packet">The SMB2 packet.</param>
        /// <param name="compressionInfo">Compression info.</param>
        /// <param name="role">SMB2 role.</param>
        /// <returns>The compressed packet, or original packet if compression is not applicable.</returns>
        public static Smb2Packet Compress(Smb2CompressiblePacket packet, Smb2CompressionInfo compressionInfo, Smb2Role role)
        {
            Smb2Packet compressed;

            if (compressionInfo.SupportChainedCompression)
            {
                compressed = CompressForChained(packet, compressionInfo, role);
            }
            else
            {
                compressed = CompressForNonChained(packet, compressionInfo, role);
            }

            if (compressed == packet)
            {
                // Compression is not applicable.
                return(packet);
            }

            var originalBytes = packet.ToBytes();

            var compressedBytes = compressed.ToBytes();

            // Check whether compression shrinks the on-wire packet size
            if (compressedBytes.Length < originalBytes.Length)
            {
                return(compressed);
            }
            else
            {
                return(packet);
            }
        }
예제 #2
0
        private static Smb2Packet CompressForNonChained(Smb2CompressiblePacket packet, Smb2CompressionInfo compressionInfo, Smb2Role role)
        {
            var compressionAlgorithm = GetCompressionAlgorithm(packet, compressionInfo, role);

            if (compressionAlgorithm == CompressionAlgorithm.NONE)
            {
                return(packet);
            }

            var packetBytes = packet.ToBytes();

            var compressor = GetCompressor(compressionAlgorithm);

            uint offset = 0;

            if (compressionInfo.CompressBufferOnly)
            {
                offset = (packet as IPacketBuffer).BufferOffset;
            }

            var compressedPacket = new Smb2NonChainedCompressedPacket();

            compressedPacket.Header.ProtocolId = Smb2Consts.ProtocolIdInCompressionTransformHeader;
            compressedPacket.Header.OriginalCompressedSegmentSize = (uint)packetBytes.Length;
            compressedPacket.Header.CompressionAlgorithm          = compressionAlgorithm;
            compressedPacket.Header.Flags     = Compression_Transform_Header_Flags.SMB2_COMPRESSION_FLAG_NONE;
            compressedPacket.Header.Offset    = offset;
            compressedPacket.UncompressedData = packetBytes.Take((int)offset).ToArray();
            compressedPacket.CompressedData   = compressor.Compress(packetBytes.Skip((int)offset).ToArray());

            compressedPacket.OriginalPacket = packet;

            return(compressedPacket);
        }
예제 #3
0
        /// <summary>
        /// Compress SMB2 packet.
        /// </summary>
        /// <param name="packet">The SMB2 packet.</param>
        /// <param name="compressionInfo">Compression info.</param>
        /// <param name="role">SMB2 role.</param>
        /// <param name="offset">The offset where compression start, default zero.</param>
        /// <returns></returns>
        public static Smb2Packet Compress(Smb2CompressiblePacket packet, Smb2CompressionInfo compressionInfo, Smb2Role role, uint offset = 0)
        {
            var compressionAlgorithm = GetCompressionAlgorithm(packet, compressionInfo, role);

            if (compressionAlgorithm == CompressionAlgorithm.NONE)
            {
                return packet;
            }

            var packetBytes = packet.ToBytes();

            var compressor = GetCompressor(compressionAlgorithm);

            var compressedPacket = new Smb2CompressedPacket();
            compressedPacket.Header.ProtocolId = Smb2Consts.ProtocolIdInCompressionTransformHeader;
            compressedPacket.Header.OriginalCompressedSegmentSize = (uint)packetBytes.Length;
            compressedPacket.Header.CompressionAlgorithm = compressionAlgorithm;
            compressedPacket.Header.Reserved = 0;
            compressedPacket.Header.Offset = offset;
            compressedPacket.UncompressedData = packetBytes.Take((int)offset).ToArray();
            compressedPacket.CompressedData = compressor.Compress(packetBytes.Skip((int)offset).ToArray());

            var compressedPackectBytes = compressedPacket.ToBytes();

            // Check whether compression shrinks the on-wire packet size
            if (compressedPackectBytes.Length < packetBytes.Length)
            {
                compressedPacket.OriginalPacket = packet;
                return compressedPacket;
            }
            else
            {
                return packet;
            }
        }
예제 #4
0
        /// <summary>
        /// Compress SMB2 packet.
        /// </summary>
        /// <param name="packet">The SMB2 packet.</param>
        /// <param name="compressionInfo">Compression info.</param>
        /// <param name="role">SMB2 role.</param>
        /// <param name="offset">The offset where compression start, default zero.</param>
        /// <returns></returns>
        public static Smb2Packet Compress(Smb2CompressiblePacket packet, Smb2CompressionInfo compressionInfo, Smb2Role role, uint offset = 0)
        {
            var compressionAlgorithm = GetCompressionAlgorithm(packet, compressionInfo, role);

            if (compressionAlgorithm == CompressionAlgorithm.NONE)
            {
                return(packet);
            }

            var packetBytes = packet.ToBytes();

            var compressor = GetCompressor(compressionAlgorithm);

            var compressedPacket = new Smb2CompressedPacket();

            compressedPacket.Header.ProtocolId = Smb2Consts.ProtocolIdInCompressionTransformHeader;
            compressedPacket.Header.OriginalCompressedSegmentSize = (uint)packetBytes.Length;
            compressedPacket.Header.CompressionAlgorithm          = compressionAlgorithm;
            compressedPacket.Header.Reserved  = 0;
            compressedPacket.Header.Offset    = offset;
            compressedPacket.UncompressedData = packetBytes.Take((int)offset).ToArray();
            compressedPacket.CompressedData   = compressor.Compress(packetBytes.Skip((int)offset).ToArray());

            // HACK: fake size
            if (((Smb2SinglePacket)packet).Header.Command == Smb2Command.WRITE)
            {
                ((Smb2WriteRequestPacket)packet).PayLoad.Length       += 0x1000;
                compressedPacket.Header.OriginalCompressedSegmentSize += 0x1000;
            }

            // HACK: force compressed packet to be sent
            return(compressedPacket);

            // var compressedPackectBytes = compressedPacket.ToBytes();

            // Check whether compression shrinks the on-wire packet size
            // if (compressedPackectBytes.Length < packetBytes.Length)
            // {
            //     compressedPacket.OriginalPacket = packet;
            //     return compressedPacket;
            // }
            // else
            // {
            //     return packet;
            // }
        }
        private static Smb2Packet CompressWithPatternV1(Smb2CompressiblePacket packet, Smb2CompressionInfo compressionInfo, Smb2Role role)
        {
            var data = packet.ToBytes();

            var dataToCompress = data;

            if (compressionInfo.CompressBufferOnly)
            {
                dataToCompress = data.Skip((packet as IPacketBuffer).BufferOffset).ToArray();
            }

            SMB2_COMPRESSION_PATTERN_PAYLOAD_V1?forwardDataPattern;

            SMB2_COMPRESSION_PATTERN_PAYLOAD_V1?backwardDataPattern;

            ScanForPatternV1(dataToCompress, out forwardDataPattern, out backwardDataPattern);

            if (forwardDataPattern == null && backwardDataPattern == null)
            {
                // Regress to non-chained since no pattern is found at front or end.
                return(CompressForNonChained(packet, compressionInfo, role));
            }

            var result = new Smb2ChainedCompressedPacket();

            result.OriginalPacket = packet;

            result.Header = new Compression_Transform_Header();

            result.Header.ProtocolId = Smb2Consts.ProtocolIdInCompressionTransformHeader;

            result.Header.OriginalCompressedSegmentSize = (UInt32)data.Length;

            result.Header.Flags = Compression_Transform_Header_Flags.SMB2_COMPRESSION_FLAG_CHAINED;

            var payloads = new List <Tuple <SMB2_COMPRESSION_PAYLOAD_HEADER, object> >();

            bool isFirst = true;

            if (compressionInfo.CompressBufferOnly)
            {
                var header = data.Take((packet as IPacketBuffer).BufferOffset).ToArray();

                var payloadHeader = SMB2_COMPRESSION_PAYLOAD_HEADER.Create(CompressionAlgorithm.NONE, (UInt32)header.Length, 0, ref isFirst);

                payloads.Add(new Tuple <SMB2_COMPRESSION_PAYLOAD_HEADER, object>(payloadHeader, header));
            }

            if (forwardDataPattern != null)
            {
                var payloadHeader = SMB2_COMPRESSION_PAYLOAD_HEADER.Create(CompressionAlgorithm.Pattern_V1, (UInt32)PatternPayloadLength, 0, ref isFirst);

                payloads.Add(new Tuple <SMB2_COMPRESSION_PAYLOAD_HEADER, object>(payloadHeader, forwardDataPattern));
            }

            int forwardDataPatternLength = (int)(forwardDataPattern?.Repetitions ?? 0);

            int backwardDataPatternLength = (int)(backwardDataPattern?.Repetitions ?? 0);

            var innerData = dataToCompress.Skip(forwardDataPatternLength).Take(dataToCompress.Length - forwardDataPatternLength - backwardDataPatternLength).ToArray();

            if (innerData.Length > 0)
            {
                var innerPayload = ChainedCompressWithCompressionAlgorithm(innerData, compressionInfo, ref isFirst);

                payloads.Add(innerPayload);
            }

            if (backwardDataPattern != null)
            {
                var payloadHeader = SMB2_COMPRESSION_PAYLOAD_HEADER.Create(CompressionAlgorithm.Pattern_V1, (UInt32)PatternPayloadLength, 0, ref isFirst);

                payloads.Add(new Tuple <SMB2_COMPRESSION_PAYLOAD_HEADER, object>(payloadHeader, backwardDataPattern));
            }

            result.Payloads = payloads.ToArray();

            return(result);
        }