//public int ExtractData(NetworkTcpSession tcpSession, NetworkHost sourceHost, NetworkHost destinationHost, IEnumerable<Packets.AbstractPacket> packetList) {
        public int ExtractData(NetworkTcpSession tcpSession, bool transferIsClientToServer, IEnumerable <PacketParser.Packets.AbstractPacket> packetList)
        {
            /*
             * NetworkHost sourceHost, destinationHost;
             * if (transferIsClientToServer) {
             *  sourceHost = tcpSession.Flow.FiveTuple.ClientHost;
             *  destinationHost = tcpSession.Flow.FiveTuple.ServerHost;
             * }
             * else {
             *  sourceHost = tcpSession.Flow.FiveTuple.ServerHost;
             *  destinationHost = tcpSession.Flow.FiveTuple.ClientHost;
             * }*/

            Packets.TcpPacket tcpPacket = null;
            Packets.FtpPacket ftpPacket = null;

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

            FtpSession ftpSession = null;//we can only have one FtpSession per packet...
            //bool returnValue=false;
            int parsedBytes = 0;


            if (tcpSession.SynPacketReceived && tcpSession.SynAckPacketReceived)
            {
                //start by checking if this is an incoming file transfer through FTP
                if (!tcpSession.SessionEstablished)
                {
                    //we now have an upcoming session

                    //see if it matches the pending FTP data sessions
                    if (this.pendingFileTransferList.ContainsKey(PendingFileTransfer.GetKey(tcpSession.ClientHost, tcpSession.ClientTcpPort, tcpSession.ServerHost, tcpSession.ServerTcpPort)))
                    {
                        PendingFileTransfer pending = this.pendingFileTransferList[PendingFileTransfer.GetKey(tcpSession.ClientHost, tcpSession.ClientTcpPort, tcpSession.ServerHost, tcpSession.ServerTcpPort)];
                        pending.FileTransferSessionEstablished = true;
                        ftpSession = pending.FtpControlSession;
                        //returnValue=true;//we managed to get some data out of this!
                        parsedBytes = tcpPacket.PayloadDataLength;
                    }
                    //see if the client port was unknown
                    else if (this.pendingFileTransferList.ContainsKey(PendingFileTransfer.GetKey(tcpSession.ClientHost, null, tcpSession.ServerHost, tcpSession.ServerTcpPort)))
                    {
                        PendingFileTransfer pending = this.pendingFileTransferList[PendingFileTransfer.GetKey(tcpSession.ClientHost, null, tcpSession.ServerHost, tcpSession.ServerTcpPort)];
                        this.pendingFileTransferList.Remove(pending.GetKey());
                        pending.DataSessionClientPort          = tcpSession.ClientTcpPort;//the Key will now be changed!
                        pending.FileTransferSessionEstablished = true;
                        this.pendingFileTransferList.Add(pending.GetKey(), pending);
                        ftpSession = pending.FtpControlSession;
                        //returnValue=true;
                        parsedBytes = tcpPacket.PayloadDataLength;
                    }
                }//end check for new FTP DATA sessions
                else if (tcpPacket != null && tcpPacket.FlagBits.Fin)
                {
                    //check if there is an FTP data session being closed
                    if (this.MainPacketHandler.FileStreamAssemblerList.ContainsAssembler(tcpSession.Flow.FiveTuple, transferIsClientToServer, true, PacketParser.FileTransfer.FileStreamTypes.FTP))
                    {
                        PacketParser.FileTransfer.FileStreamAssembler assembler = this.MainPacketHandler.FileStreamAssemblerList.GetAssembler(tcpSession.Flow.FiveTuple, transferIsClientToServer);
                        if (assembler.FileContentLength == -1 && assembler.FileSegmentRemainingBytes == -1)
                        {
                            //TODO: see if all data has been received or if the FIN arrived before the final data packet
                            assembler.FinishAssembling();
                        }
                    }
                }
            }

            if (ftpPacket != null && tcpPacket != null)
            {
                //returnValue=true;
                parsedBytes = ftpPacket.PacketLength;

                if (ftpSessionList.ContainsKey(tcpSession))
                {
                    ftpSession = ftpSessionList[tcpSession];
                }
                else
                {
                    ftpSession = new FtpSession(tcpSession.ClientHost, tcpSession.ServerHost);
                    this.ftpSessionList.Add(tcpSession, ftpSession);
                }

                /*
                 * NetworkHost sourceHost, destinationHost;
                 * if (transferIsClientToServer) {
                 *  sourceHost = tcpSession.Flow.FiveTuple.ClientHost;
                 *  destinationHost = tcpSession.Flow.FiveTuple.ServerHost;
                 * }
                 * else {
                 *  sourceHost = tcpSession.Flow.FiveTuple.ServerHost;
                 *  destinationHost = tcpSession.Flow.FiveTuple.ClientHost;
                 * }
                 */
                if (ftpPacket.ClientToServer)
                {
                    if (ftpPacket.RequestCommand != null)
                    {
                        if (ftpPacket.RequestArgument != null)
                        {
                            System.Collections.Specialized.NameValueCollection tmpCol = new System.Collections.Specialized.NameValueCollection();
                            tmpCol.Add(ftpPacket.RequestCommand, ftpPacket.RequestArgument);
                            base.MainPacketHandler.OnParametersDetected(new Events.ParametersEventArgs(ftpPacket.ParentFrame.FrameNumber, tcpSession.Flow.FiveTuple, transferIsClientToServer, tmpCol, ftpPacket.ParentFrame.Timestamp, "FTP Request"));
                        }
                        if (ftpPacket.RequestCommand.ToUpper() == "USER")//username
                        {
                            ftpSession.Username = ftpPacket.RequestArgument;
                        }
                        else if (ftpPacket.RequestCommand.ToUpper() == "PASS")//password
                        {
                            ftpSession.Password = ftpPacket.RequestArgument;
                            if (ftpSession.Username != null && ftpSession.Password != null)
                            {
                                base.MainPacketHandler.AddCredential(new NetworkCredential(tcpSession.ClientHost, tcpSession.ServerHost, ftpPacket.PacketTypeDescription, ftpSession.Username, ftpSession.Password, ftpPacket.ParentFrame.Timestamp));
                            }
                        }
                        else if (ftpPacket.RequestCommand.ToUpper() == "PORT")
                        {
                            ushort clientListeningOnPort;
                            if (TryGetPort(ftpPacket.RequestArgument, out clientListeningOnPort))
                            {
                                //ftpSession.ActiveMode=true;
                                //ftpSession.ClientDataListenerTcpPort=this.GetPort(ftpPacket.RequestArgument);

                                //ftpSession.PendingFileTransfer=new PendingFileTransfer(ftpSession.ServerHost, (ushort)20, ftpSession.ClientHost, clientListeningOnPort, false, ftpSession);
                                ftpSession.PendingFileTransfer = new PendingFileTransfer(ftpSession.ServerHost, null, ftpSession.ClientHost, clientListeningOnPort, false, ftpSession);
                                if (this.pendingFileTransferList.ContainsKey(ftpSession.PendingFileTransfer.GetKey()))
                                {
                                    this.pendingFileTransferList.Remove(ftpSession.PendingFileTransfer.GetKey());
                                }
                                this.pendingFileTransferList.Add(ftpSession.PendingFileTransfer.GetKey(), ftpSession.PendingFileTransfer);
                            }
                        }
                        else if (ftpPacket.RequestCommand.ToUpper() == "STOR")//file upload (client -> server)

                        //set filename and file direction
                        {
                            if (ftpSession.PendingFileTransfer != null)
                            {
                                ftpSession.PendingFileTransfer.Filename = ftpPacket.RequestArgument;
                                ftpSession.PendingFileTransfer.FileDirectionIsDataSessionServerToDataSessionClient = !ftpSession.PendingFileTransfer.DataSessionIsPassive;
                                ftpSession.PendingFileTransfer.Details = ftpPacket.RequestCommand + " " + ftpPacket.RequestArgument;
                            }
                            else
                            {
                                //ftpPacket.ParentFrame.Errors.Add(new Frame.Error(ftpPacket.ParentFrame, ftpPacket.PacketStartIndex, ftpPacket.PacketEndIndex, "STOR command without a pending ftp data session"));
                                this.MainPacketHandler.OnAnomalyDetected("STOR command without a pending ftp data session. Frame: " + ftpPacket.ParentFrame.ToString(), ftpPacket.ParentFrame.Timestamp);
                                //System.Diagnostics.Debugger.Break();//this should not occur!
                            }
                        }
                        else if (ftpPacket.RequestCommand.ToUpper() == "RETR")//file download (server -> client)
                        {
                            if (ftpSession.PendingFileTransfer != null)
                            {
                                ftpSession.PendingFileTransfer.Filename = ftpPacket.RequestArgument;
                                ftpSession.PendingFileTransfer.FileDirectionIsDataSessionServerToDataSessionClient = ftpSession.PendingFileTransfer.DataSessionIsPassive;
                                ftpSession.PendingFileTransfer.Details = ftpPacket.RequestCommand + " " + ftpPacket.RequestArgument;
                            }
                            else
                            {
                                //System.Diagnostics.Debugger.Break();//this should not iccur
                                //ftpPacket.ParentFrame.Errors.Add(new Frame.Error(ftpPacket.ParentFrame, ftpPacket.PacketStartIndex, ftpPacket.PacketEndIndex, "RETR command without a pending ftp data session"));
                                this.MainPacketHandler.OnAnomalyDetected("RETR command without a pending ftp data session. Frame: " + ftpPacket.ParentFrame.ToString(), ftpPacket.ParentFrame.Timestamp);
                            }
                        }
                        else if (ftpPacket.RequestCommand.ToUpper() == "SIZE")
                        {
                            ftpSession.PendingSizeRequestFileName = ftpPacket.RequestArgument;
                        }
                    }
                }
                else  //server to client packet
                {
                    if (ftpPacket.ResponseCode != 0 && ftpPacket.ResponseArgument != null)
                    {
                        System.Collections.Specialized.NameValueCollection tmpCol = new System.Collections.Specialized.NameValueCollection();
                        tmpCol.Add(ftpPacket.ResponseCode.ToString(), ftpPacket.ResponseArgument);
                        MainPacketHandler.OnParametersDetected(new Events.ParametersEventArgs(ftpPacket.ParentFrame.FrameNumber, tcpSession.Flow.FiveTuple, transferIsClientToServer, tmpCol, ftpPacket.ParentFrame.Timestamp, "FTP Response"));

                        //look for an FTP banner
                        if (ftpPacket.ResponseCode == 220 && ftpPacket.ResponseArgument.ToLower().Contains("ftp"))
                        {
                            tcpSession.Flow.FiveTuple.ServerHost.AddFtpServerBanner(ftpPacket.ResponseArgument, tcpPacket.SourcePort);
                        }
                    }
                    if (ftpPacket.ResponseCode == 213 && ftpSession.PendingSizeRequestFileName != null)//File size response
                    {
                        int fileSize;
                        if (Int32.TryParse(ftpPacket.ResponseArgument, out fileSize))
                        {
                            ftpSession.FileSizes[ftpSession.PendingSizeRequestFileName] = fileSize;
                        }
                        //ftpSession.FileSizes.Add(ftpSession.PendingSizeRequestFileName, fileSize);
                        ftpSession.PendingSizeRequestFileName = null;
                    }
                    if (ftpPacket.ResponseCode == 226)//File receive OK
                    //close file stream assembler?
                    {
                    }
                    else if (ftpPacket.ResponseCode == 227)  //Entering Passive Mode - Response to client "PASV" command

                    //From: http://cr.yp.to/ftp/retr.html
                    //Many servers put different strings before h1 and after p2.
                    //I recommend that clients use the following strategy to parse the
                    //response line: look for the first digit after the initial space;
                    //look for the fourth comma after that digit; read two (possibly negative)
                    //integers, separated by a comma; the TCP port number is p1*256+p2,
                    //where p1 is the first integer modulo 256 and p2 is the second integer
                    //modulo 256.

                    //it is probably simpler to do this with RegEx, but this is simple enough so I wont bother with RegEx for now...
                    {
                        char[] digits    = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
                        string ipAndPort = ftpPacket.ResponseArgument.Substring(ftpPacket.ResponseArgument.IndexOfAny(digits));
                        //string ipAndPort=ftpPacket.ResponseArgument.Substring(ftpPacket.ResponseArgument.IndexOf('(')+1);
                        ipAndPort = ipAndPort.Substring(0, ipAndPort.LastIndexOfAny(digits) + 1);
                        //ipAndPort=ipAndPort.Substring(0, ipAndPort.IndexOf(')'));
                        ushort serverListeningOnPort;
                        if (this.TryGetPort(ipAndPort, out serverListeningOnPort))
                        {
                            ftpSession.PendingFileTransfer = new PendingFileTransfer(ftpSession.ClientHost, null, ftpSession.ServerHost, serverListeningOnPort, true, ftpSession);
                            if (this.pendingFileTransferList.ContainsKey(ftpSession.PendingFileTransfer.GetKey()))
                            {
                                this.pendingFileTransferList.Remove(ftpSession.PendingFileTransfer.GetKey());
                            }
                            this.pendingFileTransferList.Add(ftpSession.PendingFileTransfer.GetKey(), ftpSession.PendingFileTransfer);
                        }
                    }
                    else if (ftpPacket.ResponseCode == 230)//Login successful
                    //ftpSession.=ftpPacket.RequestArgument;
                    {
                        if (ftpSession.Username != null && ftpSession.Password != null)
                        {
                            base.MainPacketHandler.AddCredential(new NetworkCredential(tcpSession.ClientHost, tcpSession.ServerHost, ftpPacket.PacketTypeDescription, ftpSession.Username, ftpSession.Password, true, ftpPacket.ParentFrame.Timestamp));
                        }
                    }
                    else if (ftpPacket.ResponseCode == 234)  //server response to an 'AUTH TLS' command rfc4217 and rfc2228

                    /**
                     * If the server is willing to accept the named security mechanism,
                     * and does not require any security data, it must respond with reply
                     * code 234.
                     **/
                    //Unfortunately we haven't stored the request, so we can't know if the client was asking for TLS or some other security measure
                    {
                        if (ftpPacket.ResponseArgument.Contains("TLS") || ftpPacket.ResponseArgument.Contains("SSL"))
                        {
                            tcpSession.ProtocolFinder.SetConfirmedApplicationLayerProtocol(ApplicationLayerProtocol.Ssl, false);
                        }
                    }
                }//end server to client
            }
            if (ftpSession != null && ftpSession.PendingFileTransfer != null)
            {
                //I guess returnValue is already set to true by now, but I'll do it again just to be sure...
                if (parsedBytes == 0)
                {
                    parsedBytes = tcpPacket.PayloadDataLength;
                }
                //returnValue=true;
                PendingFileTransfer pending = ftpSession.PendingFileTransfer;
                //see if the pending file transfer could be transformed into a real file stream assembler
                if (pending.FileTransferSessionEstablished && pending.FileDirectionIsDataSessionServerToDataSessionClient != null && pending.DataSessionClientPort != null)
                {
                    //Server->Client ?

                    FileTransfer.FileStreamAssembler.FileAssmeblyRootLocation fileAssemblyLocation;
                    if ((ftpSession.ServerHost == pending.DataSessionServer) == pending.FileDirectionIsDataSessionServerToDataSessionClient.Value)
                    {
                        fileAssemblyLocation = FileTransfer.FileStreamAssembler.FileAssmeblyRootLocation.source;
                    }
                    else
                    {
                        fileAssemblyLocation = FileTransfer.FileStreamAssembler.FileAssmeblyRootLocation.destination;
                    }
                    FileTransfer.FileStreamAssembler assembler = new FileTransfer.FileStreamAssembler(MainPacketHandler.FileStreamAssemblerList, pending.GetFiveTuple(), !pending.FileDirectionIsDataSessionServerToDataSessionClient.Value, FileTransfer.FileStreamTypes.FTP, pending.Filename, "/", pending.Details, tcpPacket.ParentFrame.FrameNumber, tcpPacket.ParentFrame.Timestamp, fileAssemblyLocation);

                    string fileCompletePath = "";
                    if (assembler.Filename != null && assembler.FileLocation != null)
                    {
                        fileCompletePath = assembler.FileLocation + "/" + assembler.Filename;
                    }
                    if (ftpSession.FileSizes.ContainsKey(fileCompletePath))
                    {
                        assembler.FileContentLength         = ftpSession.FileSizes[fileCompletePath];
                        assembler.FileSegmentRemainingBytes = ftpSession.FileSizes[fileCompletePath];
                    }
                    else
                    {
                        //-1 is set instead of null if Content-Length is not defined
                        assembler.FileContentLength         = -1;
                        assembler.FileSegmentRemainingBytes = -1;
                    }
                    if (assembler.TryActivate())
                    {
                        MainPacketHandler.FileStreamAssemblerList.Add(assembler);
                    }
                    //assembler.Activate();
                    //the file transfer is no longer pending since the assembler is started!
                    pendingFileTransferList.Remove(pending.GetKey());
                    ftpSession.PendingFileTransfer = null;
                }
            }
            return(parsedBytes);
        }
        //public int ExtractData(NetworkTcpSession tcpSession, NetworkHost sourceHost, NetworkHost destinationHost, IEnumerable<Packets.AbstractPacket> packetList) {
        public int ExtractData(NetworkTcpSession tcpSession, bool transferIsClientToServer, IEnumerable <PacketParser.Packets.AbstractPacket> packetList)
        {
            NetworkHost sourceHost, destinationHost;

            if (transferIsClientToServer)
            {
                sourceHost      = tcpSession.Flow.FiveTuple.ClientHost;
                destinationHost = tcpSession.Flow.FiveTuple.ServerHost;
            }
            else
            {
                sourceHost      = tcpSession.Flow.FiveTuple.ServerHost;
                destinationHost = tcpSession.Flow.FiveTuple.ClientHost;
            }
            //bool successfulExtraction=false;
            int successfullyExtractedBytes = 0;

            foreach (Packets.AbstractPacket p in packetList)
            {
                if (p.GetType() == typeof(Packets.NtlmSspPacket))
                {
                    Packets.NtlmSspPacket ntlmPacket = (Packets.NtlmSspPacket)p;
                    if (ntlmPacket.NtlmChallenge != null)
                    {
                        if (ntlmChallengeList.ContainsKey(tcpSession.GetHashCode()))
                        {
                            ntlmChallengeList[tcpSession.GetHashCode()] = ntlmPacket.NtlmChallenge;
                        }
                        else
                        {
                            ntlmChallengeList.Add(tcpSession.GetHashCode(), ntlmPacket.NtlmChallenge);
                        }
                    }
                    if (ntlmPacket.DomainName != null)
                    {
                        sourceHost.AddDomainName(ntlmPacket.DomainName);
                    }
                    if (ntlmPacket.HostName != null)
                    {
                        sourceHost.AddHostName(ntlmPacket.HostName);
                    }
                    if (ntlmPacket.UserName != null)
                    {
                        if (ntlmPacket.UserName.EndsWith("$"))  //hostname
                        {
                            sourceHost.AddHostName(ntlmPacket.UserName.TrimEnd(new[] { '$' }));
                        }
                        else
                        {
                            sourceHost.AddNumberedExtraDetail("NTLM Username ", ntlmPacket.UserName);
                        }

                        string lanManagerHashInfo = null;
                        if (ntlmPacket.LanManagerResponse != null)
                        {
                            lanManagerHashInfo = "LAN Manager Response: " + ntlmPacket.LanManagerResponse;
                        }
                        if (ntlmPacket.NtlmResponse != null)
                        {
                            if (lanManagerHashInfo == null)
                            {
                                lanManagerHashInfo = "";
                            }
                            else
                            {
                                lanManagerHashInfo = lanManagerHashInfo + " - ";
                            }
                            lanManagerHashInfo = lanManagerHashInfo + "NTLM Response: " + ntlmPacket.NtlmResponse;
                        }
                        if (lanManagerHashInfo == null)
                        {
                            base.MainPacketHandler.AddCredential(new NetworkCredential(sourceHost, destinationHost, "NTLMSSP", ntlmPacket.UserName, ntlmPacket.ParentFrame.Timestamp));
                        }
                        else
                        {
                            if (ntlmChallengeList.ContainsKey(tcpSession.GetHashCode()))
                            {
                                lanManagerHashInfo = "NTLM Challenge: " + ntlmChallengeList[tcpSession.GetHashCode()] + " - " + lanManagerHashInfo;
                            }
                            if (ntlmPacket.DomainName == null)
                            {
                                base.MainPacketHandler.AddCredential(new NetworkCredential(sourceHost, destinationHost, "NTLMSSP", ntlmPacket.UserName, lanManagerHashInfo, ntlmPacket.ParentFrame.Timestamp));
                            }
                            else
                            {
                                base.MainPacketHandler.AddCredential(new NetworkCredential(sourceHost, destinationHost, "NTLMSSP", ntlmPacket.DomainName + "\\" + ntlmPacket.UserName, lanManagerHashInfo, ntlmPacket.ParentFrame.Timestamp));
                            }
                        }
                    }
                    successfullyExtractedBytes += ntlmPacket.ParentFrame.Data.Length;//it's OK to return a larger value that what was parsed
                }
            }

            return(successfullyExtractedBytes);
        }
        //public int ExtractData(NetworkTcpSession tcpSession, NetworkHost sourceHost, NetworkHost destinationHost, IEnumerable<AbstractPacket> packetList) {
        public int ExtractData(NetworkTcpSession tcpSession, bool transferIsClientToServer, IEnumerable <PacketParser.Packets.AbstractPacket> packetList)
        {
            /*
             * NetworkHost sourceHost, destinationHost;
             * if (transferIsClientToServer) {
             *  sourceHost = tcpSession.Flow.FiveTuple.ClientHost;
             *  destinationHost = tcpSession.Flow.FiveTuple.ServerHost;
             * }
             * else {
             *  sourceHost = tcpSession.Flow.FiveTuple.ServerHost;
             *  destinationHost = tcpSession.Flow.FiveTuple.ClientHost;
             * }*/
            Packets.ImapPacket imapPacket = null;
            Packets.TcpPacket  tcpPacket  = null;
            foreach (Packets.AbstractPacket p in packetList)
            {
                if (p.GetType() == typeof(Packets.TcpPacket))
                {
                    tcpPacket = (Packets.TcpPacket)p;
                }
                else if (p.GetType() == typeof(Packets.ImapPacket))
                {
                    imapPacket = (Packets.ImapPacket)p;
                }
            }
            if (tcpPacket != null && (tcpPacket.SourcePort == 220 || tcpPacket.SourcePort == 143) && this.lastCommand.ContainsKey(tcpSession) && this.lastCommand[tcpSession] == ImapPacket.ClientCommand.UID && this.serverToClientEmailReassemblers.ContainsKey(tcpSession))
            {
                return(this.ExtractEmail(tcpSession, tcpPacket, tcpPacket.PacketStartIndex + tcpPacket.DataOffsetByteCount, tcpPacket.PayloadDataLength));
            }
            else if (tcpPacket != null && (tcpPacket.DestinationPort == 220 || tcpPacket.DestinationPort == 143) && this.lastCommand.ContainsKey(tcpSession) && this.lastCommand[tcpSession] == ImapPacket.ClientCommand.APPEND && this.clientToServerEmailReassemblers.ContainsKey(tcpSession))
            {
                return(this.ExtractEmail(tcpSession, tcpPacket, tcpPacket.PacketStartIndex + tcpPacket.DataOffsetByteCount, tcpPacket.PayloadDataLength));
            }
            else if (tcpPacket != null && imapPacket != null)
            {
                if (imapPacket.ClientToServer)
                {
                    if (imapPacket.Command != null)
                    {
                        if (lastCommand.ContainsKey(tcpSession))
                        {
                            lastCommand[tcpSession] = imapPacket.Command.Value;
                        }
                        else
                        {
                            lastCommand.Add(tcpSession, imapPacket.Command.Value);
                        }

                        if (imapPacket.FullRequestOrResponseLine != null && imapPacket.FullRequestOrResponseLine.Length > 0)
                        {
                            System.Collections.Specialized.NameValueCollection parameters = new System.Collections.Specialized.NameValueCollection();
                            parameters.Add(imapPacket.Command.Value.ToString(), imapPacket.FullRequestOrResponseLine);
                            base.MainPacketHandler.OnParametersDetected(new Events.ParametersEventArgs(imapPacket.ParentFrame.FrameNumber, tcpSession.Flow.FiveTuple, transferIsClientToServer, parameters, imapPacket.ParentFrame.Timestamp, "IMAP Client Command"));
                        }

                        //remove any old email reassemblers since we have now received a new command
                        if (this.serverToClientEmailReassemblers.ContainsKey(tcpSession))
                        {
                            this.serverToClientEmailReassemblers[tcpSession].Close();
                            this.serverToClientEmailReassemblers.Remove(tcpSession);//we will need to create a new reassembler
                        }

                        if (imapPacket.Command == ImapPacket.ClientCommand.APPEND)
                        {
                            //an email is being uploaded to the server
                            if (imapPacket.BodyLength > 0)
                            {
                                int emailBytes = this.ExtractEmail(tcpSession, tcpPacket, imapPacket.PacketStartIndex + imapPacket.ParsedBytesCount, imapPacket.PacketLength - imapPacket.ParsedBytesCount, imapPacket.BodyLength, true);
                                imapPacket.ParsedBytesCount += emailBytes;
                            }
                        }
                        else if (imapPacket.Command == ImapPacket.ClientCommand.LOGIN)
                        {
                            string[] args       = imapPacket.FullRequestOrResponseLine.Split(new char[] { ' ' });
                            char[]   quoteChars = new char[] { '\'', '"' };
                            //a001 LOGIN SMITH SESAME
                            if (args.Length > 3)
                            {
                                string            username = args[2].Trim(quoteChars);
                                string            password = args[3].Trim(quoteChars);
                                NetworkCredential cred     = new NetworkCredential(tcpSession.ClientHost, tcpSession.ServerHost, "IMAP", username, password, imapPacket.ParentFrame.Timestamp);
                                //base.MainPacketHandler.OnCredentialDetected(new Events.CredentialEventArgs(cred));
                                base.MainPacketHandler.AddCredential(cred);
                            }
                        }
                    }
                    else if (lastCommand.ContainsKey(tcpSession) && lastCommand[tcpSession] == ImapPacket.ClientCommand.AUTHENTICATE)
                    {
                        if (imapPacket.FullRequestOrResponseLine != null && imapPacket.FullRequestOrResponseLine.Length > 0)
                        {
                            string            base64 = imapPacket.FullRequestOrResponseLine;
                            NetworkCredential cred   = SmtpPacketHandler.ExtractBase64EncodedAuthPlainCredential(base64, imapPacket.ParentFrame, tcpSession, ApplicationLayerProtocol.Imap);
                            if (cred != null)
                            {
                                //base.MainPacketHandler.OnCredentialDetected(new Events.CredentialEventArgs(cred));
                                base.MainPacketHandler.AddCredential(cred);

                                if (imapPacket.ParsedBytesCount == 0)
                                {
                                    imapPacket.ParsedBytesCount = base64.Length + 2;//add CRLF
                                }
                            }
                        }
                    }
                }
                else  //server to client
                {
                    if (imapPacket.Result != null && imapPacket.FullRequestOrResponseLine != null && imapPacket.FullRequestOrResponseLine.Length > 0)
                    {
                        System.Collections.Specialized.NameValueCollection parameters = new System.Collections.Specialized.NameValueCollection();
                        parameters.Add(imapPacket.Result.Value.ToString(), imapPacket.FullRequestOrResponseLine);
                        base.MainPacketHandler.OnParametersDetected(new Events.ParametersEventArgs(imapPacket.ParentFrame.FrameNumber, tcpSession.Flow.FiveTuple, transferIsClientToServer, parameters, imapPacket.ParentFrame.Timestamp, "IMAP Server Response"));
                    }

                    if (lastCommand.ContainsKey(tcpSession) && (lastCommand[tcpSession] == ImapPacket.ClientCommand.FETCH || lastCommand[tcpSession] == ImapPacket.ClientCommand.UID))
                    {
                        if (imapPacket.Command != null && imapPacket.FullRequestOrResponseLine != null && imapPacket.FullRequestOrResponseLine.Length > 0)
                        {
                            System.Collections.Specialized.NameValueCollection parameters = new System.Collections.Specialized.NameValueCollection();
                            parameters.Add(imapPacket.Command.Value.ToString(), imapPacket.FullRequestOrResponseLine);
                            base.MainPacketHandler.OnParametersDetected(new Events.ParametersEventArgs(imapPacket.ParentFrame.FrameNumber, tcpSession.Flow.FiveTuple, transferIsClientToServer, parameters, imapPacket.ParentFrame.Timestamp, "IMAP Untagged Response"));
                        }
                        //the server might push an email here
                        if (imapPacket.BodyLength > 0)
                        {
                            int emailBytes = this.ExtractEmail(tcpSession, tcpPacket, imapPacket.PacketStartIndex + imapPacket.ParsedBytesCount, imapPacket.PacketLength - imapPacket.ParsedBytesCount, imapPacket.BodyLength, false);
                            if (imapPacket.ParenthesesDiff > 0 && imapPacket.ParsedBytesCount + emailBytes < imapPacket.PacketLength)
                            {
                                //we might have a trailing line that closes the parenthesis, let's read that one too
                                int    index                   = imapPacket.PacketStartIndex + imapPacket.ParsedBytesCount + emailBytes;
                                string trailingLine            = Utils.ByteConverter.ReadLine(imapPacket.ParentFrame.Data, ref index);
                                int    trailingParenthesesDiff = trailingLine.Split('(').Length - trailingLine.Split(')').Length;
                                if (imapPacket.ParenthesesDiff + trailingParenthesesDiff == 0)
                                {
                                    return(index - imapPacket.PacketStartIndex);
                                }
                                else
                                {
                                    return(imapPacket.ParsedBytesCount + emailBytes);
                                }
                            }
                            else
                            {
                                return(imapPacket.ParsedBytesCount + emailBytes);
                            }
                        }
                    }
                    else if (lastCommand.ContainsKey(tcpSession) && (lastCommand[tcpSession] == ImapPacket.ClientCommand.STARTTLS))
                    {
                        if (imapPacket.Result == ImapPacket.ServerResult.OK)
                        {
                            //1 OK Begin TLS negotiation now
                            //do the same protocol switch trick as in SocksPacketHandler
                            //tcpSession.ProtocolFinder = new TcpPortProtocolFinder(tcpSession.ClientHost, tcpSession.ServerHost, tcpSession.ClientTcpPort, tcpSession.ServerTcpPort, tcpPacket.ParentFrame.FrameNumber, tcpPacket.ParentFrame.Timestamp, base.MainPacketHandler);
                            tcpSession.ProtocolFinder.SetConfirmedApplicationLayerProtocol(ApplicationLayerProtocol.Ssl, false);
                        }
                    }
                }
                return(imapPacket.ParsedBytesCount);
            }
            else
            {
                return(0);
            }
        }
