private void extractBase64EncodedEmailAndPassword(string base64, Frame frame, NetworkTcpSession session) { NetworkCredential cred = SmtpPacketHandler.ExtractBase64EncodedAuthPlainCredential(base64, frame, session, ApplicationLayerProtocol.Pop3); if (cred != null) { //this.MainPacketHandler.OnCredentialDetected(new Events.CredentialEventArgs(cred)); this.MainPacketHandler.AddCredential(cred); this.updateCredential(cred, session); return; } /* * //dGVzdAB0ZXN0AHRlc3RwYXNz => user = test, password = password * byte[] bytes = System.Convert.FromBase64String(base64); * if (bytes.Length > 3 && Array.IndexOf<byte>(bytes, 0, 2) > 0) { * int firstNullIndex = Array.IndexOf<byte>(bytes, 0); * int secondNullIndex = Array.IndexOf<byte>(bytes, 0, firstNullIndex+1); * if (firstNullIndex >= 0 && secondNullIndex > 0) { * string username = ASCIIEncoding.ASCII.GetString(bytes, firstNullIndex + 1, secondNullIndex - firstNullIndex - 1); * string password = ASCIIEncoding.ASCII.GetString(bytes, secondNullIndex + 1, bytes.Length - secondNullIndex - 1); * NetworkCredential cred = new NetworkCredential(session.ClientHost, session.ServerHost, "POP3", username, password, frame.Timestamp); * this.MainPacketHandler.OnCredentialDetected(new Events.CredentialEventArgs(cred)); * this.updateCredential(cred, session); * return; * } * } */ /* * //the following code is probably not needed since we should already have found the credential by now * string emailAndPassword = System.Text.ASCIIEncoding.ASCII.GetString(bytes); * //TODO figure out how to split the email and password! * bool credentialFound = false; * if (!credentialFound) { * foreach (string hostname in this.getDomainsAndParentDomains(session.ServerHost.HostNameList)) { * if (hostname.Length > 0 && hostname.Contains(".") && emailAndPassword.ToLower().Contains(hostname.ToLower())) { * int passwordIndex = emailAndPassword.IndexOf(hostname, StringComparison.InvariantCultureIgnoreCase) + hostname.Length; * NetworkCredential cred = new NetworkCredential(session.ClientHost, session.ServerHost, "POP3", emailAndPassword.Substring(0, passwordIndex), emailAndPassword.Substring(passwordIndex), frame.Timestamp); * this.MainPacketHandler.OnCredentialDetected(new Events.CredentialEventArgs(cred)); * credentialFound = true; * this.updateCredential(cred, session); * } * } * } * if(!credentialFound && emailAndPassword.Contains(".") && emailAndPassword.Contains("@")) { * int atIndex = emailAndPassword.IndexOf('@'); * string[] top20TopDomains = { ".com", ".org", ".edu", ".gov", ".uk", ".net", ".ca", ".de", ".jp", ".fr", ".au", ".us", ".ru", ".ch", ".it", ".nl", ".se", ".no", ".es", ".mil" }; * foreach(string topDomain in top20TopDomains) { * if(emailAndPassword.IndexOf(topDomain, atIndex, StringComparison.InvariantCultureIgnoreCase) > 0) { * int passwordIndex = emailAndPassword.IndexOf(topDomain, atIndex, StringComparison.InvariantCultureIgnoreCase) + topDomain.Length; * NetworkCredential cred = new NetworkCredential(session.ClientHost, session.ServerHost, "POP3", emailAndPassword.Substring(0, passwordIndex), emailAndPassword.Substring(passwordIndex), frame.Timestamp); * this.MainPacketHandler.OnCredentialDetected(new Events.CredentialEventArgs(cred)); * credentialFound = true; * this.updateCredential(cred, session); * } * * } * if(!credentialFound) { * //it might be some less popular domain name * int dotIndex = emailAndPassword.IndexOf('.', atIndex); * if(dotIndex > 0) { * int passwordIndex = dotIndex + 2;//just a guess, could be something else * if(passwordIndex < emailAndPassword.Length) { * NetworkCredential cred = new NetworkCredential(session.ClientHost, session.ServerHost, "POP3", emailAndPassword.Substring(0, passwordIndex), emailAndPassword.Substring(passwordIndex), frame.Timestamp); * this.MainPacketHandler.OnCredentialDetected(new Events.CredentialEventArgs(cred)); * credentialFound = true; * this.updateCredential(cred, session); * } * } * } * } * if(!credentialFound && emailAndPassword.Length > 0) { * NetworkCredential cred = new NetworkCredential(session.ClientHost, session.ServerHost, "POP3", emailAndPassword, emailAndPassword, frame.Timestamp); * this.MainPacketHandler.OnCredentialDetected(new Events.CredentialEventArgs(cred)); * } */ }
//public int ExtractData(NetworkTcpSession tcpSession, NetworkHost sourceHost, NetworkHost destinationHost, IEnumerable<PacketParser.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; * }*/ 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.Email email = new Mime.Email(smtpSession.DataStream, base.MainPacketHandler, tcpPacket, transferIsClientToServer, tcpSession, ApplicationLayerProtocol.Smtp, FileTransfer.FileStreamAssembler.FileAssmeblyRootLocation.destination); } } 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.Trim().StartsWith("LOGIN", StringComparison.InvariantCultureIgnoreCase)) { //if (requestCommandAndArgument.Value.ToUpper().Contains("LOGIN")) { smtpSession.State = SmtpSession.SmtpState.AuthLogin; //SMTP clients sometimes send the email address right away like this: "AUTH LOGIN aGVqaG9wcEBpbnRlcm5ldC5zZQ==" if (requestCommandAndArgument.Value.Length > "LOGIN ".Length) { try { string base64Username = requestCommandAndArgument.Value.Substring("LOGIN ".Length).Trim(); byte[] usernameBytes = System.Convert.FromBase64String(base64Username); smtpSession.Username = System.Text.ASCIIEncoding.ASCII.GetString(usernameBytes); } catch (ArgumentException) { } } } else if (requestCommandAndArgument.Value.Trim().StartsWith("PLAIN", StringComparison.InvariantCultureIgnoreCase)) { //AUTH PLAIN <base64-encoded username and password> smtpSession.State = SmtpSession.SmtpState.AuthLogin; //SMTP clients sometimes send the email address right away like this: "AUTH LOGIN aGVqaG9wcEBpbnRlcm5ldC5zZQ==" if (requestCommandAndArgument.Value.Length > "PLAIN ".Length) { try { string base64 = requestCommandAndArgument.Value.Substring("PLAIN ".Length).Trim(); NetworkCredential cred = SmtpPacketHandler.ExtractBase64EncodedAuthPlainCredential(base64, smtpPacket.ParentFrame, tcpSession, ApplicationLayerProtocol.Smtp); if (cred != null) { //this.MainPacketHandler.OnCredentialDetected(new Events.CredentialEventArgs(cred)); this.MainPacketHandler.AddCredential(cred); } } catch (ArgumentException) { } } } } 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; } else if (requestCommandAndArgument.Key.Equals(SmtpPacket.ClientCommands.STARTTLS.ToString(), StringComparison.InvariantCultureIgnoreCase)) { smtpSession.State = SmtpSession.SmtpState.StartTlsRequested; } } } } 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" { if (smtpSession.State == SmtpSession.SmtpState.Footer) { //smtpSession.DataStream.Seek(0, System.IO.SeekOrigin.Begin); smtpSession.DataStream = new System.IO.MemoryStream(); //System.Diagnostics.Debugger.Break(); } smtpSession.State = SmtpSession.SmtpState.None;//Added in order to reset state when multiple SMTP sessions are sent within the same TCP session } else if (replyCodeAndArgument.Key == 220) { if (smtpSession.State == SmtpSession.SmtpState.StartTlsRequested) { tcpSession.ProtocolFinder.SetConfirmedApplicationLayerProtocol(ApplicationLayerProtocol.Ssl, false); } } } } //There was a SMTP packet, so treat this as a sucsessfull extraction return(tcpPacket.PayloadDataLength); } else //smtpPacket == null { return(0); } }
//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); } }