internal void AddData(long fileOffset, byte[] fileData, Frame frame)
        {
            if (this.initialFrameNumber < 0 || frame.FrameNumber < this.initialFrameNumber)
            {
                this.initialFrameNumber = frame.FrameNumber;
                this.initialTimeStamp   = frame.Timestamp;
            }

            if (this.fileStream == null)
            {
                this.tempFilePath = FileStreamAssembler.GetFilePath(FileStreamAssembler.FileAssmeblyRootLocation.cache, this.fiveTuple, this.transferIsClientToServer, FileStreamTypes.SMB2, "", this.FilePath, this.fileStreamAssemblerList, uniqueFileId.GetHashCode().ToString("X4") + "-" + Utils.StringManglerUtil.ConvertToFilename(FilePath, 20)).absolutPath;

                this.fileStream = new System.IO.FileStream(tempFilePath, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.Write, System.IO.FileShare.None, 256 * 1024);//256 kB buffer is probably a suitable value for good performance on large files
            }
            if (this.fileStream != null && this.fileStream.CanWrite)
            {
                if (fileStream.Position != fileOffset)
                {
                    fileStream.Seek(fileOffset, System.IO.SeekOrigin.Begin);
                }

                fileStream.Write(fileData, 0, fileData.Length);
                if (this.segmentOffsetBytesWritten.ContainsKey(fileOffset))
                {
                    this.segmentOffsetBytesWritten[fileOffset] = Math.Max(fileData.Length, this.segmentOffsetBytesWritten[fileOffset]);
                }
                else
                {
                    this.segmentOffsetBytesWritten.Add(fileOffset, fileData.Length);
                }
                //check if we have 100% of the file
                long index = 0;
                foreach (var kvp in this.segmentOffsetBytesWritten)
                {
                    if (kvp.Key < index)
                    {
                        break;
                    }
                    index = Math.Max(index, kvp.Key + kvp.Value);
                }
                if (index > 0 && index == this.fileSize)
                {
                    this.AssembleAndClose();
                }
            }
        }