Exemple #4
0
        public int ExtractData(NetworkTcpSession tcpSession, NetworkHost sourceHost, NetworkHost destinationHost, IEnumerable <Packets.AbstractPacket> packetList)
        {
            //bool successfulExtraction=false;
            int successfullyExtractedBytes = 0;

            foreach (Packets.AbstractPacket p in packetList)
            {
                if (p.GetType() == typeof(Packets.NtlmSspPacket))
                {
                    Packets.NtlmSspPacket ntlmPacket = (Packets.NtlmSspPacket)p;
                    if (ntlmPacket.NtlmChallenge != null)
                    {
                        if (ntlmChallengeList.ContainsKey(tcpSession.GetHashCode()))
                        {
                            ntlmChallengeList[tcpSession.GetHashCode()] = ntlmPacket.NtlmChallenge;
                        }
                        else
                        {
                            ntlmChallengeList.Add(tcpSession.GetHashCode(), ntlmPacket.NtlmChallenge);
                        }
                    }
                    if (ntlmPacket.DomainName != null)
                    {
                        sourceHost.AddDomainName(ntlmPacket.DomainName);
                    }
                    if (ntlmPacket.HostName != null)
                    {
                        sourceHost.AddHostName(ntlmPacket.HostName);
                    }
                    if (ntlmPacket.UserName != null)
                    {
                        if (!sourceHost.ExtraDetailsList.ContainsKey("NTLM Username " + ntlmPacket.UserName))
                        {
                            sourceHost.ExtraDetailsList.Add("NTLM Username " + ntlmPacket.UserName, ntlmPacket.UserName);
                        }
                        string lanManagerHashInfo = null;
                        if (ntlmPacket.LanManagerResponse != null)
                        {
                            lanManagerHashInfo = "LAN Manager Response: " + ntlmPacket.LanManagerResponse;
                        }
                        if (ntlmPacket.NtlmResponse != null)
                        {
                            if (lanManagerHashInfo == null)
                            {
                                lanManagerHashInfo = "";
                            }
                            else
                            {
                                lanManagerHashInfo = lanManagerHashInfo + " - ";
                            }
                            lanManagerHashInfo = lanManagerHashInfo + "NTLM Response: " + ntlmPacket.NtlmResponse;
                        }
                        if (lanManagerHashInfo == null)
                        {
                            base.MainPacketHandler.AddCredential(new NetworkCredential(sourceHost, destinationHost, "NTLMSSP", ntlmPacket.UserName, ntlmPacket.ParentFrame.Timestamp));
                        }
                        else
                        {
                            if (ntlmChallengeList.ContainsKey(tcpSession.GetHashCode()))
                            {
                                lanManagerHashInfo = "NTLM Challenge: " + ntlmChallengeList[tcpSession.GetHashCode()] + " - " + lanManagerHashInfo;
                            }
                            base.MainPacketHandler.AddCredential(new NetworkCredential(sourceHost, destinationHost, "NTLMSSP", ntlmPacket.UserName, lanManagerHashInfo, ntlmPacket.ParentFrame.Timestamp));
                        }
                    }
                    successfullyExtractedBytes += ntlmPacket.ParentFrame.Data.Length;//it's OK to return a larger value that what was parsed
                }
            }

            return(successfullyExtractedBytes);
        }
