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);
        }
Example #2
0
        static void Main(string[] args)
        {
            Console.WriteLine();
            Console.WriteLine("Chrome IPC Sniffer v" + Assembly.GetExecutingAssembly().GetName().Version.ToString());
            Console.WriteLine();

            //
            // Parse the arguments
            //
            bool onlyNewPipes             = false;
            bool forceFetchInterfacesInfo = false;
            bool forceExtractMethodNames  = false;
            bool onlyMojo = false;

            foreach (string argument in args)
            {
                if (argument.Contains("--update-interfaces-info"))
                {
                    forceFetchInterfacesInfo = true; forceExtractMethodNames = true;
                }
                else if (argument.Contains("--only-new-mojo-pipes"))
                {
                    onlyNewPipes = true;
                }
                else if (argument.Contains("--extract-method-names"))
                {
                    forceExtractMethodNames = true;
                }
                else if (argument.Contains("--only-mojo"))
                {
                    onlyMojo = true;
                }
                else if (argument.Contains("-h") || argument.Contains("--help") || argument.Contains("/?"))
                {
                    ShowUsage(); return;
                }
                else
                {
                    Console.WriteLine("[!] Unrecognized argument '{0}'", argument);
                    return;
                }
            }

            Console.WriteLine("Type -h to get usage help and extended options");
            Console.WriteLine();

            Console.WriteLine("[+] Starting up");

            //
            // Prepare
            //

            ChromeMonitor chromeMonitor    = new ChromeMonitor();
            string        mojoVersion      = MojoInterfacesFetcher.UpdateInterfacesInfoIfNeeded(chromeMonitor.ChromeVersion, force: forceFetchInterfacesInfo);
            string        legacyIpcversion = LegacyIpcInterfacesFetcher.UpdateInterfacesInfoIfNeeded(chromeMonitor.ChromeVersion, force: forceFetchInterfacesInfo);

            if (mojoVersion != chromeMonitor.ChromeVersion || legacyIpcversion != chromeMonitor.ChromeVersion)
            {
                Console.WriteLine("[!] Cached info is for " + mojoVersion + ", you may run --update-interfaces-info");
            }

            MojoMethodHashesExtractor.ExtractMethodNames(chromeMonitor.DLLPath, force: forceExtractMethodNames);

            bool success = UpdateWiresharkConfiguration();

            if (!success)
            {
                return;
            }

            Console.WriteLine("[+] Enumerating existing chrome pipes");
            HandlesUtility.EnumerateExistingHandles(ChromeMonitor.GetRunningChromeProcesses());

            //
            // Start sniffing
            //

            string outputPipeName = "chromeipc";
            string outputPipePath = @"\\.\pipe\" + outputPipeName;

            Console.WriteLine("[+] Starting sniffing of chrome named pipe to " + outputPipePath + ".");

            NamedPipeSniffer pipeMonitor  = new NamedPipeSniffer(chromeMonitor, outputPipeName, onlyMojo ? "mojo" : "", onlyNewPipes);
            bool             isMonitoring = pipeMonitor.Start();

            if (isMonitoring)
            {
                if (Process.GetProcessesByName("Wireshark").Length == 0)
                {
                    Console.WriteLine("[+] Opening Wirehark");
                    Process.Start(@"C:\Program Files\Wireshark\Wireshark.exe", "-k -i " + outputPipePath);
                }

                Console.WriteLine("[+] Capturing packets...");
            }

            //
            // Set up clean up routines
            //
            Console.CancelKeyPress += delegate
            {
                Thread.CurrentThread.IsBackground = false;
                pipeMonitor.Stop();
            };
        }
        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);
        }