Ejemplo n.º 1
0
        public Email(System.IO.MemoryStream emailMimeStream, PacketHandler mainPacketHandler, Packets.TcpPacket tcpPacket, bool transferIsClientToServer, NetworkTcpSession tcpSession, ApplicationLayerProtocol protocol, FileTransfer.FileStreamAssembler.FileAssmeblyRootLocation fileAssmeblyRootLocation = FileTransfer.FileStreamAssembler.FileAssmeblyRootLocation.destination)
        {
            Mime.UnbufferedReader ur = new PacketParser.Mime.UnbufferedReader(emailMimeStream);
            this.MainPacketHandler = mainPacketHandler;
            this.protocol          = protocol;
            if (this.protocol == ApplicationLayerProtocol.Smtp)
            {
                this.fileTransferProtocol = FileTransfer.FileStreamTypes.SMTP;
            }
            else if (this.protocol == ApplicationLayerProtocol.Pop3)
            {
                this.fileTransferProtocol = FileTransfer.FileStreamTypes.POP3;
            }
            else if (this.protocol == ApplicationLayerProtocol.Imap)
            {
                this.fileTransferProtocol = FileTransfer.FileStreamTypes.IMAP;
            }
            //this.reassembleFileAtSourceHost = reassembleFileAtSourceHost;
            this.fileAssmeblyRootLocation = fileAssmeblyRootLocation;

            this.fiveTuple = tcpSession.Flow.FiveTuple;
            this.transferIsClientToServer = transferIsClientToServer;

            this.attachments = new List <FileTransfer.ReconstructedFile>();
            this.from        = null;
            this.to          = null;
            this.subject     = null;
            this.messageId   = null;
            this.date        = null;//Date: Fri, 1 Aug 2003 14:17:51 -0700
            Encoding customEncoding = null;

            System.Collections.Specialized.NameValueCollection rootAttributes = null;
            bool messageSentToPacketHandler = false;

            foreach (Mime.MultipartPart multipart in Mime.PartBuilder.GetParts(ur))  //I might need to add "ref customEncoding" as a parameter here
            {
                if (rootAttributes == null)
                {
                    from           = multipart.Attributes["From"];
                    to             = multipart.Attributes["To"];
                    subject        = multipart.Attributes["Subject"];
                    messageId      = multipart.Attributes["Message-ID"];
                    date           = multipart.Attributes["Date"];
                    rootAttributes = multipart.Attributes;
                }
                if (multipart.Attributes["charset"] != null)
                {
                    try {
                        customEncoding = Encoding.GetEncoding(multipart.Attributes["charset"]);
                    }
                    catch { }
                }
                this.parseMultipart(multipart, rootAttributes, tcpPacket, ref messageSentToPacketHandler, customEncoding, from, to, subject, messageId);
            }

            //create an .eml file with the whole DATA portion
            string emlFilename = null;

            if (subject != null && subject.Length > 3)
            {
                emlFilename = Utils.StringManglerUtil.ConvertToFilename(subject, 10);

                /*
                 * try {
                 *  System.IO.FileInfo fi = new System.IO.FileInfo(subject.Substring(0, 10));
                 *  emlFilename = subject.Substring(0, 10);
                 * }
                 * catch {
                 *  emlFilename = Utils.StringManglerUtil.ConvertToFilename(subject, 10);
                 * }
                 */
            }
            if (emlFilename == null || emlFilename.Length == 0)
            {
                if (messageId != null && messageId.Length > 3)
                {
                    emlFilename = Utils.StringManglerUtil.ConvertToFilename(messageId, 10);
                }
                else
                {
                    emlFilename = "message_" + tcpSession.GetHashCode().ToString("X8");
                }
            }


            emlFilename = emlFilename + ".eml";

            /*
             * string extendedFileId = tcpSession.GetHashCode().ToString();
             * if (messageId != null && messageId.Length > 0)
             *  extendedFileId = messageId;
             */
            if (rootAttributes != null)
            {
                string extendedFileId = GetFileId(rootAttributes);
                using (FileTransfer.FileStreamAssembler assembler = new FileTransfer.FileStreamAssembler(MainPacketHandler.FileStreamAssemblerList, this.fiveTuple, this.transferIsClientToServer, this.fileTransferProtocol, emlFilename, "/", emailMimeStream.Length, emailMimeStream.Length, this.protocol.ToString() + " transcript From: " + from + " To: " + to + " Subject: " + subject, extendedFileId, tcpPacket.ParentFrame.FrameNumber, tcpPacket.ParentFrame.Timestamp, this.fileAssmeblyRootLocation)) {
                    if (assembler.TryActivate())
                    {
                        assembler.FileReconstructed += MainPacketHandler.OnMessageAttachmentDetected;
                        assembler.FileReconstructed += Assembler_FileReconstructed;
                        assembler.AddData(emailMimeStream.ToArray(), tcpPacket.SequenceNumber);
                        //assembler.FinishAssembling();
                    }
                    else
                    {
                        assembler.Clear();
                        assembler.FinishAssembling();
                    }
                }
            }
        }
