public void OnReadWritePacketReceived(dm_NotifyHdr notificationHeader, dm_ReadWriteNotifyParams writeParams, byte[] data, bool isWriting) { UInt64 fileObject = writeParams.fileIdentifier; UInt32 processId = notificationHeader.processId; if (!chromeMonitor.IsChromeProcess(processId)) { return; } // Find out on which pipe this packet was sent NamedPipeInfo pipe = DeterminePipeFromPacket(notificationHeader, writeParams); string pipeName = pipe != null ? pipe.PipeFileName : "<Unknown " + fileObject.ToString("X") + ">"; if (pipe != null) { // Update this pipe's information namedPipeFiles[pipeName].AddProcessIfNeeded(processId); namedPipeFiles[pipeName].AddFileObjectIfNeeded(fileObject); } if (!pipeName.Contains(this.pipeNameFilter)) { return; } // // Find out what is the destination process of this packet // UInt32 destinationPID = 0; if (pipe != null) { if (pipe.InvolvedProcesses.Count < 2 && !destoryedNamedPipes.Contains(pipe.PipeFileName)) { // // try to find the destination process using Windows handle query // List <int> legalPIDs = ChromeMonitor.GetRunningChromeProcesses().Select(process => process.Id).ToList(); string fullPipePath = @"\Device\NamedPipe" + pipe.PipeFileName; namedPipeFiles[pipeName].InvolvedProcesses = HandlesUtility.GetProcessesUsingFile(fullPipePath, legalPIDs); if (namedPipeFiles[pipeName].InvolvedProcesses.Count < 2) { // TODO: because we are doing heavy caching on the handle information, // it happens sometimes that we reach here but the pipe actually is in fact valid. //Console.WriteLine("[-] Could not find destination PID for " + pipeName); destoryedNamedPipes.Add(pipe.PipeFileName); } } if (pipe.InvolvedProcesses.Count >= 2) { List <uint> involvedProcesses = pipe.InvolvedProcesses.ToList(); involvedProcesses.Remove(notificationHeader.processId); destinationPID = involvedProcesses.Last(); } } if (!isWriting) { return; } if (data.Length == 0) { return; } // // Send it off // this.numPacketsProcessed++; byte[] wiresharkPacket = GenerateWiresharkPacket(notificationHeader, writeParams, pipeName, destinationPID, data); wiresharkSender.SendToWiresharkAsEthernet(wiresharkPacket, 0); }
public NamedPipeInfo DeterminePipeFromPacket(dm_NotifyHdr notificationHeader, dm_ReadWriteNotifyParams writeParams) { UInt64 fileObject = writeParams.fileIdentifier; // Search for the pipe by the file object List <NamedPipeInfo> matchingPipes = namedPipeFiles.Values.Where((x) => x.FileObjects.Contains(fileObject)).ToList(); if (matchingPipes.Count == 1) { return(matchingPipes[0]); } if (destoryedNamedPipes.Contains(fileObject.ToString("X"))) { return(null); } if (matchingPipes.Count == 0) { // We didn't see this file object before. if (this.recordingOnlyNewMojoPipes) { // are we missing create packets? // we probably do, because we can't read fast enough. throw new Exception("I will not suffer inconsistencies."); } // // Try to get the pipe name from the file object // string pipeName = HandlesUtility.GetFilePathFromFileObject(new IntPtr((long)fileObject)); if (pipeName != null && pipeName.Contains(@"\Device\NamedPipe")) { pipeName = pipeName.Substring(@"\Device\NamedPipe".Length); if (!namedPipeFiles.ContainsKey(pipeName)) { // We don't know this pipe // create it then namedPipeFiles[pipeName] = new NamedPipeInfo(fileObject, pipeName, notificationHeader.processId); } return(namedPipeFiles[pipeName]); } else { // either the pipe does not exist anymore, or its handle was closed, or NtQueryObject got hang } } else { // this file object must be dead, because it's used in two pipes throw new Exception("I will not suffer inconsistencies."); } //Console.WriteLine("[-] Could not find pipe name for " + fileObject.ToString("X")); destoryedNamedPipes.Add(fileObject.ToString("X")); return(null); }
/// <summary> /// Continiously reads notification data from the kernel driver/buffering stream /// and heads it over to ProcessNotification /// </summary> public void ProcessingLoop() { BinaryReader sourceTdevStream = useExtraStreamBuffering ? new BinaryReader(this.tdevBufferedStream) : new BinaryReader(this.tdevStream.BaseStream); Stopwatch totalStopwatch = new Stopwatch(); totalStopwatch.Start(); long streamPosition = 0; double timePeek = 0; BinaryReader packetsReader; while (!isShuttingDown) { if (this.tdevBufferedStream != null) { this.tdevBufferedStream.OnDataAvailable.WaitOne(); } // Read the next bunch of packets packetsReader = new BinaryReader(new MemoryStream()); AppendToStream(sourceTdevStream.BaseStream, packetsReader.BaseStream, BLOCK_SIZE); Stopwatch sw = new Stopwatch(); sw.Start(); while (packetsReader.BaseStream.Position < packetsReader.BaseStream.Length) { long headerEndOffset = packetsReader.BaseStream.Position + Marshal.SizeOf(typeof(dm_NotifyHdr)); if (packetsReader.BaseStream.Length < headerEndOffset && tdevMonitor.ReadMode == dm_ReadMode.dm_ReadMode_Stream) { // We need to read more data so the notification header could be read completely long missingSize = headerEndOffset - packetsReader.BaseStream.Length; AppendToStream(sourceTdevStream.BaseStream, packetsReader.BaseStream, missingSize, true); } dm_NotifyHdr notificationHeader = packetsReader.ReadStruct <dm_NotifyHdr>(); if (notificationHeader.signature != 1852796276) { throw new Exception("Encountered bad signature (" + notificationHeader.signature + ") at position " + (streamPosition + packetsReader.BaseStream.Position) + "!"); } long notificationParamBeginOffset = packetsReader.BaseStream.Position; if ((notificationHeader.flags & (ushort)dm_NotifyFlag.dm_NotifyFlag_InsufficientBuffer) > 0) { BLOCK_SIZE *= 2; Console.WriteLine("[-] Buffer was not sufficient, increasing block size to " + BLOCK_SIZE); // skip this packet long remainingSize1 = (notificationParamBeginOffset + notificationHeader.paramSize) - packetsReader.BaseStream.Position; packetsReader.ReadBytes((int)remainingSize1); break; } if ((notificationHeader.flags & (ushort)dm_NotifyFlag.dm_NotifyFlag_DataDropped) > 0) { TimeSpan timeFromLastDrop = DateTime.Now - this.lastDropTime; if (timeFromLastDrop.TotalMilliseconds > 700) { Console.WriteLine("[-] Some packets were dropped."); } lastDropTime = DateTime.Now; } long paramsEndOffset = notificationParamBeginOffset + notificationHeader.paramSize; if (packetsReader.BaseStream.Length < paramsEndOffset && tdevMonitor.ReadMode == dm_ReadMode.dm_ReadMode_Stream) { // We need to read more data so the packet could be read completely long missingSize = paramsEndOffset - packetsReader.BaseStream.Length; AppendToStream(sourceTdevStream.BaseStream, packetsReader.BaseStream, missingSize, true); } ProcessNotification(notificationHeader, packetsReader); long remainingSize = (notificationParamBeginOffset + notificationHeader.paramSize) - packetsReader.BaseStream.Position; byte[] read = packetsReader.ReadBytes((int)remainingSize); } sw.Stop(); if (sw.Elapsed.TotalMilliseconds > timePeek) { timePeek = sw.Elapsed.TotalMilliseconds; } streamPosition += packetsReader.BaseStream.Position; } }