Exemple #5
0
        //public int ExtractData(NetworkTcpSession tcpSession, NetworkHost sourceHost, NetworkHost destinationHost, IEnumerable<Packets.AbstractPacket> packetList) {
        public int ExtractData(NetworkTcpSession tcpSession, bool transferIsClientToServer, IEnumerable <PacketParser.Packets.AbstractPacket> packetList)
        {
            NetworkHost sourceHost, destinationHost;

            if (transferIsClientToServer)
            {
                sourceHost      = tcpSession.Flow.FiveTuple.ClientHost;
                destinationHost = tcpSession.Flow.FiveTuple.ServerHost;
            }
            else
            {
                sourceHost      = tcpSession.Flow.FiveTuple.ServerHost;
                destinationHost = tcpSession.Flow.FiveTuple.ClientHost;
            }
            //bool successfulExtraction=false;
            int successfullyExtractedBytes = 0;

            foreach (Packets.AbstractPacket p in packetList)
            {
                if (p.GetType() == typeof(Packets.NtlmSspPacket))
                {
                    Packets.NtlmSspPacket ntlmPacket = (Packets.NtlmSspPacket)p;
                    if (ntlmPacket.NtlmChallenge != null)
                    {
                        if (ntlmChallengeList.ContainsKey(tcpSession.GetHashCode()))
                        {
                            ntlmChallengeList[tcpSession.GetHashCode()] = ntlmPacket.NtlmChallenge;
                        }
                        else
                        {
                            ntlmChallengeList.Add(tcpSession.GetHashCode(), ntlmPacket.NtlmChallenge);
                        }
                    }
                    if (ntlmPacket.DomainName != null)
                    {
                        sourceHost.AddDomainName(ntlmPacket.DomainName);
                    }
                    if (ntlmPacket.HostName != null)
                    {
                        sourceHost.AddHostName(ntlmPacket.HostName, ntlmPacket.PacketTypeDescription);
                    }
                    if (ntlmPacket.UserName != null)
                    {
                        if (ntlmPacket.UserName.EndsWith("$"))  //hostname
                        {
                            sourceHost.AddHostName(ntlmPacket.UserName.TrimEnd(new[] { '$' }), ntlmPacket.PacketTypeDescription);
                        }
                        else
                        {
                            sourceHost.AddNumberedExtraDetail("NTLM Username ", ntlmPacket.UserName);
                        }

                        string lanManagerHashInfo = null;
                        if (ntlmPacket.LanManagerResponse != null)
                        {
                            lanManagerHashInfo = "LAN Manager Response: " + ntlmPacket.LanManagerResponse;
                            if (ntlmPacket.LanManagerResponse.Length >= 16)
                            {
                                //$LM$a9c604d244c4e99d
                                string lmHash = ntlmPacket.LanManagerResponse.Substring(0, 16);
                                if (lmHash.Trim(new[] { '0' }).Length > 0)
                                {
                                    base.MainPacketHandler.AddCredential(new NetworkCredential(sourceHost, destinationHost, "NTLMSSP", ntlmPacket.DomainName + "\\" + ntlmPacket.UserName, "$LM$" + lmHash, ntlmPacket.ParentFrame.Timestamp));
                                }
                            }
                        }
                        if (ntlmPacket.NtlmResponse != null)
                        {
                            if (lanManagerHashInfo == null)
                            {
                                lanManagerHashInfo = "";
                            }
                            else
                            {
                                lanManagerHashInfo = lanManagerHashInfo + " - ";
                            }
                            lanManagerHashInfo = lanManagerHashInfo + "NTLM Response: " + ntlmPacket.NtlmResponse;
                        }
                        if (lanManagerHashInfo == null)
                        {
                            base.MainPacketHandler.AddCredential(new NetworkCredential(sourceHost, destinationHost, "NTLMSSP", ntlmPacket.UserName, ntlmPacket.ParentFrame.Timestamp));
                        }
                        else
                        {
                            string ntlmChallenge = null;
                            if (ntlmChallengeList.ContainsKey(tcpSession.GetHashCode()))
                            {
                                ntlmChallenge      = ntlmChallengeList[tcpSession.GetHashCode()];
                                lanManagerHashInfo = "NTLM Challenge: " + ntlmChallenge + " - " + lanManagerHashInfo;
                            }
                            if (ntlmPacket.DomainName == null)
                            {
                                base.MainPacketHandler.AddCredential(new NetworkCredential(sourceHost, destinationHost, "NTLMSSP", ntlmPacket.UserName, lanManagerHashInfo, ntlmPacket.ParentFrame.Timestamp));
                            }
                            else
                            {
                                base.MainPacketHandler.AddCredential(new NetworkCredential(sourceHost, destinationHost, "NTLMSSP", ntlmPacket.DomainName + "\\" + ntlmPacket.UserName, lanManagerHashInfo, ntlmPacket.ParentFrame.Timestamp));
                            }

                            if (ntlmChallenge != null && ntlmPacket.NtlmResponse != null)
                            {
                                string johnHash = null;
                                if (ntlmPacket.NtlmResponse.Length == 48)  //24 bytes of binary data => NTLMv1
                                //example: $NETNTLM$1122334455667788$B2B2220790F40C88BCFF347C652F67A7C4A70D3BEBD70233
                                {
                                    johnHash = "$NETNTLM$" + ntlmChallenge + "$" + ntlmPacket.NtlmResponse;
                                }
                                else if (ntlmPacket.NtlmResponse.Length > 48)  //NTLMv2
                                //example: $NETNTLMv2$NTLMV2TESTWORKGROUP$1122334455667788$07659A550D5E9D02996DFD95C87EC1D5$0101000000000000006CF6385B74CA01B3610B02D99732DD000000000200120057004F0052004B00470052004F00550050000100200044004100540041002E00420049004E0043002D0053004500430055005200490000000000
                                {
                                    StringBuilder johnHashSB = new StringBuilder("$NETNTLMv2$");
                                    if (ntlmPacket.DomainName != null)
                                    {
                                        johnHashSB.Append(ntlmPacket.DomainName);
                                    }
                                    johnHashSB.Append("$");
                                    johnHashSB.Append(ntlmChallenge);
                                    johnHashSB.Append("$");
                                    johnHashSB.Append(ntlmPacket.NtlmResponse.Substring(0, 32)); //NTProofStr
                                    johnHashSB.Append("$");
                                    johnHashSB.Append(ntlmPacket.NtlmResponse.Substring(32));    //NTLMv2 response, minus NTProofStr
                                    johnHash = johnHashSB.ToString();
                                }
                                if (johnHash != null)
                                {
                                    base.MainPacketHandler.AddCredential(new NetworkCredential(sourceHost, destinationHost, "NTLMSSP", ntlmPacket.DomainName + "\\" + ntlmPacket.UserName, johnHash, ntlmPacket.ParentFrame.Timestamp));
                                }
                            }
                        }
                    }
                    successfullyExtractedBytes += ntlmPacket.ParentFrame.Data.Length;//it's OK to return a larger value that what was parsed
                }
            }

            return(successfullyExtractedBytes);
        }