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