Ejemplo n.º 2
0
        private void parseMultipart(Mime.MultipartPart multipart, System.Collections.Specialized.NameValueCollection rootAttributes, Packets.TcpPacket tcpPacket, /*NetworkHost sourceHost, NetworkHost destinationHost, */ ref bool messageSentToPacketHandler, Encoding customEncoding, string from = null, string to = null, string subject = null, string messageId = null)
        {
            if (multipart.Attributes.Count > 0)
            {
                this.MainPacketHandler.OnParametersDetected(new PacketParser.Events.ParametersEventArgs(tcpPacket.ParentFrame.FrameNumber, this.fiveTuple, this.transferIsClientToServer, multipart.Attributes, tcpPacket.ParentFrame.Timestamp, this.protocol + " packet"));
            }
            string contentType = multipart.Attributes["Content-Type"];
            string charset     = multipart.Attributes["charset"];

            if (charset != null && charset.Length > 0)
            {
                try {
                    customEncoding = System.Text.Encoding.GetEncoding(charset);
                }
                catch { };
            }
            bool   attachment         = false;
            string contentDisposition = multipart.Attributes["Content-Disposition"];

            if (contentDisposition != null && contentDisposition.Contains("attachment"))
            {
                attachment = true;
            }
            if (contentType != null && (
                    contentType.Equals("multipart/mixed", StringComparison.InvariantCultureIgnoreCase) ||
                    contentType.Equals("multipart/alternative", StringComparison.InvariantCultureIgnoreCase) ||
                    contentType.Equals("multipart/related", StringComparison.InvariantCultureIgnoreCase)
                    ))
            {
                /**
                 * There are a variety of ways to attach images to an email.
                 * Content types are used to identify what is contained by each part of the email.
                 * As well as the various types of image, and text/plain and text/html for the text and HTML parts,
                 * there are various containers:
                 * multipart/alternative as a container for parts containing the same information in different formats,
                 * multipart/related as a container for parts that are linked in some way, and
                 * multipart/mixed as a general container.
                 **/

                //Mime.MultipartPart mimeMultipart = new Mime.MultipartPart(multipart.Data);
                System.IO.Stream      mixedStream = new System.IO.MemoryStream(multipart.Data);
                Mime.UnbufferedReader mixedReader = new PacketParser.Mime.UnbufferedReader(mixedStream);
                string boundary = mixedReader.ReadLine(200, customEncoding);
                if (boundary != null && boundary.Length == 0)//there was an empty line before the boundary, try to read it again
                {
                    boundary = mixedReader.ReadLine(200, customEncoding);
                }
                if (boundary != null && boundary.StartsWith("--"))
                {
                    boundary = boundary.Substring(2);
                    List <Mime.MultipartPart> innerParts = new List <Mime.MultipartPart>(Mime.PartBuilder.GetParts(mixedReader, boundary, customEncoding));
                    foreach (Mime.MultipartPart innerPart in innerParts)
                    {
                        //a bit of recursion here
                        this.parseMultipart(innerPart, rootAttributes, tcpPacket, ref messageSentToPacketHandler, customEncoding, from, to, subject, messageId);
                    }
                }
            }
            else if (!attachment && contentType == null || !attachment && contentType != null && (contentType.Equals("text/plain", StringComparison.InvariantCultureIgnoreCase) || !messageSentToPacketHandler && contentType.Equals("text/html", StringComparison.InvariantCultureIgnoreCase)))
            {
                //print the data as text
                //string textData = null;
                byte[] textDataBytes = null;
                if (multipart.Attributes["Content-Transfer-Encoding"] == "quoted-printable")
                {
                    textDataBytes = Utils.ByteConverter.ReadQuotedPrintable(multipart.Data).ToArray();
                    //textData = Utils.ByteConverter.ReadString();
                }
                else if (multipart.Attributes["Content-Transfer-Encoding"] == "base64")
                {
                    textDataBytes = System.Convert.FromBase64String(Utils.ByteConverter.ReadString(multipart.Data));
                    //textData = Utils.ByteConverter.ReadString();
                }
                else
                {
                    textDataBytes = multipart.Data;
                    //textData = Utils.ByteConverter.ReadString();
                }
                string textData = null;
                if (customEncoding == null)
                {
                    textData = Utils.ByteConverter.ReadString(textDataBytes);
                }
                else
                {
                    textData = customEncoding.GetString(textDataBytes);
                }
                if (textData != null)
                {
                    Dictionary <string, string> aggregatedAttributeDictionary = new Dictionary <string, string>();
                    System.Collections.Specialized.NameValueCollection aggregatedAttributes = new System.Collections.Specialized.NameValueCollection();
                    aggregatedAttributes.Add(rootAttributes);
                    foreach (string name in rootAttributes.Keys)
                    {
                        aggregatedAttributeDictionary.Add(name, rootAttributes[name]);
                    }
                    foreach (string name in multipart.Attributes)
                    {
                        if (!aggregatedAttributeDictionary.ContainsKey(name))
                        {
                            aggregatedAttributeDictionary.Add(name, multipart.Attributes[name]);
                            aggregatedAttributes.Add(name, multipart.Attributes[name]);
                        }
                    }
                    if (textData.Length > 0)
                    {
                        if (this.transferIsClientToServer)
                        {
                            this.MainPacketHandler.OnMessageDetected(new PacketParser.Events.MessageEventArgs(this.protocol, this.fiveTuple.ClientHost, this.fiveTuple.ServerHost, tcpPacket.ParentFrame.FrameNumber, tcpPacket.ParentFrame.Timestamp, from, to, subject, textData, customEncoding, aggregatedAttributes));
                        }
                        else
                        {
                            this.MainPacketHandler.OnMessageDetected(new PacketParser.Events.MessageEventArgs(this.protocol, this.fiveTuple.ServerHost, this.fiveTuple.ClientHost, tcpPacket.ParentFrame.FrameNumber, tcpPacket.ParentFrame.Timestamp, from, to, subject, textData, customEncoding, aggregatedAttributes));
                        }
                    }
                    messageSentToPacketHandler = true;
                    if (contentType != null && contentType.Equals("text/html", StringComparison.InvariantCultureIgnoreCase))
                    {
                        //re-parse the multipart so that it is also extracted to an HTML file
                        this.parseMultipart(multipart, rootAttributes, tcpPacket, ref messageSentToPacketHandler, customEncoding, from, to, subject, messageId);
                    }
                }
            }
            else
            {
                //store the stuff to disk
                string filename = multipart.Attributes["name"];
                if (filename == null || filename.Length == 0)
                {
                    filename = multipart.Attributes["filename"];
                }
                if (filename == null || filename.Length == 0)
                {
                    if (subject != null && subject.Length > 3)
                    {
                        filename = Utils.StringManglerUtil.ConvertToFilename(subject, 10);
                    }
                    else if (messageId != null && messageId.Length > 3)
                    {
                        filename = Utils.StringManglerUtil.ConvertToFilename(messageId, 10);
                    }
                    if (filename == null || filename.Length < 3)
                    {
                        filename = "email_" + (multipart.GetHashCode() % 1000);
                    }

                    string extension = Utils.StringManglerUtil.GetExtension(contentType);
                    if (extension == null || extension.Length < 1)
                    {
                        extension = "dat";
                    }
                    filename = filename + "." + extension;
                }

                List <byte> fileData = new List <byte>();
                if (multipart.Attributes["Content-Transfer-Encoding"] == "base64")
                {
                    //decode base64 stuff
                    int index = 0;
                    while (index < multipart.Data.Length)
                    {
                        string base64 = Utils.ByteConverter.ReadLine(multipart.Data, ref index);
                        if (base64 == null && index < multipart.Data.Length)
                        {
                            //read the remaining data
                            base64 = Utils.ByteConverter.ReadString(multipart.Data, index, multipart.Data.Length - index, false, false);
                            index  = multipart.Data.Length;
                        }
#if DEBUG
                        if (base64 == null)
                        {
                            System.Diagnostics.Debugger.Break();
                        }
#endif
                        //if (base64 != null && base64.Length > 0) {
                        try {
                            fileData.AddRange(Convert.FromBase64String(base64));
                        }
                        catch (FormatException e) { }
                    }
                }
                else if (multipart.Attributes["Content-Transfer-Encoding"] == "quoted-printable")
                {
                    //must be decoded according to http://www.ietf.org/rfc/rfc2045.txt
                    fileData = Utils.ByteConverter.ReadQuotedPrintable(multipart.Data);
                }
                else
                {
                    //Add the raw data
                    fileData.AddRange(multipart.Data);
                }

                if (fileData != null && fileData.Count > 0)
                {
                    string fileId = GetFileId(rootAttributes);

                    FileTransfer.FileStreamAssembler assembler = new FileTransfer.FileStreamAssembler(MainPacketHandler.FileStreamAssemblerList, this.fiveTuple, this.transferIsClientToServer, this.fileTransferProtocol, filename, "/", fileData.Count, fileData.Count, "E-mail From: " + from + " To: " + to + " Subject: " + subject, fileId, tcpPacket.ParentFrame.FrameNumber, tcpPacket.ParentFrame.Timestamp, this.fileAssmeblyRootLocation);
                    if (assembler.TryActivate())
                    {
                        assembler.FileReconstructed += MainPacketHandler.OnMessageAttachmentDetected;
                        assembler.AddData(fileData.ToArray(), tcpPacket.SequenceNumber);
                        //assembler.FinishAssembling();
                    }
                    else
                    {
                        assembler.Clear();
                        assembler.FinishAssembling();
                    }
                }
            }
        }
