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;
            }
        }