private void ExtractSmbData(NetworkTcpSession tcpSession, bool transferIsClientToServer, Packets.TcpPacket tcpPacket, Packets.SmbPacket.AbstractSmbCommand smbCommandPacket, PacketHandler mainPacketHandler) { 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; } string smbSessionId; if (smbCommandPacket.ParentCifsPacket.FlagsResponse) { smbSessionId = SmbSession.GetSmbSessionId(sourceHost.IPAddress, tcpPacket.SourcePort, destinationHost.IPAddress, tcpPacket.DestinationPort); } else { smbSessionId = SmbSession.GetSmbSessionId(destinationHost.IPAddress, tcpPacket.DestinationPort, sourceHost.IPAddress, tcpPacket.SourcePort); } if (smbCommandPacket.GetType() == typeof(Packets.SmbPacket.NegotiateProtocolRequest)) { Packets.SmbPacket.NegotiateProtocolRequest request = (Packets.SmbPacket.NegotiateProtocolRequest)smbCommandPacket; sourceHost.AcceptedSmbDialectsList = request.DialectList; } else if (smbCommandPacket.GetType() == typeof(Packets.SmbPacket.NegotiateProtocolResponse)) { Packets.SmbPacket.NegotiateProtocolResponse reply = (Packets.SmbPacket.NegotiateProtocolResponse)smbCommandPacket; if (destinationHost.AcceptedSmbDialectsList != null && destinationHost.AcceptedSmbDialectsList.Count > reply.DialectIndex) { sourceHost.PreferredSmbDialect = destinationHost.AcceptedSmbDialectsList[reply.DialectIndex]; } //sourceHost.ExtraDetailsList.Add("Preferred SMB dialect", destinationHost.AcceptedSmbDialectsList[reply.DialectIndex]); } else if (smbCommandPacket.GetType() == typeof(Packets.SmbPacket.TreeConnectAndXRequest)) { Packets.SmbPacket.TreeConnectAndXRequest request = (Packets.SmbPacket.TreeConnectAndXRequest)smbCommandPacket; if (request.ShareName != null && request.ShareName.Length > 0) { destinationHost.AddNumberedExtraDetail("SMB File Share", request.ShareName); System.Collections.Specialized.NameValueCollection parameters = new System.Collections.Specialized.NameValueCollection(); parameters.Add("SMB Tree Connect AndX Request " + request.ParentCifsPacket.MultiplexId.ToString(), request.ShareName); mainPacketHandler.OnParametersDetected(new Events.ParametersEventArgs(smbCommandPacket.ParentFrame.FrameNumber, tcpSession.Flow.FiveTuple, transferIsClientToServer, parameters, smbCommandPacket.ParentFrame.Timestamp, "SMB Tree Connect AndX Request")); SmbSession smbSession; if (this.smbSessionPopularityList.ContainsKey(smbSessionId)) { smbSession = this.smbSessionPopularityList[smbSessionId]; } else { smbSession = new SmbSession(destinationHost.IPAddress, tcpPacket.DestinationPort, sourceHost.IPAddress, tcpPacket.SourcePort); this.smbSessionPopularityList.Add(smbSessionId, smbSession); } smbSession.AddTreeConnectAndXRequestPath(smbCommandPacket.ParentCifsPacket.UserId, smbCommandPacket.ParentCifsPacket.MultiplexId, request.ShareName); } } else if (smbCommandPacket.GetType() == typeof(Packets.SmbPacket.TreeConnectAndXResponse)) { SmbSession smbSession; if (this.smbSessionPopularityList.ContainsKey(smbSessionId)) { smbSession = this.smbSessionPopularityList[smbSessionId]; } else { smbSession = new SmbSession(sourceHost.IPAddress, tcpPacket.SourcePort, destinationHost.IPAddress, tcpPacket.DestinationPort); this.smbSessionPopularityList.Add(smbSessionId, smbSession); } smbSession.StoreTreeConnectAndXRequestPathForTree(smbCommandPacket.ParentCifsPacket.UserId, smbCommandPacket.ParentCifsPacket.MultiplexId, smbCommandPacket.ParentCifsPacket.TreeId); } else if (smbCommandPacket.GetType() == typeof(Packets.SmbPacket.SetupAndXRequest)) { Packets.SmbPacket.SetupAndXRequest request = (Packets.SmbPacket.SetupAndXRequest)smbCommandPacket; if (request.NativeLanManager != null && request.NativeLanManager.Length > 0) { if (sourceHost.ExtraDetailsList.ContainsKey("SMB Native LAN Manager")) { sourceHost.ExtraDetailsList["SMB Native LAN Manager"] = request.NativeLanManager; } else { sourceHost.ExtraDetailsList.Add("SMB Native LAN Manager", request.NativeLanManager); } } if (request.NativeOs != null && request.NativeOs.Length > 0) { if (sourceHost.ExtraDetailsList.ContainsKey("SMB Native OS")) { sourceHost.ExtraDetailsList["SMB Native OS"] = request.NativeOs; } else { sourceHost.ExtraDetailsList.Add("SMB Native OS", request.NativeOs); } } if (request.PrimaryDomain != null && request.PrimaryDomain.Length > 0) { sourceHost.AddDomainName(request.PrimaryDomain); } if (request.AccountName != null && request.AccountName.Length > 0) { NetworkCredential nCredential = new NetworkCredential(sourceHost, destinationHost, smbCommandPacket.PacketTypeDescription, request.AccountName, request.ParentFrame.Timestamp); if (request.AccountPassword != null && request.AccountPassword.Length > 0) { nCredential.Password = request.AccountPassword; } mainPacketHandler.AddCredential(nCredential); } } else if (smbCommandPacket.GetType() == typeof(Packets.SmbPacket.SetupAndXResponse)) { Packets.SmbPacket.SetupAndXResponse response = (Packets.SmbPacket.SetupAndXResponse)smbCommandPacket; if (response.NativeLanManager != null && response.NativeLanManager.Length > 0) { if (sourceHost.ExtraDetailsList.ContainsKey("SMB Native LAN Manager")) { sourceHost.ExtraDetailsList["SMB Native LAN Manager"] = response.NativeLanManager; } else { sourceHost.ExtraDetailsList.Add("SMB Native LAN Manager", response.NativeLanManager); } } if (response.NativeOs != null && response.NativeOs.Length > 0) { if (sourceHost.ExtraDetailsList.ContainsKey("SMB Native OS")) { sourceHost.ExtraDetailsList["SMB Native OS"] = response.NativeOs; } else { sourceHost.ExtraDetailsList.Add("SMB Native OS", response.NativeOs); } } } else if (smbCommandPacket.GetType() == typeof(Packets.SmbPacket.NTCreateAndXRequest)) { Packets.SmbPacket.NTCreateAndXRequest request = (Packets.SmbPacket.NTCreateAndXRequest)smbCommandPacket; string filename, filePath; if (request.Filename.EndsWith("\0")) { filename = request.Filename.Remove(request.Filename.Length - 1); } else { filename = request.Filename; } //print raw filename on parameters tab System.Collections.Specialized.NameValueCollection parameters = new System.Collections.Specialized.NameValueCollection(); parameters.Add("SMB NT Create AndX Request " + request.ParentCifsPacket.MultiplexId.ToString(), filename); base.MainPacketHandler.OnParametersDetected(new Events.ParametersEventArgs(request.ParentFrame.FrameNumber, tcpSession.Flow.FiveTuple, transferIsClientToServer, parameters, request.ParentFrame.Timestamp, "SMB NTCreateAndXRequest")); SmbSession smbSession; if (this.smbSessionPopularityList.ContainsKey(smbSessionId)) { smbSession = this.smbSessionPopularityList[smbSessionId]; } else { smbSession = new SmbSession(destinationHost.IPAddress, tcpPacket.DestinationPort, sourceHost.IPAddress, tcpPacket.SourcePort); this.smbSessionPopularityList.Add(smbSessionId, smbSession); } string treePath = smbSession.GetPathForTree(smbCommandPacket.ParentCifsPacket.TreeId); if (treePath == null) { filePath = ""; } else { filePath = treePath + System.IO.Path.DirectorySeparatorChar; } if (System.IO.Path.DirectorySeparatorChar != '\\' && filename.Contains("\\")) { filename.Replace('\\', System.IO.Path.DirectorySeparatorChar); } if (filename.Contains(System.IO.Path.DirectorySeparatorChar.ToString())) { filePath += filename.Substring(0, filename.LastIndexOf(System.IO.Path.DirectorySeparatorChar.ToString())); filename = filename.Substring(filename.LastIndexOf(System.IO.Path.DirectorySeparatorChar.ToString()) + 1); } else { filePath += System.IO.Path.DirectorySeparatorChar.ToString(); } try { FileTransfer.FileStreamAssembler assembler = new FileTransfer.FileStreamAssembler(mainPacketHandler.FileStreamAssemblerList, tcpSession.Flow.FiveTuple, !transferIsClientToServer, FileTransfer.FileStreamTypes.SMB, filename, filePath, filePath + filename, smbCommandPacket.ParentFrame.FrameNumber, smbCommandPacket.ParentFrame.Timestamp); smbSession.AddFileStreamAssembler(assembler, request.ParentCifsPacket.TreeId, request.ParentCifsPacket.MultiplexId, request.ParentCifsPacket.ProcessId); } catch (Exception e) { MainPacketHandler.OnAnomalyDetected("Error creating assembler for SMB file transfer: " + e.Message); } } //else if(!smbCommandPacket.ParentCifsPacket.FlagsResponse && mainPacketHandler.FileStreamAssemblerList.ContainsAssembler(destinationHost, tcpPacket.DestinationPort, sourceHost, tcpPacket.SourcePort, true)) { else if (!smbCommandPacket.ParentCifsPacket.FlagsResponse && this.smbSessionPopularityList.ContainsKey(smbSessionId)) { //Request if (smbCommandPacket.GetType() == typeof(Packets.SmbPacket.CloseRequest) && smbSessionPopularityList.ContainsKey(smbSessionId)) { SmbSession smbSession = this.smbSessionPopularityList[smbSessionId]; Packets.SmbPacket.CloseRequest closeRequest = (Packets.SmbPacket.CloseRequest)smbCommandPacket; ushort fileId = closeRequest.FileId; //FileTransfer.FileStreamAssembler assemblerToClose; if (smbSession.ContainsFileId(closeRequest.ParentCifsPacket.TreeId, closeRequest.ParentCifsPacket.MultiplexId, closeRequest.ParentCifsPacket.ProcessId, fileId)) { FileTransfer.FileStreamAssembler assemblerToClose = smbSession.GetFileStreamAssembler(closeRequest.ParentCifsPacket.TreeId, closeRequest.ParentCifsPacket.MultiplexId, closeRequest.ParentCifsPacket.ProcessId, fileId); if (assemblerToClose != null && assemblerToClose.AssembledByteCount >= assemblerToClose.FileContentLength) { assemblerToClose.FinishAssembling(); } FileTransfer.FileSegmentAssembler segmentAssemblerToClose = smbSession.GetFileSegmentAssembler(closeRequest.ParentCifsPacket.TreeId, closeRequest.ParentCifsPacket.MultiplexId, closeRequest.ParentCifsPacket.ProcessId, fileId); if (segmentAssemblerToClose != null) { segmentAssemblerToClose.Close(); } smbSession.RemoveFileStreamAssembler(closeRequest.ParentCifsPacket.TreeId, closeRequest.ParentCifsPacket.MultiplexId, closeRequest.ParentCifsPacket.ProcessId, fileId, false); //TODO: remove the following line (added for debugging purpose 2011-04-25) //assemblerToClose.FinishAssembling(); if (mainPacketHandler.FileStreamAssemblerList.ContainsAssembler(assemblerToClose)) { mainPacketHandler.FileStreamAssemblerList.Remove(assemblerToClose, true); } else { assemblerToClose.Clear(); } } } else if (smbCommandPacket.GetType() == typeof(Packets.SmbPacket.ReadAndXRequest) && smbSessionPopularityList.ContainsKey(smbSessionId)) { SmbSession smbSession = this.smbSessionPopularityList[smbSessionId]; //Packets.CifsPacket.ReadAndXRequest request=this.smbSessionPopularityList[smbSessionId]; Packets.SmbPacket.ReadAndXRequest readRequest = (Packets.SmbPacket.ReadAndXRequest)smbCommandPacket; ushort fileId = readRequest.FileId; smbSession.Touch(readRequest.ParentCifsPacket.TreeId, readRequest.ParentCifsPacket.MultiplexId, readRequest.ParentCifsPacket.ProcessId, fileId); } else if (smbCommandPacket.GetType() == typeof(Packets.SmbPacket.WriteAndXRequest)) { SmbSession smbSession = this.smbSessionPopularityList[smbSessionId]; Packets.SmbPacket.WriteAndXRequest request = (Packets.SmbPacket.WriteAndXRequest)smbCommandPacket; FileTransfer.FileSegmentAssembler segmentAssembler = smbSession.GetFileSegmentAssembler(request.ParentCifsPacket.TreeId, request.ParentCifsPacket.MultiplexId, request.ParentCifsPacket.ProcessId, request.FileId); if (segmentAssembler == null) { string outputDir = System.IO.Path.GetDirectoryName(mainPacketHandler.OutputDirectory); FileTransfer.FileStreamAssembler tmpAssembler = smbSession.GetFileStreamAssembler(request.ParentCifsPacket.TreeId, request.ParentCifsPacket.MultiplexId, request.ParentCifsPacket.ProcessId, request.FileId); if (tmpAssembler != null) { string filePath = tmpAssembler.FileLocation; if (filePath.Length == 0 || filePath.EndsWith("/")) { filePath += tmpAssembler.Filename; } else { filePath += "/" + tmpAssembler.Filename; } segmentAssembler = new FileTransfer.FileSegmentAssembler(outputDir, tcpSession, false, filePath, tcpSession.ToString() + "SMB" + request.FileId.ToString(), mainPacketHandler.FileStreamAssemblerList, null, FileTransfer.FileStreamTypes.SMB, "SMB Write " + tmpAssembler.Details, null); smbSession.AddFileSegmentAssembler(segmentAssembler, request.FileId); } } if (segmentAssembler != null) { segmentAssembler.AddData(request.WriteOffset, request.GetFileData(), request.ParentFrame); } } } else if (smbCommandPacket.ParentCifsPacket.FlagsResponse && this.smbSessionPopularityList.ContainsKey(smbSessionId)) { //Response SmbSession smbSession = this.smbSessionPopularityList[smbSessionId]; //FileTransfer.FileStreamAssembler assembler=mainPacketHandler.FileStreamAssemblerList.GetAssembler(sourceHost, tcpPacket.SourcePort, destinationHost, tcpPacket.DestinationPort, true); if (smbCommandPacket.GetType() == typeof(Packets.SmbPacket.NTCreateAndXResponse)) { Packets.SmbPacket.NTCreateAndXResponse response = (Packets.SmbPacket.NTCreateAndXResponse)smbCommandPacket; ushort fileId = response.FileId; int fileLength = (int)response.EndOfFile;//yes, I know I will not be able to store big files now... but an int as length is really enough! //tag the requested file with the fileId FileTransfer.FileStreamAssembler assembler = smbSession.GetLastReferencedFileStreamAssembler(response.ParentCifsPacket.TreeId, response.ParentCifsPacket.MultiplexId, response.ParentCifsPacket.ProcessId); smbSession.RemoveLastReferencedAssembler(response.ParentCifsPacket.TreeId, response.ParentCifsPacket.MultiplexId, response.ParentCifsPacket.ProcessId); if (assembler != null) { //Add file ID as extended ID in order to differentiate between parallell file transfers on disk cache assembler.ExtendedFileId = "Id" + fileId.ToString("X4"); //2011-04-18 smbSession.AddFileStreamAssembler(assembler, response.ParentCifsPacket.TreeId, response.ParentCifsPacket.MultiplexId, response.ParentCifsPacket.ProcessId, response.FileId); assembler.FileContentLength = fileLength; } } else if (smbCommandPacket.GetType() == typeof(Packets.SmbPacket.ReadAndXResponse)) { Packets.SmbPacket.ReadAndXResponse response = (Packets.SmbPacket.ReadAndXResponse)smbCommandPacket; //move the assembler to the real FileStreamAssemblerList! FileTransfer.FileStreamAssembler assembler = smbSession.GetLastReferencedFileStreamAssembler(response.ParentCifsPacket.TreeId, response.ParentCifsPacket.MultiplexId, response.ParentCifsPacket.ProcessId); if (assembler == null) { base.MainPacketHandler.OnAnomalyDetected("Unable to find assembler for frame " + smbCommandPacket.ParentFrame.FrameNumber + " : " + smbCommandPacket.ToString()); } else if (assembler != null) { /* Removed 2011-04-25 * if(!mainPacketHandler.FileStreamAssemblerList.ContainsAssembler(assembler)) * mainPacketHandler.FileStreamAssemblerList.Add(assembler); * */ assembler.FileSegmentRemainingBytes += response.DataLength;//setting this one so that it can receive more bytes if (!assembler.IsActive) { System.Diagnostics.Debug.Assert(assembler.ExtendedFileId != null && assembler.ExtendedFileId != "", "No FileID set for SMB file transfer!"); if (!assembler.TryActivate()) { if (!response.ParentCifsPacket.ParentFrame.QuickParse) { response.ParentCifsPacket.ParentFrame.Errors.Add(new Frame.Error(response.ParentCifsPacket.ParentFrame, response.PacketStartIndex, response.PacketEndIndex, "Unable to activate file stream assembler for " + assembler.FileLocation + "/" + assembler.Filename)); } } else if (assembler.IsActive) { assembler.AddData(response.GetFileData(), tcpPacket.SequenceNumber); } } /* Removed 2011-04-25 * if(!assembler.IsActive) {//see if the file is fully assembled or if something else went wrong... * smbSession.RemoveLastReferencedAssembler(response.ParentCifsPacket.TreeId, response.ParentCifsPacket.MultiplexId, response.ParentCifsPacket.ProcessId); * } * */ } } } }
//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); }
private void ExtractData(ref NetworkHost sourceHost, NetworkHost destinationHost, Packets.DhcpPacket dhcpPacket) { if (dhcpPacket.OpCode == Packets.DhcpPacket.OpCodeValue.BootRequest && (sourceHost.MacAddress == null || dhcpPacket.ClientMacAddress != sourceHost.MacAddress)) { sourceHost.MacAddress = dhcpPacket.ClientMacAddress; } else if (dhcpPacket.OpCode == Packets.DhcpPacket.OpCodeValue.BootReply && (destinationHost.MacAddress == null || dhcpPacket.ClientMacAddress != destinationHost.MacAddress)) { destinationHost.MacAddress = dhcpPacket.ClientMacAddress; } if (dhcpPacket.OpCode == Packets.DhcpPacket.OpCodeValue.BootReply && (dhcpPacket.GatewayIpAddress != null && dhcpPacket.GatewayIpAddress != System.Net.IPAddress.None && dhcpPacket.GatewayIpAddress.Address > 0)) { destinationHost.ExtraDetailsList["Default Gateway"] = dhcpPacket.GatewayIpAddress.ToString(); } System.Collections.Specialized.NameValueCollection optionParameterList = new System.Collections.Specialized.NameValueCollection(); //now check all the DHCP options //byte dhcpMessageType=0x00;//1=Discover, 2=Offer, 3=Request, 5=Ack, 8=Inform foreach (Packets.DhcpPacket.Option option in dhcpPacket.OptionList) { //TODO: Add option to Parameters list if (option.OptionCode == 12)//hostname { string hostname = Utils.ByteConverter.ReadString(option.OptionValue); sourceHost.AddHostName(hostname); optionParameterList.Add("DHCP Option 12 Hostname", hostname); } else if (option.OptionCode == 15)//Domain Name { string domain = Utils.ByteConverter.ReadString(option.OptionValue); sourceHost.AddDomainName(domain); optionParameterList.Add("DHCP Option 15 Domain", domain); } else if (option.OptionCode == 50) //requested IP address { if (dhcpPacket.DhcpMessageType == 3) //Must be a DHCP Request { System.Net.IPAddress requestedIpAddress = new System.Net.IPAddress(option.OptionValue); if (sourceHost.IPAddress != requestedIpAddress) { if (!base.MainPacketHandler.NetworkHostList.ContainsIP(requestedIpAddress)) { NetworkHost clonedHost = new NetworkHost(requestedIpAddress); clonedHost.MacAddress = sourceHost.MacAddress; //foreach(string hostname in sourceHost.HostNameList) // clonedHost.AddHostName(hostname); lock (base.MainPacketHandler.NetworkHostList) base.MainPacketHandler.NetworkHostList.Add(clonedHost); //now change the host to the cloned one (and hope it works out...) sourceHost = clonedHost; } else { sourceHost = base.MainPacketHandler.NetworkHostList.GetNetworkHost(requestedIpAddress); if (dhcpPacket.OpCode == Packets.DhcpPacket.OpCodeValue.BootRequest && (sourceHost.MacAddress == null || dhcpPacket.ClientMacAddress != sourceHost.MacAddress)) { sourceHost.MacAddress = dhcpPacket.ClientMacAddress; } } } if (sourceHost.MacAddress != null && previousIpList.ContainsKey(sourceHost.MacAddress.ToString())) { //if(previousIpList.ContainsKey(sourceHost.MacAddress.ToString())) { sourceHost.AddNumberedExtraDetail("Previous IP", previousIpList[sourceHost.MacAddress.ToString()].ToString()); //sourceHost.ExtraDetailsList["Previous IP"]=previousIpList[sourceHost.MacAddress.ToString()].ToString(); previousIpList.Remove(sourceHost.MacAddress.ToString()); } } else if (dhcpPacket.DhcpMessageType == 1)//DHCP discover //see which IP address the client hade previously //They normally requests the same IP as they hade before... { System.Net.IPAddress requestedIpAddress = new System.Net.IPAddress(option.OptionValue); this.previousIpList[sourceHost.MacAddress.ToString()] = requestedIpAddress; } } /* * else if(option.OptionCode==53) {//DHCP message type * if(option.OptionValue!=null && option.OptionValue.Length==1) * dhcpMessageType=option.OptionValue[0]; * }/*/ else if (option.OptionCode == 60)//vendor class identifier { string vendorCode = Utils.ByteConverter.ReadString(option.OptionValue); sourceHost.AddDhcpVendorCode(vendorCode); optionParameterList.Add("DHCP Option 60 Vendor Code", vendorCode); } else if (option.OptionCode == 81) //Client Fully Qualified Domain Name { string domain = Utils.ByteConverter.ReadString(option.OptionValue, 3, option.OptionValue.Length - 3); sourceHost.AddHostName(domain); optionParameterList.Add("DHCP Option 81 Domain", domain); } else if (option.OptionCode == 125) //V-I Vendor-specific Information http://tools.ietf.org/html/rfc3925 { uint enterpriceNumber = Utils.ByteConverter.ToUInt32(option.OptionValue, 0); optionParameterList.Add("DHCP Option 125 Enterprise Number", enterpriceNumber.ToString()); byte dataLen = option.OptionValue[4]; if (dataLen > 0 && option.OptionValue.Length >= 5 + dataLen) { string optionData = Utils.ByteConverter.ReadString(option.OptionValue, 5, dataLen); optionParameterList.Add("DHCP Option 125 Data", optionData); } } else { string optionValueString = Utils.ByteConverter.ReadString(option.OptionValue); if (!System.Text.RegularExpressions.Regex.IsMatch(optionValueString, @"[^\u0020-\u007E]")) { optionParameterList.Add("DHCP Option " + option.OptionCode.ToString(), optionValueString); } } } if (optionParameterList.Count > 0) { //try to get the udp packet string sourcePort = "UNKNOWN"; string destinationPort = "UNKNOWN"; foreach (Packets.AbstractPacket p in dhcpPacket.ParentFrame.PacketList) { if (p.GetType() == typeof(Packets.UdpPacket)) { Packets.UdpPacket udpPacket = (Packets.UdpPacket)p; sourcePort = "UDP " + udpPacket.SourcePort; destinationPort = "UDP " + udpPacket.DestinationPort; break; } } Events.ParametersEventArgs ea = new Events.ParametersEventArgs(dhcpPacket.ParentFrame.FrameNumber, sourceHost, destinationHost, sourcePort, destinationPort, optionParameterList, dhcpPacket.ParentFrame.Timestamp, "DHCP Option"); MainPacketHandler.OnParametersDetected(ea); } }
public void ExtractData(ref NetworkHost sourceHost, NetworkHost destinationHost, IEnumerable <Packets.AbstractPacket> packetList) { Packets.DnsPacket dnsPacket = null; Packets.IIPPacket ipPacket = null; Packets.ITransportLayerPacket transportLayerPacket = null; foreach (Packets.AbstractPacket p in packetList) { if (p.GetType() == typeof(Packets.DnsPacket)) { dnsPacket = (Packets.DnsPacket)p; } else if (p is Packets.IIPPacket) { ipPacket = (Packets.IIPPacket)p; } /*else if(p.GetType()==typeof(Packets.IPv6Packet)) * ipv6Packet=(Packets.IPv6Packet)p;*/ else if (p is Packets.ITransportLayerPacket tlp) { transportLayerPacket = tlp; } } if (dnsPacket != null) { //ExtractDnsData(dnsPacket); if (dnsPacket.Flags.Response) { System.Collections.Specialized.NameValueCollection cNamePointers = new System.Collections.Specialized.NameValueCollection(); if (dnsPacket.AnswerRecords != null && dnsPacket.AnswerRecords.Length > 0) { foreach (Packets.DnsPacket.ResourceRecord r in dnsPacket.AnswerRecords) { if (r.IP != null) { if (!base.MainPacketHandler.NetworkHostList.ContainsIP(r.IP)) { NetworkHost host = new NetworkHost(r.IP); host.AddHostName(r.DNS, dnsPacket.PacketTypeDescription); lock (base.MainPacketHandler.NetworkHostList) base.MainPacketHandler.NetworkHostList.Add(host); MainPacketHandler.OnNetworkHostDetected(new Events.NetworkHostEventArgs(host)); //base.MainPacketHandler.ParentForm.ShowDetectedHost(host); } else { base.MainPacketHandler.NetworkHostList.GetNetworkHost(r.IP).AddHostName(r.DNS, dnsPacket.PacketTypeDescription); } if (cNamePointers[r.DNS] != null) { base.MainPacketHandler.NetworkHostList.GetNetworkHost(r.IP).AddHostName(cNamePointers[r.DNS], dnsPacket.PacketTypeDescription); } } else if (r.Type == (ushort)Packets.DnsPacket.RRTypes.CNAME) { cNamePointers.Add(r.PrimaryName, r.DNS); } MainPacketHandler.OnDnsRecordDetected(new Events.DnsRecordEventArgs(r, sourceHost, destinationHost, ipPacket, transportLayerPacket)); //base.MainPacketHandler.ParentForm.ShowDnsRecord(r, sourceHost, destinationHost, ipPakcet, udpPacket); } } else { //display the flags instead //TODO : MainPacketHandler.OnDnsRecordDetected(new Events.DnsRecordEventArgs( if (dnsPacket.QueriedDnsName != null && dnsPacket.QueriedDnsName.Length > 0) { MainPacketHandler.OnDnsRecordDetected(new Events.DnsRecordEventArgs(new Packets.DnsPacket.ResponseWithErrorCode(dnsPacket), sourceHost, destinationHost, ipPacket, transportLayerPacket)); } } } else //DNS request { if (dnsPacket.QueriedDnsName != null && dnsPacket.QueriedDnsName.Length > 0) { sourceHost.AddQueriedDnsName(dnsPacket.QueriedDnsName); } } } }
public void ExtractData(ref NetworkHost sourceHost, NetworkHost destinationHost, IEnumerable <Packets.AbstractPacket> packetList) { Packets.UdpPacket udpPacket = null; Packets.TftpPacket tftpPacket = null; foreach (Packets.AbstractPacket p in packetList) { if (p.GetType() == typeof(Packets.UdpPacket)) { udpPacket = (Packets.UdpPacket)p; } else if (p.GetType() == typeof(Packets.TftpPacket)) { tftpPacket = (Packets.TftpPacket)p; } } if (udpPacket != null) { FileTransfer.FileStreamAssembler assembler; if (TryGetTftpFileStreamAssembler(out assembler, base.MainPacketHandler.FileStreamAssemblerList, sourceHost, udpPacket.SourcePort, destinationHost, udpPacket.DestinationPort) || (tftpPacket != null && TryCreateNewAssembler(out assembler, base.MainPacketHandler.FileStreamAssemblerList, tftpPacket, sourceHost, udpPacket.SourcePort, destinationHost))) { //we have an assembler! string sessionId = this.GetTftpSessionId(sourceHost, udpPacket.SourcePort, destinationHost, udpPacket.DestinationPort); ushort blksize = 512;//default if (this.tftpSessionBlksizeList.ContainsKey(sessionId)) { blksize = this.tftpSessionBlksizeList[sessionId]; } //but we might not have a TFTP packet since it is likely to run over a random port if (tftpPacket == null || tftpPacket.Blksize != blksize) { try { tftpPacket = new Packets.TftpPacket(udpPacket.ParentFrame, udpPacket.PacketStartIndex + 8, udpPacket.PacketEndIndex, blksize);//this is not very pretty since the UDP header length is hardcoded to be 8. if (tftpPacket.Blksize != blksize) { if (this.tftpSessionBlksizeList.ContainsKey(sessionId)) { this.tftpSessionBlksizeList[sessionId] = tftpPacket.Blksize; } else { this.tftpSessionBlksizeList.Add(sessionId, tftpPacket.Blksize); } } } catch (Exception e) { if (assembler != null) { MainPacketHandler.OnAnomalyDetected("Error parsing TFTP packet: " + e.Message, udpPacket.ParentFrame.Timestamp); } } } //see if we have an tftp pakcet and parse its file data if (tftpPacket != null) { ExtractFileData(assembler, base.MainPacketHandler.FileStreamAssemblerList, sourceHost, udpPacket.SourcePort, destinationHost, udpPacket.DestinationPort, tftpPacket); } } }//end if udpPacket }
public int ExtractData(NetworkTcpSession tcpSession, bool transferIsClientToServer, IEnumerable <PacketParser.Packets.AbstractPacket> packetList) { Packets.Pop3Packet pop3Packet = 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.Pop3Packet)) { pop3Packet = (Packets.Pop3Packet)p; } } if (tcpPacket != null && tcpPacket.SourcePort == 110 && this.pop3LastCommand.ContainsKey(tcpSession) && this.pop3LastCommand[tcpSession] == Pop3Packet.ClientCommand.RETR && this.emailReassemblers.ContainsKey(tcpSession)) { return(this.ExtractEmail(tcpSession, tcpPacket, tcpPacket.PacketStartIndex + tcpPacket.DataOffsetByteCount, tcpPacket.PayloadDataLength)); } else if (pop3Packet != null && tcpPacket != null) { if (pop3Packet.PacketHeaderIsComplete) { int bytesParsedAfterHeader = 0; if (pop3Packet.FullRequestOrResponseLine != null && pop3Packet.FullRequestOrResponseLine.Length > 0) { System.Collections.Specialized.NameValueCollection parms = new System.Collections.Specialized.NameValueCollection(); string command = pop3Packet.GetCommandOrResponse(); parms.Add(command, pop3Packet.GetCommandOrResponseArguments()); if (pop3Packet.ClientToServer) { 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; } base.MainPacketHandler.OnParametersDetected(new Events.ParametersEventArgs(pop3Packet.ParentFrame.FrameNumber, tcpSession.Flow.FiveTuple, transferIsClientToServer, parms, pop3Packet.ParentFrame.Timestamp, "POP3 Command")); //See if there are additional lines after the command if (Enum.IsDefined(typeof(Pop3Packet.ClientCommand), command.ToUpper())) { Pop3Packet.ClientCommand clientCommand = (Pop3Packet.ClientCommand)Enum.Parse(typeof(Pop3Packet.ClientCommand), command.ToUpper()); //remove any old email reassemblers since we have now received a new command if (this.emailReassemblers.ContainsKey(tcpSession)) { this.emailReassemblers[tcpSession].Close(); this.emailReassemblers.Remove(tcpSession);//we will need to create a new reassembler } /** * https://tools.ietf.org/html/rfc1939 * If an argument was given and the POP3 server issues a * positive response with a line containing information for * that message. * If no argument was given and the POP3 server issues a * positive response, then the response given is multi-line. **/ if (clientCommand == Pop3Packet.ClientCommand.LIST && pop3Packet.FullRequestOrResponseLine.Length > 5) { clientCommand = Pop3Packet.ClientCommand.LIST_WITH_ARGS; } else if (clientCommand == Pop3Packet.ClientCommand.UIDL && pop3Packet.FullRequestOrResponseLine.Length > 5) { clientCommand = Pop3Packet.ClientCommand.UIDL_WITH_ARGS; } if (clientCommand == Pop3Packet.ClientCommand.USER) { if (pop3Packet.GetCommandOrResponseArguments().Length > 0) { NetworkCredential credential = new NetworkCredential(sourceHost, destinationHost, "POP3", pop3Packet.GetCommandOrResponseArguments(), pop3Packet.ParentFrame.Timestamp); //this.pop3Credentials.Add(tcpSession, credential); this.updateCredential(credential, tcpSession); } } else if (clientCommand == Pop3Packet.ClientCommand.PASS) { if (this.pop3Credentials.ContainsKey(tcpSession)) { NetworkCredential credential = this.pop3Credentials[tcpSession]; credential.Password = pop3Packet.GetCommandOrResponseArguments(); //this.MainPacketHandler.OnCredentialDetected(new Events.CredentialEventArgs(credential)); this.MainPacketHandler.AddCredential(credential); } } else if (clientCommand == Pop3Packet.ClientCommand.AUTH) { string authArgs = pop3Packet.GetCommandOrResponseArguments(); if (authArgs.StartsWith("PLAIN", StringComparison.InvariantCultureIgnoreCase)) { clientCommand = Pop3Packet.ClientCommand.AUTH_PLAIN; if (authArgs.Trim().Length > 5) { //we have an in-line credential //AUTH PLAIN dGVzdAB0ZXN0AHRlc3RwYXNz //dGVzdAB0ZXN0AHRlc3RwYXNz == "test\0test\0pass" string emailAndPassword = authArgs.Substring(5).TrimStart(); this.extractBase64EncodedEmailAndPassword(emailAndPassword, pop3Packet.ParentFrame, tcpSession); } } } else if (clientCommand == Pop3Packet.ClientCommand.APOP) { //username is cleartext //password is MD5(nonce+password) /** * S: +OK POP3 server ready <*****@*****.**> * C: APOP mrose c4c9334bac560ecc979e58001b3e22fb * S: +OK maildrop has 1 message (369 octets) **/ string userAndHash = pop3Packet.GetCommandOrResponseArguments(); userAndHash = userAndHash.Trim(); int spaceIndex = userAndHash.IndexOf(' '); if (spaceIndex > 0 && spaceIndex < userAndHash.Length - 1) { string user = userAndHash.Substring(0, spaceIndex).Trim(); string hash = userAndHash.Substring(spaceIndex).Trim(); NetworkCredential cred = new NetworkCredential(tcpSession.ClientHost, tcpSession.ServerHost, "POP3", user, "APOP hash: " + hash, pop3Packet.ParentFrame.Timestamp); //MainPacketHandler.OnCredentialDetected(new Events.CredentialEventArgs(cred)); MainPacketHandler.AddCredential(cred); } } else if (clientCommand == Pop3Packet.ClientCommand.RETR) { //clear all previous server-to-client data in case there is still some trailing data from the previous command that hasn't been parsed yet int bytesInStream = tcpSession.ServerToClientTcpDataStream.CountBytesToRead(); if (bytesInStream > 0) { tcpSession.ServerToClientTcpDataStream.RemoveData(bytesInStream); } } if (this.pop3LastCommand.ContainsKey(tcpSession)) { this.pop3LastCommand[tcpSession] = clientCommand; } else { this.pop3LastCommand.Add(tcpSession, clientCommand); } } else { //unknown command. We might be seing a multi-line command //Check for last command if (this.pop3LastCommand.ContainsKey(tcpSession)) { if (this.pop3LastCommand[tcpSession] == Pop3Packet.ClientCommand.AUTH_PLAIN) { /** * C: AUTH PLAIN * S: + * C: dGVzdAB0ZXN0AHRlc3Q= **/ /** * Client: AUTH PLAIN * Server: + * Client: bmFtZUBleGFtcGxlLmNvbU15UGFzc3dvcmQK * Server: +OK mailbox "*****@*****.**" has 30 messages (1115683 octets) H migmx127 **/ this.extractBase64EncodedEmailAndPassword(pop3Packet.FullRequestOrResponseLine, tcpPacket.ParentFrame, tcpSession); //TODO parsa ovanstående i en ny funktion } } } } else { if (pop3Packet.GetCommandOrResponse() == Pop3Packet.RESPONSE_OK) { if (this.pop3LastCommand.ContainsKey(tcpSession)) { //consume all multi-line responses here if (this.pop3LastCommand[tcpSession] == Pop3Packet.ClientCommand.LIST_WITH_ARGS) { foreach (string s in pop3Packet.ReadResponseLines()) { //do nothing... just make sure all lines are read } } else if (this.pop3LastCommand[tcpSession] == Pop3Packet.ClientCommand.RETR) { /* * Utils.StreamReassembler reassembler; * if (this.emailReassemblers.ContainsKey(tcpSession)) * reassembler = this.emailReassemblers[tcpSession]; * else * reassembler = new Utils.StreamReassembler(Pop3Packet.MULTILINE_RESPONSE_TERMINATOR, 0); * * foreach (string line in pop3Packet.ReadResponseLines()) { * reassembler.AddData(line); * if (reassembler.TerminatorFound) * break; * } * if(reassembler.TerminatorFound) { * Mime.Email email = new Mime.Email(reassembler.DataStream, base.MainPacketHandler, tcpPacket, sourceHost, destinationHost, tcpSession, ApplicationLayerProtocol.Pop3); * } */ bytesParsedAfterHeader += this.ExtractEmail(tcpSession, tcpPacket, pop3Packet); } else if (this.pop3LastCommand[tcpSession] == Pop3Packet.ClientCommand.TOP) { foreach (string s in pop3Packet.ReadResponseLines()) { //do nothing... just make sure all lines are read } } if (this.pop3LastCommand[tcpSession] == Pop3Packet.ClientCommand.UIDL_WITH_ARGS) { foreach (string s in pop3Packet.ReadResponseLines()) { //do nothing... just make sure all lines are read } } else if (pop3Packet.ParsedBytesCount < pop3Packet.PacketEndIndex - pop3Packet.PacketStartIndex + 1) { foreach (string s in pop3Packet.ReadResponseLines()) { //do nothing... just make sure all lines are read } } //parse single line details from responses here } else if (pop3Packet.PacketHeaderIsComplete) { if (pop3Packet.GetCommandOrResponseArguments().Length > 0) { tcpSession.Flow.FiveTuple.ServerHost.AddNumberedExtraDetail("POP3 Banner", pop3Packet.GetCommandOrResponseArguments()); } } if (pop3Packet.PacketHeaderIsComplete) { 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; } base.MainPacketHandler.OnParametersDetected(new Events.ParametersEventArgs(pop3Packet.ParentFrame.FrameNumber, tcpSession.Flow.FiveTuple, transferIsClientToServer, parms, pop3Packet.ParentFrame.Timestamp, "POP3 Response")); } } } } return(pop3Packet.ParsedBytesCount + bytesParsedAfterHeader); } else if (!pop3Packet.ClientToServer) //invalid response received from Server { if (this.pop3LastCommand.ContainsKey(tcpSession) && this.pop3LastCommand[tcpSession] == Pop3Packet.ClientCommand.RETR) { //reassemble a segment of an email here return(pop3Packet.ParsedBytesCount + this.ExtractEmail(tcpSession, tcpPacket, pop3Packet)); } else if (pop3Packet.ParentFrame.Data[pop3Packet.PacketStartIndex] == '+') { //special handling of responses like "+ " for AUTH PLAIN to indicate that more data is expected from the client int index = pop3Packet.PacketStartIndex; string line = Utils.ByteConverter.ReadLine(pop3Packet.ParentFrame.Data, ref index); return(index - pop3Packet.PacketStartIndex); } else { return(0); } } else { return(0); } } else { 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) { Packets.SocksPacket socksPacket = 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.SocksPacket)) { socksPacket = (Packets.SocksPacket)p; } } if (socksPacket != null && tcpPacket != null) { string paramName = "SOCKS"; if (socksPacket.ClientToServer) { if (socksPacket.CommandOrReply == 1) { paramName += " Connect"; if (!this.socksConnectIpPorts.ContainsKey(tcpSession)) { if (socksPacket.IpAddress != null) { this.socksConnectIpPorts.Add(tcpSession, new KeyValuePair <System.Net.IPAddress, ushort>(socksPacket.IpAddress, socksPacket.Port)); } else { this.socksConnectIpPorts.Add(tcpSession, new KeyValuePair <System.Net.IPAddress, ushort>(tcpSession.ClientHost.IPAddress, socksPacket.Port)); } } } else if (socksPacket.CommandOrReply == 2) { paramName += " Bind"; } else if (socksPacket.CommandOrReply == 3) { paramName += " DNS Associate"; } if (socksPacket.Username != null && socksPacket.Password != null) { //base.MainPacketHandler.OnCredentialDetected(new Events.CredentialEventArgs(new NetworkCredential(tcpSession.ClientHost, tcpSession.ServerHost, "SOCKS", socksPacket.Username, socksPacket.Password, socksPacket.ParentFrame.Timestamp))); base.MainPacketHandler.AddCredential(new NetworkCredential(tcpSession.ClientHost, tcpSession.ServerHost, "SOCKS", socksPacket.Username, socksPacket.Password, socksPacket.ParentFrame.Timestamp)); } } else { if (socksPacket.CommandOrReply == 0) { paramName += " Bind Succeeded"; if (this.socksConnectIpPorts.ContainsKey(tcpSession)) { KeyValuePair <System.Net.IPAddress, ushort> target = this.socksConnectIpPorts[tcpSession]; ushort serverPort = target.Value; NetworkHost serverHost; if (base.MainPacketHandler.NetworkHostList.ContainsIP(target.Key)) { serverHost = base.MainPacketHandler.NetworkHostList.GetNetworkHost(target.Key); } else { serverHost = tcpSession.ClientHost; } tcpSession.ProtocolFinder = new TcpPortProtocolFinder(tcpSession.Flow, tcpPacket.ParentFrame.FrameNumber, base.MainPacketHandler, serverHost, serverPort); } } else if (socksPacket.CommandOrReply == 1) { paramName += " General SOCKS server failure"; } else if (socksPacket.CommandOrReply == 2) { paramName += " Connection not allowed by ruleset"; } else if (socksPacket.CommandOrReply == 3) { paramName += " Network unreachable"; } else if (socksPacket.CommandOrReply == 4) { paramName += " Host unreachable"; } else if (socksPacket.CommandOrReply == 5) { paramName += " Connection refused"; } else if (socksPacket.CommandOrReply == 6) { paramName += " TTL expired"; } else if (socksPacket.CommandOrReply == 7) { paramName += " Command not supported"; } else if (socksPacket.CommandOrReply == 8) { paramName += " Address type not supported"; } } if (socksPacket.ATyp == SocksPacket.ATYP.DOMAINNAME) { System.Collections.Specialized.NameValueCollection parms = new System.Collections.Specialized.NameValueCollection(); parms.Add(paramName, socksPacket.DomainName + ":" + socksPacket.Port.ToString()); MainPacketHandler.OnParametersDetected(new Events.ParametersEventArgs(socksPacket.ParentFrame.FrameNumber, tcpSession.Flow.FiveTuple, transferIsClientToServer, parms, socksPacket.ParentFrame.Timestamp, "SOCKS Connection")); } else if (socksPacket.ATyp == SocksPacket.ATYP.IPv4 || socksPacket.ATyp == SocksPacket.ATYP.IPv6) { System.Collections.Specialized.NameValueCollection parms = new System.Collections.Specialized.NameValueCollection(); parms.Add(paramName, socksPacket.IpAddress.ToString() + ":" + socksPacket.Port.ToString()); MainPacketHandler.OnParametersDetected(new Events.ParametersEventArgs(socksPacket.ParentFrame.FrameNumber, tcpSession.Flow.FiveTuple, transferIsClientToServer, parms, socksPacket.ParentFrame.Timestamp, "SOCKS Connection")); } } if (socksPacket != null) { return(socksPacket.ParsedBytesCount); } else { return(0); } }