Ejemplo n.º 3
0
        public Email(System.IO.MemoryStream emailMimeStream, PacketHandler mainPacketHandler, Packets.TcpPacket tcpPacket, bool transferIsClientToServer, NetworkTcpSession tcpSession, ApplicationLayerProtocol protocol, FileTransfer.FileStreamAssembler.FileAssmeblyRootLocation fileAssmeblyRootLocation = FileTransfer.FileStreamAssembler.FileAssmeblyRootLocation.destination)
        {
            SharedUtils.Logger.Log("Extracting Email from MIME data in " + tcpPacket.ParentFrame.ToString(), SharedUtils.Logger.EventLogEntryType.Information);
            Mime.UnbufferedReader ur = new PacketParser.Mime.UnbufferedReader(emailMimeStream);
            this.MainPacketHandler = mainPacketHandler;
            this.protocol          = protocol;
            if (this.protocol == ApplicationLayerProtocol.Smtp)
            {
                this.fileTransferProtocol = FileTransfer.FileStreamTypes.SMTP;
            }
            else if (this.protocol == ApplicationLayerProtocol.Pop3)
            {
                this.fileTransferProtocol = FileTransfer.FileStreamTypes.POP3;
            }
            else if (this.protocol == ApplicationLayerProtocol.Imap)
            {
                this.fileTransferProtocol = FileTransfer.FileStreamTypes.IMAP;
            }
            //this.reassembleFileAtSourceHost = reassembleFileAtSourceHost;
            this.fileAssmeblyRootLocation = fileAssmeblyRootLocation;

            this.fiveTuple = tcpSession.Flow.FiveTuple;
            this.transferIsClientToServer = transferIsClientToServer;

            this.attachments = new List <FileTransfer.ReconstructedFile>();
            this.from        = null;
            this.to          = null;
            this.subject     = null;
            this.messageId   = null;
            this.date        = null;//Date: Fri, 1 Aug 2003 14:17:51 -0700
            Encoding customEncoding = null;

            this.RootAttributes = null;
            bool messageSentToPacketHandler = false;

            //The open source .NET implementation Mono can crash if the strings contain Unicode chracters
            //see KeePass bug: https://sourceforge.net/p/keepass/feature-requests/2254/
            foreach (Mime.MultipartPart multipart in Mime.PartBuilder.GetParts(ur, Utils.SystemHelper.IsRunningOnMono(), null))  //I might need to add "ref customEncoding" as a parameter here

            {
                SharedUtils.Logger.Log("Extracting MIME part with attributes \"" + String.Join(",", multipart.Attributes.AllKeys) + "\" in " + tcpPacket.ParentFrame.ToString(), SharedUtils.Logger.EventLogEntryType.Information);

                if (this.RootAttributes == null)
                {
                    from                = multipart.Attributes["From"];
                    to                  = multipart.Attributes["To"];
                    subject             = multipart.Attributes["Subject"];
                    messageId           = multipart.Attributes["Message-ID"];
                    date                = multipart.Attributes["Date"];
                    this.RootAttributes = multipart.Attributes;
                }
                if (multipart.Attributes["charset"] != null)
                {
                    try {
                        customEncoding = Encoding.GetEncoding(multipart.Attributes["charset"]);
                    }
                    catch (Exception e) {
                        SharedUtils.Logger.Log("Exception getting encoding for charset \"" + multipart.Attributes["charset"] + "\". " + e.ToString(), SharedUtils.Logger.EventLogEntryType.Warning);
                    }
                }

                this.parseMultipart(multipart, this.RootAttributes, tcpPacket, ref messageSentToPacketHandler, customEncoding, emailMimeStream.Length, from, to, subject, messageId);
            }

            if (!messageSentToPacketHandler && from != null && to != null)
            {
                //send message to PacketHandler with force
                if (this.transferIsClientToServer)
                {
                    this.MainPacketHandler.OnMessageDetected(new PacketParser.Events.MessageEventArgs(this.protocol, this.fiveTuple.ClientHost, this.fiveTuple.ServerHost, tcpPacket.ParentFrame.FrameNumber, tcpPacket.ParentFrame.Timestamp, from, to, subject, "", customEncoding, this.RootAttributes, emailMimeStream.Length));
                }
                else
                {
                    this.MainPacketHandler.OnMessageDetected(new PacketParser.Events.MessageEventArgs(this.protocol, this.fiveTuple.ServerHost, this.fiveTuple.ClientHost, tcpPacket.ParentFrame.FrameNumber, tcpPacket.ParentFrame.Timestamp, from, to, subject, "", customEncoding, this.RootAttributes, emailMimeStream.Length));
                }

                messageSentToPacketHandler = true;
            }

            //create an .eml file with the whole DATA portion
            string emlFilename = null;

            if (subject != null && subject.Length > 3)
            {
                emlFilename = Utils.StringManglerUtil.ConvertToFilename(subject, 10);
            }
            if (emlFilename == null || emlFilename.Length == 0)
            {
                if (messageId != null && messageId.Length > 3)
                {
                    emlFilename = Utils.StringManglerUtil.ConvertToFilename(messageId, 10);
                }
                else
                {
                    emlFilename = "message_" + tcpSession.GetHashCode().ToString("X8");
                }
            }


            emlFilename = emlFilename + ".eml";

            if (this.RootAttributes != null)
            {
                string extendedFileId = GetMessageId(this.RootAttributes);
                using (FileTransfer.FileStreamAssembler assembler = new FileTransfer.FileStreamAssembler(MainPacketHandler.FileStreamAssemblerList, this.fiveTuple, this.transferIsClientToServer, this.fileTransferProtocol, emlFilename, "/", emailMimeStream.Length, emailMimeStream.Length, this.protocol.ToString() + " transcript From: " + from + " To: " + to + " Subject: " + subject, extendedFileId, tcpPacket.ParentFrame.FrameNumber, tcpPacket.ParentFrame.Timestamp, this.fileAssmeblyRootLocation)) {
                    if (assembler.TryActivate())
                    {
                        assembler.FileReconstructed += this.MainPacketHandler.OnMessageAttachmentDetected;
                        assembler.FileReconstructed += this.Assembler_FileReconstructed;
                        SharedUtils.Logger.Log("Adding emailMimeStream bytes: " + emailMimeStream.Length, SharedUtils.Logger.EventLogEntryType.Information);
                        assembler.AddData(emailMimeStream.ToArray(), tcpPacket.SequenceNumber);
                    }
                    else
                    {
                        SharedUtils.Logger.Log("Unable to activate email assembler", SharedUtils.Logger.EventLogEntryType.Warning);
                        assembler.Clear();
                        assembler.FinishAssembling();
                    }
                }
            }
        }