예제 #2
0
        internal ReconstructedFile Reassemble()
        {
            string destinationPath = FileStreamAssembler.GetFilePath(this.fileAssmeblyRootLocation, this.fiveTuple, this.transferIsClientToServer, this.fileStreamType, this.fileLocation, this.filename, this.parentAssemblerList, this.extendedFileId);

            ReconstructedFile reconstructedFile = null;

            using (System.IO.FileStream fullFileStream = new System.IO.FileStream(destinationPath, System.IO.FileMode.Create, System.IO.FileAccess.Write, System.IO.FileShare.None, 256 * 1024)) {//256 kB buffer is probably a suitable value for good performance on large files
                foreach (KeyValuePair <long, ReconstructedFile> part in this.filePartList)
                {
                    //if (fullFileStream.Position != part.Key)
                    //    fullFileStream.Seek(part.Key, System.IO.SeekOrigin.Begin);
                    long partOffset = fullFileStream.Position - part.Key;
                    if (partOffset < part.Key + part.Value.FileSize)
                    {
                        using (System.IO.FileStream partStream = new System.IO.FileStream(part.Value.FilePath, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read, 256 * 1024)) {
                            if (partOffset > 0)
                            {
                                partStream.Seek(partOffset, System.IO.SeekOrigin.Begin);
                            }
                            //Stream.CopyTo isn't available in .NET 2.0 so I'll have to copy the data manually
                            byte[] buffer    = new byte[4096];
                            int    bytesRead = partStream.Read(buffer, 0, buffer.Length);
                            while (bytesRead > 0)
                            {
                                fullFileStream.Write(buffer, 0, bytesRead);
                                bytesRead = partStream.Read(buffer, 0, buffer.Length);
                            }
                        }
                    }
                }
                fullFileStream.Close();//so that I can read the full size of the file when creating the ReconstructedFile
                reconstructedFile = new ReconstructedFile(destinationPath, this.fiveTuple, this.transferIsClientToServer, this.fileStreamType, this.extendedFileId, this.initialFrameNumber, this.timestamp, this.serverHostname);
            }

            this.closed = true;
            this.filePartList.Clear();
            return(reconstructedFile);
        }
        internal void AddData(long fileOffset, byte[] fileData, Frame frame)
        {
            if (this.initialFrameNumber < 0 || frame.FrameNumber < this.initialFrameNumber)
            {
                this.initialFrameNumber = frame.FrameNumber;
                this.initialTimeStamp   = frame.Timestamp;
            }

            if (this.fileStream == null)
            {
                this.tempFilePath = FileStreamAssembler.GetFilePath(FileStreamAssembler.FileAssmeblyRootLocation.cache, this.fiveTuple, this.transferIsClientToServer, FileStreamTypes.SMB2, "", this.filePath, this.fileStreamAssemblerList, uniqueFileId.GetHashCode().ToString("X4") + "-" + Utils.StringManglerUtil.ConvertToFilename(filePath, 20));

                this.fileStream = new System.IO.FileStream(tempFilePath, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.Write, System.IO.FileShare.None, 256 * 1024);//256 kB buffer is probably a suitable value for good performance on large files
            }
            if (this.fileStream != null && this.fileStream.CanWrite)
            {
                if (fileStream.Position != fileOffset)
                {
                    fileStream.Seek(fileOffset, System.IO.SeekOrigin.Begin);
                }
                fileStream.Write(fileData, 0, fileData.Length);
            }
        }
        internal void Close()
        {
            //TODO release all file handles and flush data to disk and move file from cache to server/port directory
            if (this.fileStream != null)
            {
                this.fileStream.Close();
            }

            if (this.parentAssemblerList != null)
            {
                this.parentAssemblerList.Remove(this.uniqueFileId);
            }

            string fixedFilename     = this.filePath;//no directory info
            string fixedFileLocation = "";

            FileStreamAssembler.FixFilenameAndLocation(ref fixedFilename, ref fixedFileLocation);

            string destinationPath;

            //reassemble the files at the server, regardless if they were downloaded from there or uploaded to the server
            if (this.transferIsClientToServer)
            {
                destinationPath = FileStreamAssembler.GetFilePath(FileStreamAssembler.FileAssmeblyRootLocation.destination, this.fiveTuple, this.transferIsClientToServer, this.fileStreamType, fixedFileLocation, fixedFilename, this.fileStreamAssemblerList, "");
            }
            else
            {
                destinationPath = FileStreamAssembler.GetFilePath(FileStreamAssembler.FileAssmeblyRootLocation.source, this.fiveTuple, this.transferIsClientToServer, this.fileStreamType, fixedFileLocation, fixedFilename, this.fileStreamAssemblerList, "");
            }


            //I need to create the directory here since the file might either be moved to this located or a new file will be created there from a stream
            //string directoryName = destinationPath.Substring(0, destinationPath.Length - fixedFilename.Length);
            string directoryName = System.IO.Path.GetDirectoryName(destinationPath);

            if (!System.IO.Directory.Exists(directoryName))
            {
                try {
                    System.IO.Directory.CreateDirectory(directoryName);
                }
                catch (Exception e) {
                    this.fileStreamAssemblerList.PacketHandler.OnAnomalyDetected("Error creating directory \"" + directoryName + "\" for path \"" + destinationPath + "\".\n" + e.Message);
                }
            }


            //files which are already completed can simply be moved to their final destination
            if (this.fileStream != null)
            {
                this.fileStream.Close();
            }
            try {
                //string tmpPath = this.tempFilePath;
                if (System.IO.File.Exists(this.tempFilePath))
                {
                    System.IO.File.Move(this.tempFilePath, destinationPath);
                }
            }
            catch (Exception e) {
                this.fileStreamAssemblerList.PacketHandler.OnAnomalyDetected("Error moving file \"" + this.tempFilePath + "\" to \"" + destinationPath + "\". " + e.Message);
            }

            if (System.IO.File.Exists(destinationPath))
            {
                try {
                    ReconstructedFile completedFile = new ReconstructedFile(destinationPath, this.fiveTuple, this.transferIsClientToServer, this.fileStreamType, this.details, this.initialFrameNumber, this.initialTimeStamp, this.serverHostname);
                    this.fileStreamAssemblerList.PacketHandler.AddReconstructedFile(completedFile);
                    //parentAssemblerList.PacketHandler.ParentForm.ShowReconstructedFile(completedFile);
                }
                catch (Exception e) {
                    this.fileStreamAssemblerList.PacketHandler.OnAnomalyDetected("Error creating reconstructed file: " + e.Message);
                }
            }
        }