Ejemplo n.º 4
0
        public int ExtractData(NetworkTcpSession tcpSession, NetworkHost sourceHost, NetworkHost destinationHost, IEnumerable <PacketParser.Packets.AbstractPacket> packetList)
        {
            SmtpSession smtpSession;

            if (this.smtpSessionList.ContainsKey(tcpSession))
            {
                smtpSession = this.smtpSessionList[tcpSession];
            }
            else
            {
                smtpSession = new SmtpSession();
                this.smtpSessionList.Add(tcpSession, smtpSession);
            }

            Packets.TcpPacket  tcpPacket  = null;
            Packets.SmtpPacket smtpPacket = null;

            foreach (Packets.AbstractPacket p in packetList)
            {
                if (p.GetType() == typeof(Packets.TcpPacket))
                {
                    tcpPacket = (Packets.TcpPacket)p;
                }
                else if (p.GetType() == typeof(Packets.SmtpPacket))
                {
                    smtpPacket = (Packets.SmtpPacket)p;
                }
            }



            if (smtpPacket != null)
            {
                if (smtpPacket.ClientToServer)
                {
                    if (smtpSession.State == SmtpSession.SmtpState.Username)
                    {
                        string base64Username = smtpPacket.ReadLine().Trim();
                        try {
                            byte[] usernameBytes = System.Convert.FromBase64String(base64Username);
                            smtpSession.Username = System.Text.ASCIIEncoding.ASCII.GetString(usernameBytes);
                        }
                        catch (FormatException e) { }
                    }
                    else if (smtpSession.State == SmtpSession.SmtpState.Password)
                    {
                        string base64Password = smtpPacket.ReadLine().Trim();
                        try {
                            byte[] passwordBytes = System.Convert.FromBase64String(base64Password);
                            smtpSession.Password = System.Text.ASCIIEncoding.ASCII.GetString(passwordBytes);
                        }
                        catch (FormatException e) { }
                    }
                    else if (smtpSession.State == SmtpSession.SmtpState.Data)
                    {
                        //write data to file until we receive "\n.\n" could also be \r\n.\r\n
                        smtpSession.AddData(smtpPacket.ParentFrame.Data, smtpPacket.PacketStartIndex, smtpPacket.PacketLength);
                        //check if state has transitioned over to footer
                        if (smtpSession.State == SmtpSession.SmtpState.Footer)
                        {
                            Mime.UnbufferedReader ur = new PacketParser.Mime.UnbufferedReader(smtpSession.DataStream);
                            string from      = null;
                            string to        = null;
                            string subject   = null;
                            string messageId = null;
                            System.Collections.Specialized.NameValueCollection rootAttributes = null;
                            foreach (Mime.MultipartPart multipart in Mime.PartBuilder.GetParts(ur))
                            {
                                if (rootAttributes == null)
                                {
                                    from           = multipart.Attributes["From"];
                                    to             = multipart.Attributes["To"];
                                    subject        = multipart.Attributes["Subject"];
                                    messageId      = multipart.Attributes["Message-ID"];
                                    rootAttributes = multipart.Attributes;
                                }

                                base.MainPacketHandler.OnParametersDetected(new PacketParser.Events.ParametersEventArgs(smtpPacket.ParentFrame.FrameNumber, sourceHost, destinationHost, "TCP " + tcpPacket.SourcePort, "TCP " + tcpPacket.DestinationPort, multipart.Attributes, tcpPacket.ParentFrame.Timestamp, "SMTP packet"));

                                string   contentType = multipart.Attributes["Content-Type"];
                                string   charset     = multipart.Attributes["charset"];
                                Encoding encoding    = null;
                                if (charset != null && charset.Length > 0)
                                {
                                    try {
                                        encoding = System.Text.Encoding.GetEncoding(charset);
                                    }
                                    catch { };
                                }
                                bool   attachment         = false;
                                string contentDisposition = multipart.Attributes["Content-Disposition"];
                                if (contentDisposition != null && contentDisposition.Contains("attachment"))
                                {
                                    attachment = true;
                                }
                                if (!attachment && contentType == null || contentType.Equals("text/plain", StringComparison.InvariantCultureIgnoreCase))
                                {
                                    //print the data as text
                                    //string textData = null;
                                    byte[] textDataBytes = null;
                                    if (multipart.Attributes["Content-Transfer-Encoding"] == "quoted-printable")
                                    {
                                        textDataBytes = Utils.ByteConverter.ReadQuotedPrintable(multipart.Data).ToArray();
                                        //textData = Utils.ByteConverter.ReadString();
                                    }
                                    else if (multipart.Attributes["Content-Transfer-Encoding"] == "base64")
                                    {
                                        textDataBytes = System.Convert.FromBase64String(Utils.ByteConverter.ReadString(multipart.Data));
                                        //textData = Utils.ByteConverter.ReadString();
                                    }
                                    else
                                    {
                                        textDataBytes = multipart.Data;
                                        //textData = Utils.ByteConverter.ReadString();
                                    }
                                    string textData = null;
                                    if (encoding == null)
                                    {
                                        textData = Utils.ByteConverter.ReadString(textDataBytes);
                                    }
                                    else
                                    {
                                        textData = encoding.GetString(textDataBytes);
                                    }
                                    if (textData != null)
                                    {
                                        //System.Collections.Specialized.NameValueCollection tmpCol=new System.Collections.Specialized.NameValueCollection();
                                        //tmpCol.Add("e-mail", textData);
                                        //base.MainPacketHandler.OnParametersDetected(new PacketParser.Events.ParametersEventArgs(smtpPacket.ParentFrame.FrameNumber, sourceHost, destinationHost, "TCP "+tcpPacket.SourcePort, "TCP "+tcpPacket.DestinationPort, tmpCol, tcpPacket.ParentFrame.Timestamp, "SMTP packet"));
                                        System.Collections.Specialized.NameValueCollection aggregatedAttributes = new System.Collections.Specialized.NameValueCollection();
                                        aggregatedAttributes.Add(rootAttributes);
                                        aggregatedAttributes.Add(multipart.Attributes);
                                        base.MainPacketHandler.OnMessageDetected(new PacketParser.Events.MessageEventArgs(ApplicationLayerProtocol.Smtp, sourceHost, destinationHost, smtpPacket.ParentFrame.FrameNumber, smtpPacket.ParentFrame.Timestamp, from, to, subject, textData, aggregatedAttributes));
                                    }
                                }
                                else
                                {
                                    //store the stuff to disk
                                    string filename = multipart.Attributes["name"];
                                    if (filename == null || filename.Length == 0)
                                    {
                                        filename = multipart.Attributes["filename"];
                                    }
                                    if (filename == null || filename.Length == 0)
                                    {
                                        if (subject != null && subject.Length > 3)
                                        {
                                            filename = Utils.StringManglerUtil.ConvertToFilename(subject, 10);
                                        }
                                        else if (messageId != null && messageId.Length > 3)
                                        {
                                            filename = Utils.StringManglerUtil.ConvertToFilename(messageId, 10);
                                        }
                                        if (filename == null || filename.Length < 3)
                                        {
                                            filename = "email_" + (multipart.GetHashCode() % 1000);
                                        }

                                        string extension = Utils.StringManglerUtil.GetExtension(contentType);
                                        if (extension == null || extension.Length < 1)
                                        {
                                            extension = "dat";
                                        }
                                        filename = filename + "." + extension;
                                    }
                                    //check if filename is encoded as '?CharacterSet?Enum(Q,B)?', for example '=?UTF-8?B?IE1ldGhvZA==?=' RFC2047

                                    /*
                                     * if (Mime.Rfc2047Parser.IsRfc2047String(filename)) {
                                     *  try {
                                     *      filename = Mime.Rfc2047Parser.ParseRfc2047String(filename);
                                     *  }
                                     *  catch (Exception) { }
                                     * }*/
                                    List <byte> fileData = new List <byte>();
                                    if (multipart.Attributes["Content-Transfer-Encoding"] == "base64")
                                    {
                                        //decode base64 stuff
                                        int index = 0;
                                        while (index < multipart.Data.Length)
                                        {
                                            string base64 = Utils.ByteConverter.ReadLine(multipart.Data, ref index);
                                            if (base64 == null && index < multipart.Data.Length)
                                            {
                                                //read the remaining data
                                                base64 = Utils.ByteConverter.ReadString(multipart.Data, index, multipart.Data.Length - index, false, false);
                                                index  = multipart.Data.Length;
                                            }
#if DEBUG
                                            if (base64 == null)
                                            {
                                                System.Diagnostics.Debugger.Break();
                                            }
#endif
                                            //if (base64 != null && base64.Length > 0) {
                                            try {
                                                fileData.AddRange(Convert.FromBase64String(base64));
                                            }
                                            catch (FormatException e) { }
                                        }
                                    }
                                    else if (multipart.Attributes["Content-Transfer-Encoding"] == "quoted-printable")
                                    {
                                        //must be decoded according to http://www.ietf.org/rfc/rfc2045.txt
                                        fileData = Utils.ByteConverter.ReadQuotedPrintable(multipart.Data);
                                    }
                                    else
                                    {
                                        //Add the raw data
                                        fileData.AddRange(multipart.Data);
                                    }

                                    if (fileData != null && fileData.Count > 0)
                                    {
                                        FileTransfer.FileStreamAssembler assembler = new FileTransfer.FileStreamAssembler(MainPacketHandler.FileStreamAssemblerList, sourceHost, tcpPacket.SourcePort, destinationHost, tcpPacket.DestinationPort, true, FileTransfer.FileStreamTypes.SMTP, filename, "/", fileData.Count, fileData.Count, "E-mail From: " + from + " To: " + to + " Subject: " + subject, filename, tcpPacket.ParentFrame.FrameNumber, tcpPacket.ParentFrame.Timestamp);
                                        if (assembler.TryActivate())
                                        {
                                            assembler.AddData(fileData.ToArray(), tcpPacket.SequenceNumber);
                                            //assembler.FinishAssembling();
                                        }
                                        else
                                        {
                                            assembler.Clear();
                                            assembler.FinishAssembling();
                                        }
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        foreach (KeyValuePair <string, string> requestCommandAndArgument in smtpPacket.RequestCommandsAndArguments)
                        {
                            if (requestCommandAndArgument.Key.Equals(SmtpPacket.ClientCommands.HELO.ToString(), StringComparison.InvariantCultureIgnoreCase))
                            {
                                string clientDomain = requestCommandAndArgument.Value;
                            }
                            else if (requestCommandAndArgument.Key.Equals(SmtpPacket.ClientCommands.EHLO.ToString(), StringComparison.InvariantCultureIgnoreCase))
                            {
                                string clientDomain = requestCommandAndArgument.Value;
                            }
                            else if (requestCommandAndArgument.Key.Equals(SmtpPacket.ClientCommands.AUTH.ToString(), StringComparison.InvariantCultureIgnoreCase))
                            {
                                if (requestCommandAndArgument.Value.ToUpper().Contains("LOGIN"))
                                {
                                    smtpSession.State = SmtpSession.SmtpState.AuthLogin;
                                }
                            }
                            else if (requestCommandAndArgument.Key.Equals(SmtpPacket.ClientCommands.MAIL.ToString(), StringComparison.InvariantCultureIgnoreCase))
                            {
                                if (requestCommandAndArgument.Value.StartsWith("FROM", StringComparison.InvariantCultureIgnoreCase))
                                {
                                    int colonIndex = requestCommandAndArgument.Value.IndexOf(':');
                                    if (colonIndex > 0 && requestCommandAndArgument.Value.Length > colonIndex + 1)
                                    {
                                        smtpSession.MailFrom = requestCommandAndArgument.Value.Substring(colonIndex + 1).Trim();
                                    }
                                }
                            }
                            else if (requestCommandAndArgument.Key.Equals(SmtpPacket.ClientCommands.RCPT.ToString(), StringComparison.InvariantCultureIgnoreCase))
                            {
                                if (requestCommandAndArgument.Value.StartsWith("TO", StringComparison.InvariantCultureIgnoreCase))
                                {
                                    int colonIndex = requestCommandAndArgument.Value.IndexOf(':');
                                    if (colonIndex > 0 && requestCommandAndArgument.Value.Length > colonIndex + 1)
                                    {
                                        smtpSession.AddRecipient(requestCommandAndArgument.Value.Substring(colonIndex + 1).Trim());
                                    }
                                }
                            }
                            else if (requestCommandAndArgument.Key.Equals(SmtpPacket.ClientCommands.DATA.ToString(), StringComparison.InvariantCultureIgnoreCase))
                            {
                                smtpSession.State = SmtpSession.SmtpState.Data;
                            }
#if DEBUG
                            base.MainPacketHandler.OnParametersDetected(new Events.ParametersEventArgs(tcpPacket.ParentFrame.FrameNumber, sourceHost, destinationHost, "TCP " + tcpPacket.SourcePort, "TCP " + tcpPacket.DestinationPort, smtpPacket.RequestCommandsAndArguments, tcpPacket.ParentFrame.Timestamp, "SMTP Request"));
#endif
                        }
                    }

                    /*}
                     * else if(smtpPacket.RequestCommand != null) {
                     *  if(smtpPacket.RequestCommand.Equals(SmtpPacket.ClientCommands.HELO.ToString(), StringComparison.InvariantCultureIgnoreCase)) {
                     *      string clientDomain = smtpPacket.RequestArgument;
                     *  }
                     *  else if(smtpPacket.RequestCommand.Equals(SmtpPacket.ClientCommands.EHLO.ToString(), StringComparison.InvariantCultureIgnoreCase)) {
                     *      string clientDomain = smtpPacket.RequestArgument;
                     *  }
                     *  else if(smtpPacket.RequestCommand.Equals(SmtpPacket.ClientCommands.AUTH.ToString(), StringComparison.InvariantCultureIgnoreCase)) {
                     *      if(smtpPacket.RequestArgument.ToUpper().Contains("LOGIN"))
                     *          smtpSession.State = SmtpSession.SmtpState.AuthLogin;
                     *  }
                     *  else if(smtpPacket.RequestCommand.Equals(SmtpPacket.ClientCommands.MAIL.ToString(), StringComparison.InvariantCultureIgnoreCase)) {
                     *      if(smtpPacket.RequestArgument.StartsWith("FROM", StringComparison.InvariantCultureIgnoreCase)) {
                     *          int colonIndex = smtpPacket.RequestArgument.IndexOf(':');
                     *          if(colonIndex>0 && smtpPacket.RequestArgument.Length > colonIndex+1)
                     *              smtpSession.MailFrom = smtpPacket.RequestArgument.Substring(colonIndex+1).Trim();
                     *      }
                     *  }
                     *  else if(smtpPacket.RequestCommand.Equals(SmtpPacket.ClientCommands.RCPT.ToString(), StringComparison.InvariantCultureIgnoreCase)) {
                     *      if(smtpPacket.RequestArgument.StartsWith("TO", StringComparison.InvariantCultureIgnoreCase)) {
                     *          int colonIndex = smtpPacket.RequestArgument.IndexOf(':');
                     *          if(colonIndex>0 && smtpPacket.RequestArgument.Length > colonIndex+1)
                     *              smtpSession.AddRecipient(smtpPacket.RequestArgument.Substring(colonIndex+1).Trim());
                     *      }
                     *  }
                     *  else if(smtpPacket.RequestCommand.Equals(SmtpPacket.ClientCommands.DATA.ToString(), StringComparison.InvariantCultureIgnoreCase)) {
                     *      smtpSession.State = SmtpSession.SmtpState.Data;
                     *  }
                     * }*/
                }
                else  //server to client
                {
                    foreach (KeyValuePair <int, string> replyCodeAndArgument in smtpPacket.Replies)
                    {
                        if (replyCodeAndArgument.Key == 334)  //AUTH LOGIN
                        {
                            if (replyCodeAndArgument.Value.Equals("VXNlcm5hbWU6"))
                            {
                                smtpSession.State = SmtpSession.SmtpState.Username;
                            }
                            else if (replyCodeAndArgument.Value.Equals("UGFzc3dvcmQ6"))
                            {
                                smtpSession.State = SmtpSession.SmtpState.Password;
                            }
                        }
                        else if (replyCodeAndArgument.Key == 235)  //AUTHENTICATION SUCCESSFUL
                        {
                            base.MainPacketHandler.AddCredential(new NetworkCredential(tcpSession.ClientHost, tcpSession.ServerHost, smtpPacket.PacketTypeDescription, smtpSession.Username, smtpSession.Password, smtpPacket.ParentFrame.Timestamp));
                            smtpSession.State = SmtpSession.SmtpState.Authenticated;
                        }
                        else if (replyCodeAndArgument.Key >= 500) //error
                        {
                            smtpSession.State = SmtpSession.SmtpState.None;
                        }
                        else if (replyCodeAndArgument.Key == 354) //DATA "Start mail input; end with <CRLF>.<CRLF>"
                        {
                            smtpSession.State = SmtpSession.SmtpState.Data;
                        }
                        else if (replyCodeAndArgument.Key == 250) //"Requested mail action okay, completed"
                        {
                            smtpSession.State = SmtpSession.SmtpState.None;
                        }
                    }
                }
                //There was a SMTP packet, so treat this as a sucsessfull extraction
                return(tcpPacket.PayloadDataLength);
            }
            else //smtpPacket == null
            {
                return(0);
            }
        }
Ejemplo n.º 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);
                }
            }
        }