예제 #5
0
        /// <summary>
        /// Closes the fileStream and removes the FileStreamAssembler from the parentAssemblerList
        /// </summary>
        internal void FinishAssembling()
        {
            this.isActive = false;
            try {
                foreach (byte[] data in tcpPacketBufferWindow.Values)
                {
                    this.fileStream.Write(data, 0, data.Length);
                }
                this.fileStream.Flush();
            }
            catch (Exception ex) {
                if (fileStream != null)
                {
                    parentAssemblerList.PacketHandler.OnAnomalyDetected("Error writing final data to file \"" + fileStream.Name + "\".\n" + ex.Message);
                }
                else
                {
                    parentAssemblerList.PacketHandler.OnAnomalyDetected("Error writing final data to file \"" + this.filename + "\".\n" + ex.Message);
                }
            }
            tcpPacketBufferWindow.Clear();
            parentAssemblerList.Remove(this, false);
            string destinationPath = GetFilePath(false);

            //I need to create the directory here since the file might either be moved to this located or a new file will be created there from a stream
            string directoryName = destinationPath.Substring(0, destinationPath.Length - this.filename.Length);

            if (this.fileStreamType != FileStreamTypes.HttpPostMimeMultipartFormData && !System.IO.Directory.Exists(directoryName))
            {
                try {
                    System.IO.Directory.CreateDirectory(directoryName);
                }
                catch (Exception e) {
                    parentAssemblerList.PacketHandler.OnAnomalyDetected("Error creating directory \"" + directoryName + "\".\n" + e.Message);
                    //parentAssemblerList.PacketHandler.ParentForm.ShowError("Error creating directory \""+directoryName+"\".\n"+e.Message);
                }
            }

            if (System.IO.File.Exists(destinationPath))
            {
                try {
                    System.IO.File.Delete(destinationPath);
                }
                catch (Exception e) {
                    parentAssemblerList.PacketHandler.OnAnomalyDetected("Error deleting file \"" + destinationPath + "\" (tried to replace it)");
                    //parentAssemblerList.PacketHandler.ParentForm.ShowError("Error deleting file \""+destinationPath+"\" (tried to replace it)");
                }
            }

            //do some special fixes such as un-chunk data or decompress compressed data
            if (this.fileStreamType == FileStreamTypes.HttpGetChunked || (parentAssemblerList.DecompressGzipStreams && this.contentEncoding == Packets.HttpPacket.ContentEncodings.Gzip) || this.contentEncoding == Packets.HttpPacket.ContentEncodings.Deflate)
            {
                this.fileStream.Position = 0;//move to fileStream start since it needs to be read

                if (this.fileStreamType == FileStreamTypes.HttpGetChunked && (parentAssemblerList.DecompressGzipStreams && this.contentEncoding == Packets.HttpPacket.ContentEncodings.Gzip))
                {
                    using (DeChunkedDataStream deChunkedStream = new DeChunkedDataStream(this.fileStream)) {
                        using (System.IO.Compression.GZipStream decompressedStream = new System.IO.Compression.GZipStream(deChunkedStream, System.IO.Compression.CompressionMode.Decompress)) {
                            try {
                                this.WriteStreamToFile(decompressedStream, destinationPath);
                            }
                            catch (Exception e) {
                                this.parentAssemblerList.PacketHandler.OnAnomalyDetected("Error: Cannot write to file " + destinationPath + " (" + e.Message + ")");
                                //this.parentAssemblerList.PacketHandler.ParentForm.ShowError("Error: Cannot write to file "+destinationPath+" ("+e.Message+")");
                            }
                            decompressedStream.Close();
                        }
                        deChunkedStream.Close();
                    }
                }
                else if (this.fileStreamType == FileStreamTypes.HttpGetChunked && this.contentEncoding == Packets.HttpPacket.ContentEncodings.Deflate)
                {
                    using (DeChunkedDataStream deChunkedStream = new DeChunkedDataStream(this.fileStream)) {
                        using (System.IO.Compression.DeflateStream decompressedStream = new System.IO.Compression.DeflateStream(deChunkedStream, System.IO.Compression.CompressionMode.Decompress)) {
                            try {
                                this.WriteStreamToFile(decompressedStream, destinationPath);
                            }
                            catch (Exception e) {
                                this.parentAssemblerList.PacketHandler.OnAnomalyDetected("Error: Cannot write to file " + destinationPath + " (" + e.Message + ")");
                                //this.parentAssemblerList.PacketHandler.ParentForm.ShowError("Error: Cannot write to file "+destinationPath+" ("+e.Message+")");
                            }

                            decompressedStream.Close();
                        }
                        deChunkedStream.Close();
                    }
                }
                else if (this.fileStreamType == FileStreamTypes.HttpGetChunked)
                {
                    using (DeChunkedDataStream deChunkedStream = new DeChunkedDataStream(this.fileStream)) {
                        try {
                            this.WriteStreamToFile(deChunkedStream, destinationPath);
                        }
                        catch (Exception e) {
                            this.parentAssemblerList.PacketHandler.OnAnomalyDetected("Error: Cannot write to file " + destinationPath + " (" + e.Message + ")");
                            //this.parentAssemblerList.PacketHandler.ParentForm.ShowError("Error: Cannot write to file "+destinationPath+" ("+e.Message+")");
                        }
                        deChunkedStream.Close();
                    }
                }
                else
                {
                    using (System.IO.Compression.GZipStream decompressedStream = new System.IO.Compression.GZipStream(this.fileStream, System.IO.Compression.CompressionMode.Decompress)) {
                        try {
                            this.WriteStreamToFile(decompressedStream, destinationPath);
                        }
                        catch (Exception e) {
                            this.parentAssemblerList.PacketHandler.OnAnomalyDetected("Error: Cannot write to file " + destinationPath + " (" + e.Message + ")");
                            //this.parentAssemblerList.PacketHandler.ParentForm.ShowError("Error: Cannot write to file "+destinationPath+" ("+e.Message+")");
                        }
                        decompressedStream.Close();
                    }
                }

                this.fileStream.Close();
                System.IO.File.Delete(GetFilePath(true));//delete the temp file
            }
            else if (this.fileStreamType == FileStreamTypes.HttpPostMimeMultipartFormData)
            {
                Mime.UnbufferedReader mimeReader = new PacketParser.Mime.UnbufferedReader(this.fileStream);

                List <Mime.MultipartPart> parts = new List <PacketParser.Mime.MultipartPart>();
                foreach (Mime.MultipartPart part in Mime.PartBuilder.GetParts(mimeReader, this.Details))
                {
                    parts.Add(part);
                }

                this.parentAssemblerList.PacketHandler.ExtractMultipartFormData(parts, sourceHost, destinationHost, timestamp, this.initialFrameNumber, "TCP " + sourcePort, "TCP " + destinationPort, ApplicationLayerProtocol.Unknown);

                foreach (Mime.MultipartPart part in parts)
                {
                    if (part.Attributes["filename"] != null && part.Attributes["filename"].Length > 0 && part.Data != null && part.Data.Length > 0)
                    {
                        //we have a file!
                        string mimeFileLocation = part.Attributes["filename"];
                        if (mimeFileLocation.Contains("/"))
                        {
                            mimeFileLocation = mimeFileLocation.Substring(0, mimeFileLocation.LastIndexOf('/'));
                        }
                        if (mimeFileLocation.Contains("\\"))
                        {
                            mimeFileLocation = mimeFileLocation.Substring(0, mimeFileLocation.LastIndexOf('\\'));
                        }
                        string mimeFileName = part.Attributes["filename"];
                        if (mimeFileName.Contains("/") && mimeFileName.Length > mimeFileName.LastIndexOf('/') + 1)
                        {
                            mimeFileName = mimeFileName.Substring(mimeFileName.LastIndexOf('/') + 1);
                        }
                        if (mimeFileName.Contains("\\") && mimeFileName.Length > mimeFileName.LastIndexOf('\\') + 1)
                        {
                            mimeFileName = mimeFileName.Substring(mimeFileName.LastIndexOf('\\') + 1);
                        }


                        using (FileStreamAssembler partAssembler = new FileStreamAssembler(this.parentAssemblerList, this.sourceHost, this.sourcePort, this.destinationHost, this.destinationPort, this.tcpTransfer, FileStreamTypes.HttpPostMimeFileData, mimeFileName, mimeFileLocation, part.Attributes["filename"], this.initialFrameNumber, this.timestamp)) {
                            this.parentAssemblerList.Add(partAssembler);
                            partAssembler.FileContentLength         = part.Data.Length;
                            partAssembler.FileSegmentRemainingBytes = part.Data.Length;
                            if (partAssembler.TryActivate())
                            {
                                partAssembler.AddData(part.Data, 0);
                            }
                        }

                        /*
                         * FixFilenameAndLocation(ref mimeFileName, ref mimeFileLocation);
                         * string mimeFilePath=GetFilePath(false, this.tcpTransfer, this.sourceHost.IPAddress, this.destinationHost.IPAddress, this.sourcePort, this.destinationPort, this.fileStreamType, mimeFileLocation, mimeFileName, this.parentAssemblerList);
                         * Mime.ByteArrayStream partDataStream=new PacketParser.Mime.ByteArrayStream(part.Data, 0);
                         * pare
                         * this.WriteStreamToFile(partDataStream, mimeFilePath);
                         * try {
                         *  ReconstructedFile completedFile=new ReconstructedFile(mimeFilePath, sourceHost, destinationHost, sourcePort, destinationPort, tcpTransfer, fileStreamType, "boundary="+details, this.initialFrameNumber, this.timestamp);
                         *  parentAssemblerList.PacketHandler.AddReconstructedFile(completedFile);
                         *  //parentAssemblerList.PacketHandler.ParentForm.ShowReconstructedFile(completedFile);
                         * }
                         * catch(Exception e) {
                         *  this.parentAssemblerList.PacketHandler.OnAnomalyDetected("Error creating reconstructed file: "+e.Message);
                         * }*/
                    }
                }
                this.fileStream.Close();
                System.IO.File.Delete(GetFilePath(true));
            }
            else  //files which are already completed can simply be moved to their final destination
            {
                if (this.fileStream != null)
                {
                    this.fileStream.Close();
                }
                try {
                    string tmpPath = GetFilePath(true);
                    if (System.IO.File.Exists(tmpPath))
                    {
                        System.IO.File.Move(tmpPath, destinationPath);
                    }
                }
                catch (Exception e) {
                    this.parentAssemblerList.PacketHandler.OnAnomalyDetected("Error moving file \"" + GetFilePath(true) + "\" to \"" + destinationPath + "\". " + e.Message);
                }
            }
            if (System.IO.File.Exists(destinationPath))
            {
                try {
                    ReconstructedFile completedFile = new ReconstructedFile(destinationPath, sourceHost, destinationHost, sourcePort, destinationPort, tcpTransfer, fileStreamType, details, this.initialFrameNumber, this.timestamp);
                    parentAssemblerList.PacketHandler.AddReconstructedFile(completedFile);
                    //parentAssemblerList.PacketHandler.ParentForm.ShowReconstructedFile(completedFile);
                }
                catch (Exception e) {
                    this.parentAssemblerList.PacketHandler.OnAnomalyDetected("Error creating reconstructed file: " + e.Message);
                }
            }
        }