示例#1
0
        public bool LoadEvents(int procID, int sampleInterval100ns)
        {
            m_procID         = procID;
            m_SampleInterval = sampleInterval100ns / 10000.0;

            // Filter to process
            TraceEvents processEvents = m_traceLog.Events.Filter(FilterEvent);

            // Get Dispatcher
            TraceEventDispatcher source = processEvents.GetSource();

            kernelGuid = KernelTraceEventParser.ProviderGuid;

            // Hookup events
            source.Clr.All += OnClrEvent;

            ClrPrivateTraceEventParser clrPrivate = new ClrPrivateTraceEventParser(source);

            clrPrivate.All += OnClrPrivateEvent;

            KernelTraceEventParser kernel = source.Kernel;

            kernel.PerfInfoSample += delegate(SampledProfileTraceData data)
            {
                ThreadMemoryInfo thread = GetThread(data.ThreadID);

                thread.AddEvent(HeapEvents.CPUSample, data.TimeStampRelativeMSec);
            };

            kernel.VirtualMemAlloc += OnVirtualMem;
            kernel.VirtualMemFree  += OnVirtualMem;

            m_processLookup = new Dictionary <int, Microsoft.Diagnostics.Tracing.Analysis.TraceProcess>();

            // Process all events into GCProcess lookup dictionary
            Microsoft.Diagnostics.Tracing.Analysis.TraceLoadedDotNetRuntimeExtensions.NeedLoadedDotNetRuntimes(source);
            Microsoft.Diagnostics.Tracing.Analysis.TraceProcessesExtensions.AddCallbackOnProcessStart(source, proc =>
            {
                Microsoft.Diagnostics.Tracing.Analysis.TraceProcessesExtensions.SetSampleIntervalMSec(proc, sampleInterval100ns);
                proc.Log = m_traceLog;
            });
            source.Process();
            foreach (var proc in Microsoft.Diagnostics.Tracing.Analysis.TraceProcessesExtensions.Processes(source))
            {
                if (Microsoft.Diagnostics.Tracing.Analysis.TraceLoadedDotNetRuntimeExtensions.LoadedDotNetRuntime(proc) != null)
                {
                    m_processLookup.Add(proc.ProcessID, proc);
                }
            }

            // Get the process we want
            if (!m_processLookup.ContainsKey(procID))
            {
                return(false);
            }

            m_process = m_processLookup[procID];
            m_runtime = Microsoft.Diagnostics.Tracing.Analysis.TraceLoadedDotNetRuntimeExtensions.LoadedDotNetRuntime(m_process);
            return(true);
        }
示例#2
0
        public void Start(IEnumerable <EventType> types)
        {
            if (EventTrace == null)
            {
                throw new InvalidOperationException("Must register for event notifications");
            }

            _kernelSession =
                new TraceEventSession(KernelTraceEventParser.KernelSessionName,
                                      TraceEventSessionOptions.NoRestartOnCreate)
            {
                BufferSizeMB          = 128,
                CpuSampleIntervalMSec = 10,
            };
            var keywords = KernelTraceEventParser.Keywords.All;

            _processingThread = new Thread(() =>
            {
                _kernelSession.EnableKernelProvider(keywords);
                _kernelParser = new KernelTraceEventParser(_kernelSession.Source);
                SetupCallbacks(types);
                _kernelSession.Source.Process();
            });
            _processingThread.Priority     = ThreadPriority.Lowest;
            _processingThread.IsBackground = true;
            _processingThread.Start();
        }
示例#3
0
        public void Start(IEnumerable <EventType> types, bool includeInit)
        {
            if (EventTrace == null)
            {
                throw new InvalidOperationException("Must register for event notifications");
            }

            _includeInit = includeInit;
            _session     = new TraceEventSession(KernelTraceEventParser.KernelSessionName)
            {
                BufferSizeMB          = 128,
                CpuSampleIntervalMSec = 10
            };

            var keywords = KernelTraceEventParser.Keywords.None;

            foreach (var type in types)
            {
                keywords |= EventInfo.AllEventsByType[type].Keyword;
            }

            _session.EnableKernelProvider(keywords);

            _processingThread = new Thread(() => {
                _parser = new KernelTraceEventParser(_session.Source);
                SetupCallbacks(types);
                _session.Source.Process();
            });
            _processingThread.Priority     = ThreadPriority.Lowest;
            _processingThread.IsBackground = true;
            _processingThread.Start();
        }
        public StackSource GetStackSource(TraceEvents events)
        {
            if (events == null)
            {
                ThrowHelper.ThrowArgumentNullException(nameof(events));
            }

            TraceLog log         = events.Log;
            var      stackSource = new MutableTraceEventStackSource(log)
            {
                ShowUnknownAddresses = true
            };
            var eventSource = events.GetSource();

            var sample = new StackSourceSample(stackSource);

            var kernelTraceEventParser = new KernelTraceEventParser(eventSource);

            kernelTraceEventParser.PerfInfoSample += delegate(SampledProfileTraceData data)
            {
                sample.Metric           = events.Log.SampleProfileInterval.Milliseconds;
                sample.TimeRelativeMSec = data.TimeStampRelativeMSec;
                sample.StackIndex       = stackSource.GetCallStack(data.CallStackIndex(), data);
                stackSource.AddSample(sample);
            };

            eventSource.Process();
            return(stackSource);
        }
示例#5
0
        private unsafe bool Initialize(TraceEventNativeMethods.EVENT_RECORD *eventRecord)
        {
            if (eventRecord->EventHeader.ProviderId == EventTraceGuid)
            {
                var logfile = (FAKE_TRACE_LOGFILE_HEADER *)eventRecord->UserData;
                this.pointerSize         = (int)logfile->PointerSize;
                this._QPCFreq            = logfile->PerfFreq;
                this.osVersion           = new Version((byte)logfile->Version, (byte)(logfile->Version >> 8));
                this.cpuSpeedMHz         = (int)logfile->CpuSpeedInMHz;
                this.numberOfProcessors  = (int)logfile->NumberOfProcessors;
                this.utcOffsetMinutes    = logfile->Bias;
                this._syncTimeUTC        = DateTime.FromFileTimeUtc(logfile->StartTime);
                this._syncTimeQPC        = eventRecord->EventHeader.TimeStamp;
                this.sessionStartTimeQPC = eventRecord->EventHeader.TimeStamp;
                this.sessionEndTimeQPC   = eventRecord->EventHeader.TimeStamp;
                this.eventsLost          = (int)logfile->EventsLost;

                var kernelParser = new KernelTraceEventParser(this, KernelTraceEventParser.ParserTrackingOptions.None);

                kernelParser.EventTraceHeader += delegate(EventTraceHeaderTraceData data)
                {
                    Marshal.WriteInt32(data.userData, OffsetToUTCOffsetMinutes, this.utcOffsetMinutes.Value); // Since this is a FakeTraceHeader
                };

                kernelParser.ProcessStartGroup += delegate(ProcessTraceData data)
                {
                    string path     = data.KernelImageFileName;
                    int    startIdx = path.LastIndexOf('\\');
                    if (0 <= startIdx)
                    {
                        startIdx++;
                    }
                    else
                    {
                        startIdx = 0;
                    }

                    int endIdx = path.LastIndexOf('.');
                    if (endIdx <= startIdx)
                    {
                        endIdx = path.Length;
                    }

                    this.processNameForID[data.ProcessID] = path.Substring(startIdx, endIdx - startIdx);
                };

                kernelParser.ProcessEndGroup += delegate(ProcessTraceData data)
                {
                    this.processNameForID.Remove(data.ProcessID);
                };

                return(true);
            }

            return(false);
        }
示例#6
0
        /// <summary>
        /// Wire up parsing of kernel event data from the specified ETWTraceEventSource.
        /// </summary>
        /// <param name="eventSource">The ETWTraceEventSource from which to parse the data.</param>
        private void ParseKernelTraceEvents(ETWTraceEventSource eventSource)
        {
            if (m_kernelEvents == KernelTraceEventParser.Keywords.None)
            {
                return;
            }

            var kernelParser = new KernelTraceEventParser(eventSource);

            // iterate over each set bit, wiring up a callback to parse the data
            uint eventBits = (uint)m_kernelEvents;
            int  bitPos    = 0;

            while (eventBits > 0)
            {
                // cycle through until a set bit is found
                while ((((uint)eventBits) & (uint)(1 << bitPos)) == 0)
                {
                    ++bitPos;
                    Debug.Assert(bitPos < 32);
                }

                var bitVal = (uint)(1 << bitPos);

                // now strip it from eventBits and covert it to its enum value
                eventBits ^= bitVal;
                KernelTraceEventParser.Keywords kernelEvent = (KernelTraceEventParser.Keywords)bitVal;

                if ((kernelEvent & KernelTraceEventParser.Keywords.ImageLoad) == KernelTraceEventParser.Keywords.ImageLoad)
                {
                    var modLoads = new EventDataListString <KernelPerfEvents>(KernelPerfEvents.ModuleLoad);

                    modLoads.Values = new HashSet <string>(StringComparer.OrdinalIgnoreCase);

                    kernelParser.ImageLoad += delegate(ImageLoadTraceData data)
                    {
                        if (string.Compare(data.ProcessName, m_process, true) == 0)
                        {
                            var modName = Path.GetFileName(data.FileName);
                            if (!modLoads.Values.Contains(modName))
                            {
                                modLoads.Values.Add(modName);
                            }

                            m_processFound = true;
                        }
                    };

                    m_aed.AddData(modLoads);
                }
                else
                {
                    Console.WriteLine("WARNING: Kernel event {0} NYI for reporting.", kernelEvent);
                }
            }
        }
示例#7
0
        public void Start()
        {
            _session = new TraceEventSession("ALPCLogger");
            _session.StopOnDispose = true;
            _session.BufferSizeMB  = 64;

            _session.EnableKernelProvider(KernelTraceEventParser.Keywords.AdvancedLocalProcedureCalls,
                                          KernelTraceEventParser.Keywords.AdvancedLocalProcedureCalls);

            var parser = new KernelTraceEventParser(_session.Source);

            parser.ALPCReceiveMessage += Parser_ALPCReceiveMessage;
            parser.ALPCSendMessage    += Parser_ALPCSendMessage;
            //parser.ALPCWaitForReply += Parser_ALPCWaitForReply;
            //parser.ALPCUnwait += Parser_ALPCUnwait;
            _session.Source.Process();
        }
示例#8
0
        public void Start(TraceElements elements, bool includeInit)
        {
            _includeInit = includeInit;
            _session     = new TraceEventSession(KernelTraceEventParser.KernelSessionName)
            {
                BufferSizeMB          = 128,
                CpuSampleIntervalMSec = 10
            };
            _session.EnableKernelProvider((KernelTraceEventParser.Keywords)elements);

            _processingThread = new Thread(() => {
                _parser = new KernelTraceEventParser(_session.Source);
                SetupCallbacks(elements);
                _session.Source.Process();
            });
            _processingThread.Priority     = ThreadPriority.Lowest;
            _processingThread.IsBackground = true;
            _processingThread.Start();
        }
示例#9
0
        public void Start()
        {
            var version = Environment.OSVersion.Version;

            _session = new TraceEventSession(version.Major == 6 && version.Minor == 1 ? KernelTraceEventParser.KernelSessionName : "ALPCLogger");
            _session.StopOnDispose = true;
            _session.BufferSizeMB  = 64;

            _session.EnableKernelProvider(KernelTraceEventParser.Keywords.AdvancedLocalProcedureCalls,
                                          KernelTraceEventParser.Keywords.AdvancedLocalProcedureCalls);

            var parser = new KernelTraceEventParser(_session.Source);

            parser.ALPCReceiveMessage += Parser_ALPCReceiveMessage;
            parser.ALPCSendMessage    += Parser_ALPCSendMessage;
            parser.StackWalkStack     += Parser_StackWalkStack;
            //parser.ALPCWaitForReply += Parser_ALPCWaitForReply;
            //parser.ALPCUnwait += Parser_ALPCUnwait;
            _session.Source.Process();
        }
示例#10
0
        private IEnumerable <Metric> Parse(TraceLogEventSource traceLogEventSource, PreciseMachineCounter[] counters)
        {
            var bdnEventsParser    = new EngineEventLogParser(traceLogEventSource);
            var kernelEventsParser = new KernelTraceEventParser(traceLogEventSource);

            bdnEventsParser.OverheadActualStart += OnOverheadActualStart;
            bdnEventsParser.OverheadActualStop  += OnOverheadActualStop;

            bdnEventsParser.WorkloadActualStart += OnWorkloadActualStart;
            bdnEventsParser.WorkloadActualStop  += OnWorkloadActualStop;

            kernelEventsParser.PerfInfoCollectionStart += OnPmcIntervalChange;
            kernelEventsParser.PerfInfoPMCSample       += OnPmcEvent;

            traceLogEventSource.Process();

            var benchmarkedProcessData = processIdToData.Values.Single(x => x.HasBenchmarkEvents);

            return(benchmarkedProcessData.CalculateMetrics(profileSourceIdToInterval, counters));
        }
示例#11
0
        public static void SetupCapCollectors(TraceEventDispatcher source, ClrCap.CAPAnalysisBase report)
        {
            KernelTraceEventParser kernel = source.Kernel;

            source.Kernel.SystemConfigCPU += delegate(SystemConfigCPUTraceData data)
            {
                report.MachineInfo.MachineName           = data.ComputerName;
                report.MachineInfo.Domain                = data.DomainName;
                report.MachineInfo.MemorySizeMb          = data.MemSize;
                report.MachineInfo.NumberOfProcessors    = data.NumberOfProcessors;
                report.MachineInfo.ProcessorFrequencyMHz = data.MHz;
                report.MachineInfo.HyperThreadingFlag    = (int)data.HyperThreadingFlag;
                report.MachineInfo.PageSize              = data.PageSize;
            };

            source.Kernel.SysConfigBuildInfo += delegate(BuildInfoTraceData data)
            {
                report.OSInfo.Name  = data.ProductName;
                report.OSInfo.Build = data.BuildLab;
            };
        }
示例#12
0
        public bool LoadEvents(int procID, int sampleInterval100ns)
        {
            m_procID         = procID;
            m_SampleInterval = sampleInterval100ns / 10000.0;

            // Filter to process
            TraceEvents processEvents = m_traceLog.Events.Filter(FilterEvent);

            // Get Dispatcher
            TraceEventDispatcher source = processEvents.GetSource();

            kernelGuid = KernelTraceEventParser.ProviderGuid;

            // Hookup events
            source.Clr.All += OnClrEvent;

            ClrPrivateTraceEventParser clrPrivate = new ClrPrivateTraceEventParser(source);

            clrPrivate.All += OnClrPrivateEvent;

            KernelTraceEventParser kernel = source.Kernel;

            kernel.PerfInfoSample += delegate(SampledProfileTraceData data)
            {
                ThreadMemoryInfo thread = GetThread(data.ThreadID);

                thread.AddEvent(HeapEvents.CPUSample, data.TimeStampRelativeMSec);
            };

            kernel.VirtualMemAlloc += OnVirtualMem;
            kernel.VirtualMemFree  += OnVirtualMem;

            m_processLookup = new ProcessLookup <GCProcess>();

            // Process all events into GCProcess lookup dictionary
            GCProcess.Collect(source, sampleInterval100ns, m_processLookup, null, false, m_traceLog);

            // Get the process we want
            return(m_processLookup.TryGetByID(procID, out m_gcProcess));
        }
示例#13
0
        public void Start(IEnumerable <EventType> types)
        {
            if (EventTrace == null)
            {
                throw new InvalidOperationException("Must register for event notifications");
            }

            _kernelSession = new TraceEventSession(KernelTraceEventParser.KernelSessionName, TraceEventSessionOptions.NoRestartOnCreate)
            {
                BufferSizeMB          = 128,
                CpuSampleIntervalMSec = 10,
            };
            var keywords = KernelTraceEventParser.Keywords.All;

            //foreach (var type in types)
            //    keywords |= EventInfo.AllEventsByType[type].Keyword;

            //_kernelSession.EnableKernelProvider(keywords | KernelTraceEventParser.Keywords.Job);

            //_customSession = new TraceEventSession("CustomSession");
            //_customSession.EnableProvider("Microsoft-Windows-WMI-Activity");
            //var parser = new RegisteredTraceEventParser(_customSession.Source);
            //parser.All += Parser_All;

            //Task.Run(() => _customSession.Source.Process());

            _processingThread = new Thread(() => {
                _kernelSession.EnableKernelProvider(keywords);
                _kernelParser = new KernelTraceEventParser(_kernelSession.Source);
                SetupCallbacks(types);
                _kernelSession.Source.Process();
            });
            _processingThread.Priority     = ThreadPriority.Lowest;
            _processingThread.IsBackground = true;
            _processingThread.Start();
        }
        public LoggingController()
        {
            try
            {
                _selfProcessId = Process.GetCurrentProcess().Id;
                if (Boolean.TryParse(ConfigurationManager.AppSettings["RejectSelf"], out _rejectSelf))
                {
                    if (_rejectSelf)
                    {
                        _logger.Info("Process is not logging own actions by rejecting evetns with processID=" + _selfProcessId);
                    }
                    else
                    {
                        _logger.Info("Process is logging own actions.");
                    }
                }
                else
                {
                    _logger.Info("Could not determine \"RejectSelf\" configuration key. Logging own actions.");
                    _rejectSelf = false;
                }


                _logger.Info("Initialising the ETWEngine Class.");
                _kernelSession = new TraceEventSession(KernelTraceEventParser.KernelSessionName, TraceEventSessionOptions.NoRestartOnCreate)
                {
                    BufferSizeMB          = 1024,
                    CpuSampleIntervalMSec = 10,
                };
                _kernelSession.EnableKernelProvider(
                    KernelTraceEventParser.Keywords.FileIO |
                    KernelTraceEventParser.Keywords.FileIOInit |
                    KernelTraceEventParser.Keywords.NetworkTCPIP |
                    KernelTraceEventParser.Keywords.Registry |
                    KernelTraceEventParser.Keywords.Process
                    );

                _kernelParser                  = new KernelTraceEventParser(_kernelSession.Source);
                _processingThread              = new Thread(() => { _kernelSession.Source.Process(); });
                _processingThread.Priority     = ThreadPriority.Highest;
                _processingThread.IsBackground = true;

                _filter = new CustomEventFilter(
                    ConfigurationManager.AppSettings["FileRegexString"],
                    ConfigurationManager.AppSettings["NetRegexString"],
                    ConfigurationManager.AppSettings["RegRegexString"],
                    ConfigurationManager.AppSettings["ProcRegexString"],
                    ConfigurationManager.AppSettings["NotFileRegexString"],
                    ConfigurationManager.AppSettings["NotNetRegexString"],
                    ConfigurationManager.AppSettings["NotRegRegexString"],
                    ConfigurationManager.AppSettings["NotProcRegexString"]
                    );

                _logger.Info("Seting up network events.");
                SetupNetworkEvents();

                _logger.Info("Seting up registry events.");
                SetupRegistryEvents();

                _logger.Info("Seting up file events.");
                SetupFileEvents();

                _logger.Info("Seting up process events.");
                SetupProcessEvents();
            }
            catch (Exception x)
            {
                _logger.Error(x, "Failed to properly create LoggingController");
            }
        }
示例#15
0
        static int Main(string[] args)
        {
            bool bNetConnect = false, bNetTransfer = false, bProcess = false, bThread = false, bImageLoad = false;
            bool bDns = false, bSysmon = false, bRegistry = false, bFile = false;

            if (args.Length == 0)
            {
                Console.WriteLine("\nUsage: ETWMonitor [net_connect | net_transfer | process | thread | imageload | memory | registry | dns | sysmon]\n");
                Console.WriteLine("net_connect  : Show new TCP connections");
                Console.WriteLine("net_transfer : Show network transfers");
                Console.WriteLine("process      : Show process creations and exits");
                Console.WriteLine("thread       : Show suspicious thread creation (cross-process)");
                Console.WriteLine("imageload    : Show image loading");
                Console.WriteLine("file         : Show file activity");
                Console.WriteLine("registry     : Show registry details");
                Console.WriteLine("dns          : Show DNS requests");
                Console.WriteLine("sysmon       : Show entries from Sysmon");
                return(1);
            }

            if (args[0] == "net_connect")
            {
                Console.WriteLine("\nShowing new network connections");
                bNetConnect = true;
            }
            else if (args[0] == "net_transfer")
            {
                Console.WriteLine("\nShowing network transfers");
                bNetTransfer = true;
            }
            else if (args[0] == "process")
            {
                Console.WriteLine("\nShowing process creation and exits");
                bProcess = true;
            }
            else if (args[0] == "thread")
            {
                Console.WriteLine("\nShowing suspicious thread creations (cross-process)");
                bThread = true;
            }
            else if (args[0] == "imageload")
            {
                Console.WriteLine("\nShowing image loads");
                bImageLoad = true;
            }
            else if (args[0] == "file")
            {
                Console.WriteLine("\nShowing file system activity");
                bFile = true;
            }
            else if (args[0] == "registry")
            {
                Console.WriteLine("\nShowing registry details");
                bRegistry = true;
            }
            else if (args[0] == "dns")
            {
                Console.WriteLine("\nShowing DNS requests");
                bDns = true;
            }
            else if (args[0] == "sysmon")
            {
                Console.WriteLine("\nShowing Sysmon entries");
                bSysmon = true;
            }
            else
            {
                Console.WriteLine("\nInvalid option");
                return(1);
            }

            // Today you have to be Admin to turn on ETW events (anyone can write ETW events).
            if (!(TraceEventSession.IsElevated() ?? false))
            {
                Console.WriteLine("To turn on ETW events you need to be Administrator, please run from an Admin process.");
                return(-1);
            }

            var sessionName = "";

            if (bNetConnect)
            {
                sessionName = "NetConnectSession";
            }
            else if (bNetTransfer)
            {
                sessionName = "NetTransferSession";
            }
            else if (bProcess)
            {
                sessionName = "ProcessSession";
            }
            else if (bThread)
            {
                sessionName = "ThreadSession";
            }
            else if (bImageLoad)
            {
                sessionName = "ImageLoadSession";
            }
            else if (bFile)
            {
                sessionName = "FileSession";
            }
            else if (bRegistry)
            {
                sessionName = "RegistrySession";
            }
            else if (bDns)
            {
                sessionName = "DnsSession";
            }
            else if (bSysmon)
            {
                sessionName = "SysmonSession";
            }
            else
            {
                Console.WriteLine("Error");
                return(-1);
            }

            using (var session = new TraceEventSession(sessionName, null))  // the null second parameter means 'real time session'
            {
                session.StopOnDispose = true;

                Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e) { session.Dispose(); };

                // prepare to read from the session, connect the ETWTraceEventSource to the session
                using (var source = new ETWTraceEventSource(sessionName, TraceEventSourceType.Session))
                {
                    Action <TraceEvent> action = delegate(TraceEvent data)
                    {
                        var taskName  = data.TaskName;
                        var EventName = data.EventName;

                        if (bProcess)
                        {
                            if (EventName == "Process/DCStart" || EventName == "Process/Start")
                            {
                                ProcessTraceData startprocdata = (ProcessTraceData)data;

                                string exe = (string)data.PayloadByName("ImageFileName");

                                Console.Write(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ") + EventName);
                                Console.Write(" PPID: " + startprocdata.ParentID.ToString() + " PID: " + startprocdata.ProcessID.ToString());
                                Console.Write(" Name: " + exe);

                                Process PName = GetProcByID2(startprocdata.ParentID);

                                if (PName != null)
                                {
                                    Console.Write(" ParentName: " + PName.ProcessName);
                                }

                                Console.WriteLine(" CommandLine: " + startprocdata.CommandLine);
                            }
                            else if (EventName == "Process/End")
                            {
                                ProcessTraceData exitprocdata = (ProcessTraceData)data;
                                string           exe          = (string)data.PayloadByName("ImageFileName");

                                Console.Write(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ") + EventName);
                                Console.WriteLine(" PPID: " + exitprocdata.ParentID.ToString() + " PID: " + exitprocdata.ProcessID.ToString() + " " + exe);
                            }
                        }
                        else if (bNetConnect)
                        {
                            if (taskName == "TcpRequestConnect")
                            {
                                int threadID  = data.ThreadID;
                                int processID = data.ProcessID;

                                byte[] local_addr  = (byte[])data.PayloadByName("LocalAddress");
                                byte[] remote_addr = (byte[])data.PayloadByName("RemoteAddress");

                                if (local_addr == null || remote_addr == null)
                                {
                                    Console.WriteLine("Null addr!");
                                }

                                // First two bytes are address family: 2 for ipv4, 10 for ipv6
                                // Next two bytes are the port

                                var family = new byte[2];

                                family[0] = local_addr[0];
                                family[1] = local_addr[1];

                                ushort family_nr = BitConverter.ToUInt16(family, 0);

                                if (family_nr == 2)
                                {
                                    var local_port  = new byte[2];
                                    var remote_port = new byte[2];

                                    local_port[0] = local_addr[2];
                                    local_port[1] = local_addr[3];

                                    Array.Reverse(local_port); // Need to reverse port

                                    remote_port[0] = remote_addr[2];
                                    remote_port[1] = remote_addr[3];

                                    Array.Reverse(remote_port); // Need to reverse port

                                    ushort local_port_nr  = BitConverter.ToUInt16(local_port, 0);
                                    ushort remote_port_nr = BitConverter.ToUInt16(remote_port, 0);

                                    Process proc;
                                    string  processname = "<not found>";

                                    if (processID > 0)
                                    {
                                        proc = GetProcByID(processID);
                                        if (proc != null)
                                        {
                                            processname = proc.MainModule.ModuleName;
                                        }
                                    }

                                    Console.Write(data.TimeStamp.ToString("yyyy-MM-dd HH:mm:ss") + " " + taskName + " PID: " + processID);

                                    int parentid = GetParentProcessID(processID);

                                    if (parentid != 0)
                                    {
                                        Console.Write(" PPID: " + parentid);
                                    }
                                    else
                                    {
                                        Console.Write(" PPID: (null)");
                                    }

                                    Console.Write(" TID: " + threadID + " Name: " + processname);

                                    proc = GetProcByID(parentid);

                                    if (proc != null)
                                    {
                                        Console.Write(" Parent Name: " + proc.ProcessName);
                                    }
                                    else
                                    {
                                        Console.Write(" Parent Name: (null)");
                                    }

                                    string local_ip  = local_addr[4] + "." + local_addr[5] + "." + local_addr[6] + "." + local_addr[7];
                                    string remote_ip = remote_addr[4] + "." + remote_addr[5] + "." + remote_addr[6] + "." + remote_addr[7];

                                    Console.Write(" " + local_ip + ":" + local_port_nr + "->");
                                    Console.WriteLine(remote_ip + ":" + remote_port_nr + " ");
                                }
                                else if (family_nr == 0x10)
                                {
                                    Console.WriteLine("IPV6");
                                }
                            }
                        }
                        else if (bNetTransfer)
                        {
                            if (EventName == "TcpIp/Send" || EventName == "TcpIp/Recv")
                            {
                                Console.Write(data.TimeStamp.ToString("yyyy-MM-dd HH:mm:ss") + " " + EventName + " PID: " + data.ProcessID);

                                Process processname;

                                processname = GetProcByID(data.ProcessID);

                                if (processname != null)
                                {
                                    Console.Write(" Name: " + processname.ProcessName);
                                }
                                else
                                {
                                    Console.Write(" Name: (null)");
                                }

                                IPAddress saddr = (IPAddress)data.PayloadByName("saddr");
                                IPAddress daddr = (IPAddress)data.PayloadByName("daddr");
                                int       sport = (int)data.PayloadByName("sport");
                                int       dport = (int)data.PayloadByName("dport");
                                int       size  = (int)data.PayloadByName("size");

                                Console.Write(" Src: " + saddr.ToString() + ":" + sport + " Dst: " + daddr.ToString() + ":" + dport);
                                Console.WriteLine(" Size: " + size);
                            }
                        }
                        else if (bThread) // try to catch remote thread injections only
                        {
                            if (taskName == "ThreadStart")
                            {
                                int     destProcessID = (int)data.PayloadByName("ProcessID");
                                int     parentid;
                                Process processname;

                                if (data.ProcessID != destProcessID && data.ProcessID != 4)
                                {
                                    // check if destpid is not a child of srcpid, otherwise we have a problem!
                                    // check the parentpid of srcpid

                                    int destThreadID = (int)data.PayloadByName("ThreadID");
                                    int srcThreadID  = data.ThreadID;

                                    parentid = GetParentProcessID(destProcessID);
                                    if (parentid != 0 && parentid != data.ProcessID)
                                    {
                                        Console.Write(data.TimeStamp.ToString("yyyy-MM-dd HH:mm:ss") + " POSSIBLE THREAD INJECTION: ");
                                        Console.Write(taskName + " TID: " + destThreadID + " SrcTID: " + srcThreadID + " SrcPID: " + data.ProcessID);
                                        Console.Write(" DestPID: " + destProcessID);

                                        processname = GetProcByID(data.ProcessID);

                                        if (processname != null)
                                        {
                                            Console.Write(" SrcName: " + processname.ProcessName);
                                        }
                                        else
                                        {
                                            Console.Write(" SrcName: (null)");
                                        }

                                        processname = GetProcByID(destProcessID);

                                        if (processname != null)
                                        {
                                            Console.WriteLine(" DestName: " + processname.ProcessName);
                                        }
                                        else
                                        {
                                            Console.WriteLine(" DestName: (null)");
                                        }

                                        Console.WriteLine("\nDetailed information:\n" + data.ToString());
                                    }
                                }
                            }
                        }
                        else if (bImageLoad)
                        {
                            if (EventName == "Image/DCStart" || EventName == "Image/Load" || EventName == "Image/Unload")
                            {
                                int pid = (int)data.ProcessID;
                                Console.Write(data.TimeStamp.ToString("yyyy-MM-dd HH:mm:ss ") + EventName);
                                Console.Write(" PID: " + pid);

                                Process processname;

                                processname = GetProcByID(pid);

                                if (processname != null)
                                {
                                    Console.Write(" Name: " + processname.ProcessName);
                                }
                                else
                                {
                                    Console.Write(" Name: (null)");
                                }

                                string filename = (string)data.PayloadByName("FileName");
                                Console.WriteLine(" FileName: " + filename);
                            }
                        }
                        else if (bFile)
                        {
                            if (EventName == "CreateNewFile" || EventName == "DeletePath" || EventName == "NameDelete")
                            {
                                int pid = (int)data.ProcessID;
                                Console.Write(data.TimeStamp.ToString("yyyy-MM-dd HH:mm:ss ") + EventName);
                                Console.Write(" PID: " + pid);

                                Process processname;

                                processname = GetProcByID(pid);

                                if (processname != null)
                                {
                                    Console.Write(" Name: " + processname.ProcessName);
                                }
                                else
                                {
                                    Console.Write(" Name: (null)");
                                }

                                string filename = "";

                                if (EventName == "DeletePath")
                                {
                                    filename = (string)data.PayloadByName("FilePath");
                                }
                                else
                                {
                                    filename = (string)data.PayloadByName("FileName");
                                }

                                Console.WriteLine(" File: " + filename);
                            }
                        }
                        else if (bRegistry)
                        {
                            if (EventName == "EventID(1)/CreateKey" || EventName == "EventID(5)/SetValueKey" || EventName == "EventID(3)/DeleteKey" || EventName == "EventID(6)/DeleteValueKey")
                            {
                                int pid = (int)data.ProcessID;
                                Console.Write(data.TimeStamp.ToString("yyyy-MM-dd HH:mm:ss ") + EventName);
                                Console.Write(" PID: " + pid);

                                Process processname;

                                processname = GetProcByID(pid);

                                if (processname != null)
                                {
                                    Console.Write(" Name: " + processname.ProcessName);
                                }
                                else
                                {
                                    Console.Write(" Name: (null)");
                                }

                                if (EventName == "EventID(1)/CreateKey")
                                {
                                    string RelativeName = (string)data.PayloadByName("RelativeName");
                                    int    status       = (int)data.PayloadByName("Status");
                                    Console.WriteLine(" Status: " + status + " RelativeName: " + RelativeName);
                                }
                                else if (EventName == "EventID(3)/DeleteKey")
                                {
                                    int status = (int)data.PayloadByName("Status");
                                    Console.WriteLine(" Status: " + status);
                                }
                                else if (EventName == "EventID(5)/SetValueKey")
                                {
                                    string ValueName = (string)data.PayloadByName("ValueName");
                                    int    status    = (int)data.PayloadByName("Status");
                                    Console.WriteLine(" Status: " + status + " ValueName: " + ValueName);
                                }
                                else if (EventName == "EventID(6)/DeleteValueKey")
                                {
                                    string ValueName = (string)data.PayloadByName("ValueName");
                                    int    status    = (int)data.PayloadByName("Status");
                                    Console.WriteLine(" Status: " + status + " ValueName: " + ValueName);
                                }
                            }
                        }
                        else if (bDns)
                        {
                            int pid = (int)data.ProcessID;
                            Console.Write(data.TimeStamp.ToString("yyyy-MM-dd HH:mm:ss ") + EventName);
                            Console.Write(" PID: " + pid);

                            Process processname;

                            processname = GetProcByID(pid);

                            if (processname != null)
                            {
                                Console.Write(" Name: " + processname.ProcessName);
                            }
                            else
                            {
                                Console.Write(" Name: (null)");
                            }

                            string QueryName = (string)data.PayloadByName("QueryName");
                            Console.WriteLine(" QueryName: " + QueryName);
                        }
                        else if (bSysmon)
                        {
                            Console.WriteLine(data.ToString());
                        }
                    };

                    // You can also simply use 'logman query providers' to find out the GUID yourself and wire it in.

                    Guid processProviderGuid;

                    if (bProcess)
                    {
                        session.EnableKernelProvider(KernelTraceEventParser.Keywords.Process);
                    }
                    else if (bNetConnect)
                    {
                        processProviderGuid = TraceEventSession.GetProviderByName("Microsoft-Windows-TCPIP");
                        session.EnableProvider(processProviderGuid, TraceEventLevel.Informational, 0x80);  // ut:TcpipDiagnosis seems to do the job
                    }
                    else if (bNetTransfer)
                    {
                        session.EnableKernelProvider(KernelTraceEventParser.Keywords.NetworkTCPIP);
                    }
                    else if (bThread)
                    {
                        processProviderGuid = TraceEventSession.GetProviderByName("Microsoft-Windows-Kernel-Process");
                        session.EnableProvider(processProviderGuid, TraceEventLevel.Informational, 0x20);  // WINEVENT_KEYWORD_THREAD
                    }
                    else if (bImageLoad)
                    {
                        session.EnableKernelProvider(KernelTraceEventParser.Keywords.ImageLoad);
                    }
                    else if (bFile)
                    {
                        processProviderGuid = TraceEventSession.GetProviderByName("Microsoft-Windows-Kernel-File");
                        session.EnableProvider(processProviderGuid, TraceEventLevel.Informational, 0x0000000000001410); // KERNEL_FILE_KEYWORD_CREATE_NEW_FILE, KERNEL_FILE_KEYWORD_DELETE_PATH, KERNEL_FILE_KEYWORD_FILENAME
                    }
                    else if (bRegistry)
                    {
                        processProviderGuid = TraceEventSession.GetProviderByName("Microsoft-Windows-Kernel-Registry");
                        session.EnableProvider(processProviderGuid, TraceEventLevel.Informational, 0x0000000000005300); // SetValueKey, CreateKey, DeleteKey, DeleteValueKey
                    }
                    else if (bDns)
                    {
                        processProviderGuid = TraceEventSession.GetProviderByName("Microsoft-Windows-DNS-Client");
                        session.EnableProvider(processProviderGuid, TraceEventLevel.Informational, 0x8000000000000000);  //
                    }
                    else if (bSysmon)
                    {
                        processProviderGuid = TraceEventSession.GetProviderByName("Microsoft-Windows-Sysmon");
                        session.EnableProvider(processProviderGuid, TraceEventLevel.Informational, 0x8000000000000000);  // KERNEL_MEM_KEYWORD_MEMINFO
                    }
                    else
                    {
                        Console.WriteLine("Error");
                        return(-1);
                    }

                    // We use different parsers depending on the events. For TCP/IP stuff we need to
                    // use another since we want to register not only ProcessID but also ThreadID for each event
                    if (bNetConnect || bThread || bFile || bRegistry || bDns || bSysmon)
                    {
                        // Hook up the parser that knows about Any EventSources regsitered with windows.  (e.g. the OS ones).
                        var registeredParser = new RegisteredTraceEventParser(source);
                        registeredParser.All += action;
                    }
                    else
                    {
                        // Hook up the parser that knows about kernel traces
                        var KernelParser = new KernelTraceEventParser(source);
                        KernelParser.All += action;
                    }

                    Console.WriteLine("Starting Listening for events");
                    // go into a loop processing events can calling the callbacks.  Because this is live data (not from a file)
                    // processing never completes by itself, but only because someone called 'source.Close()'.
                    source.Process();
                    Console.WriteLine();
                    Console.WriteLine("Stopping Listening for events");
                }
            }
            return(0);
        }
        /// <summary>
        /// Wire up parsing of kernel event data from the specified ETWTraceEventSource.
        /// </summary>
        /// <param name="eventSource">The ETWTraceEventSource from which to parse the data.</param>
        private void ParseKernelTraceEvents(ETWTraceEventSource eventSource)
        {
            if (m_kernelEvents == KernelTraceEventParser.Keywords.None)
                return;

            var kernelParser = new KernelTraceEventParser(eventSource);

            // iterate over each set bit, wiring up a callback to parse the data
            uint eventBits = (uint)m_kernelEvents;
            int bitPos = 0;

            while (eventBits > 0)
            {
                // cycle through until a set bit is found
                while ((((uint)eventBits) & (uint)(1 << bitPos)) == 0)
                {
                    ++bitPos;
                    Debug.Assert(bitPos < 32);
                }

                var bitVal = (uint)(1 << bitPos);

                // now strip it from eventBits and covert it to its enum value
                eventBits ^= bitVal;
                KernelTraceEventParser.Keywords kernelEvent = (KernelTraceEventParser.Keywords)bitVal;

                if ((kernelEvent & KernelTraceEventParser.Keywords.ImageLoad) == KernelTraceEventParser.Keywords.ImageLoad)
                {
                    var modLoads = new EventDataListString<KernelPerfEvents>(KernelPerfEvents.ModuleLoad);

                    modLoads.Values = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

                    kernelParser.ImageLoad += delegate(ImageLoadTraceData data)
                    {
                        if (string.Compare(data.ProcessName, m_process, true) == 0)
                        {
                            var modName = Path.GetFileName(data.FileName);
                            if (!modLoads.Values.Contains(modName))
                                modLoads.Values.Add(modName);

                            m_processFound = true;
                        }
                    };

                    m_aed.AddData(modLoads);
                }
                else
                {
                    Console.WriteLine("WARNING: Kernel event {0} NYI for reporting.", kernelEvent);
                }
            }
        }
示例#17
0
        private void Initialize(string fileOrSessionName, TraceEventSourceType type)
        {
            // Allocate the LOGFILE and structures and arrays that hold them
            // Figure out how many log files we have
            if (type == TraceEventSourceType.MergeAll)
            {
                List <string> allLogFiles = GetMergeAllLogFiles(fileOrSessionName);

                logFiles = new TraceEventNativeMethods.EVENT_TRACE_LOGFILEW[allLogFiles.Count];
                for (int i = 0; i < allLogFiles.Count; i++)
                {
                    logFiles[i].LogFileName = allLogFiles[i];
                }
            }
            else
            {
                logFiles = new TraceEventNativeMethods.EVENT_TRACE_LOGFILEW[1];
                if (type == TraceEventSourceType.FileOnly)
                {
                    logFiles[0].LogFileName = fileOrSessionName;
                }
                else
                {
                    Debug.Assert(type == TraceEventSourceType.Session);
                    logFiles[0].LoggerName   = fileOrSessionName;
                    logFiles[0].LogFileMode |= TraceEventNativeMethods.EVENT_TRACE_REAL_TIME_MODE;
                    IsRealTime = true;
                }
            }
            handles = new ulong[logFiles.Length];

            // Fill  out the first log file information (we will clone it later if we have multiple files).
            logFiles[0].BufferCallback = this.TraceEventBufferCallback;
            handles[0]    = TraceEventNativeMethods.INVALID_HANDLE_VALUE;
            useClassicETW = !OperatingSystemVersion.AtLeast(OperatingSystemVersion.Vista);
            if (useClassicETW)
            {
                IntPtr mem = Marshal.AllocHGlobal(sizeof(TraceEventNativeMethods.EVENT_RECORD));
                TraceEventNativeMethods.ZeroMemory(mem, sizeof(TraceEventNativeMethods.EVENT_RECORD));
                convertedHeader           = (TraceEventNativeMethods.EVENT_RECORD *)mem;
                logFiles[0].EventCallback = RawDispatchClassic;
            }
            else
            {
                logFiles[0].LogFileMode  |= TraceEventNativeMethods.PROCESS_TRACE_MODE_EVENT_RECORD;
                logFiles[0].EventCallback = RawDispatch;
            }
            // We want the raw timestamp because it is needed to match up stacks with the event they go with.
            logFiles[0].LogFileMode |= TraceEventNativeMethods.PROCESS_TRACE_MODE_RAW_TIMESTAMP;

            // Copy the information to any additional log files
            for (int i = 1; i < logFiles.Length; i++)
            {
                logFiles[i].BufferCallback = logFiles[0].BufferCallback;
                logFiles[i].EventCallback  = logFiles[0].EventCallback;
                logFiles[i].LogFileMode    = logFiles[0].LogFileMode;
                handles[i] = handles[0];
            }

            DateTime minSessionStartTimeUTC = DateTime.MaxValue;
            DateTime maxSessionEndTimeUTC   = DateTime.MinValue + new TimeSpan(1 * 365, 0, 0, 0); // TO avoid roundoff error when converting to QPC add a year.

            // Open all the traces
            for (int i = 0; i < handles.Length; i++)
            {
                handles[i] = TraceEventNativeMethods.OpenTrace(ref logFiles[i]);
                if (handles[i] == TraceEventNativeMethods.INVALID_HANDLE_VALUE)
                {
                    Marshal.ThrowExceptionForHR(TraceEventNativeMethods.GetHRForLastWin32Error());
                }

                // Start time is minimum of all start times
                DateTime logFileStartTimeUTC = SafeFromFileTimeUtc(logFiles[i].LogfileHeader.StartTime);
                DateTime logFileEndTimeUTC   = SafeFromFileTimeUtc(logFiles[i].LogfileHeader.EndTime);

                if (logFileStartTimeUTC < minSessionStartTimeUTC)
                {
                    minSessionStartTimeUTC = logFileStartTimeUTC;
                }
                // End time is maximum of all start times
                if (logFileEndTimeUTC > maxSessionEndTimeUTC)
                {
                    maxSessionEndTimeUTC = logFileEndTimeUTC;
                }

                // TODO do we even need log pointer size anymore?
                // We take the max pointer size.
                if ((int)logFiles[i].LogfileHeader.PointerSize > pointerSize)
                {
                    pointerSize = (int)logFiles[i].LogfileHeader.PointerSize;
                }
            }

            _QPCFreq = logFiles[0].LogfileHeader.PerfFreq;
            if (_QPCFreq == 0)
            {
                _QPCFreq = Stopwatch.Frequency;
            }

            // Real time providers don't set this to something useful
            if ((logFiles[0].LogFileMode & TraceEventNativeMethods.EVENT_TRACE_REAL_TIME_MODE) != 0)
            {
                DateTime nowUTC = DateTime.UtcNow;
                long     nowQPC = QPCTime.GetUTCTimeAsQPC(nowUTC);

                _syncTimeQPC = nowQPC;
                _syncTimeUTC = nowUTC;

                sessionStartTimeQPC = nowQPC - _QPCFreq / 10;           // Subtract 1/10 sec to keep now and nowQPC in sync.
                sessionEndTimeQPC   = long.MaxValue;                    // Represents infinity.

                Debug.Assert(SessionStartTime < SessionEndTime);
            }
            else
            {
                _syncTimeUTC = minSessionStartTimeUTC;

                // UTCDateTimeToQPC is actually going to give the wrong value for these because we have
                // not set _syncTimeQPC, but will be adjusted when we see the event Header and know _syncTypeQPC.
                sessionStartTimeQPC = this.UTCDateTimeToQPC(minSessionStartTimeUTC);
                sessionEndTimeQPC   = this.UTCDateTimeToQPC(maxSessionEndTimeUTC);
            }
            Debug.Assert(_QPCFreq != 0);
            if (pointerSize == 0)       // Real time does not set this (grrr).
            {
                pointerSize = sizeof(IntPtr);
                Debug.Assert((logFiles[0].LogFileMode & TraceEventNativeMethods.EVENT_TRACE_REAL_TIME_MODE) != 0);
            }
            Debug.Assert(pointerSize == 4 || pointerSize == 8);

            cpuSpeedMHz        = (int)logFiles[0].LogfileHeader.CpuSpeedInMHz;
            numberOfProcessors = (int)logFiles[0].LogfileHeader.NumberOfProcessors;

            // We ask for raw timestamps, but the log file may have used system time as its raw timestamp.
            // SystemTime is like a QPC time that happens 10M times a second (100ns).
            // ReservedFlags is actually the ClockType 0 = Raw, 1 = QPC, 2 = SystemTimne 3 = CpuTick (we don't support)
            if (logFiles[0].LogfileHeader.ReservedFlags == 2)   // If ClockType == EVENT_TRACE_CLOCK_SYSTEMTIME
            {
                _QPCFreq = 10000000;
            }

            Debug.Assert(_QPCFreq != 0);
            int ver = (int)logFiles[0].LogfileHeader.Version;

            osVersion = new Version((byte)ver, (byte)(ver >> 8));

            // Logic for looking up process names
            processNameForID = new Dictionary <int, string>();

            var kernelParser = new KernelTraceEventParser(this, KernelTraceEventParser.ParserTrackingOptions.None);

            kernelParser.ProcessStartGroup += delegate(ProcessTraceData data)
            {
                // Get just the file name without the extension.  Can't use the 'Path' class because
                // it tests to make certain it does not have illegal chars etc.  Since KernelImageFileName
                // is not a true user mode path, we can get failures.
                string path     = data.KernelImageFileName;
                int    startIdx = path.LastIndexOf('\\');
                if (0 <= startIdx)
                {
                    startIdx++;
                }
                else
                {
                    startIdx = 0;
                }
                int endIdx = path.LastIndexOf('.');
                if (endIdx <= startIdx)
                {
                    endIdx = path.Length;
                }
                processNameForID[data.ProcessID] = path.Substring(startIdx, endIdx - startIdx);
            };
            kernelParser.ProcessEndGroup += delegate(ProcessTraceData data)
            {
                processNameForID.Remove(data.ProcessID);
            };
            kernelParser.EventTraceHeader += delegate(EventTraceHeaderTraceData data)
            {
                if (_syncTimeQPC == 0)
                {   // In merged files there can be more of these, we only set the QPC time on the first one
                    // We were using a 'start location' of 0, but we want it to be the timestamp of this events, so we add this to our
                    // existing QPC values.
                    _syncTimeQPC         = data.TimeStampQPC;
                    sessionStartTimeQPC += data.TimeStampQPC;
                    sessionEndTimeQPC   += data.TimeStampQPC;
                }
            };
        }
示例#18
0
        /// <summary>
        /// Gets profile data from the provided <see cref="ScenarioExecutionResult"/> object
        /// </summary>
        /// <param name="scenarioExecutionResult"></param>
        /// <returns>A collection of the profiled processes for the given scenario.</returns>
        /// <remarks>
        /// Some assumptions:
        ///     1. The scenario launches a single process, but itself can launch child processes.
        ///     2. Process started/stopped within the ETW session.
        /// </remarks>
        public IReadOnlyCollection <Process> GetProfileData(ScenarioExecutionResult scenarioExecutionResult)
        {
            if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                throw new PlatformNotSupportedException();
            }

            var    processes             = new List <Process>();
            Module defaultNtoskrnlModule = null;
            var    pmcSamplingIntervals  = new Dictionary <int, long>();

            bool IsOurProcess(ProcessTraceData obj)
            {
                return(obj.ProcessID == scenarioExecutionResult.ProcessExitInfo.ProcessId ||
                       processes.Any(process => process.Id == obj.ProcessID || process.Id == obj.ParentID));
            }

            using (var source = new ETWTraceEventSource(scenarioExecutionResult.EventLogFileName))
            {
                if (source.EventsLost > 0)
                {
                    throw new Exception($"Events lost in trace '{scenarioExecutionResult.EventLogFileName}'");
                }

                const int DefaultModuleChecksum = 0;

                ////////////////////////////////////////////////////////////////
                // Process data
                var parser = new KernelTraceEventParser(source);
                parser.ProcessStart += (ProcessTraceData obj) => {
                    if (IsOurProcess(obj))
                    {
                        var process = new Process(obj.ImageFileName, obj.ProcessID, obj.ParentID, scenarioExecutionResult.PerformanceMonitorCounters);
                        process.LifeSpan.Start = obj.TimeStamp;
                        processes.Add(process);
                    }
                };
                parser.ProcessStop += (ProcessTraceData obj) => {
                    if (IsOurProcess(obj))
                    {
                        processes.Single(process => process.Id == obj.ProcessID).LifeSpan.End = obj.TimeStamp;
                    }
                };

                ////////////////////////////////////////////////////////////////
                // Image/Module data
                parser.ImageLoad += (ImageLoadTraceData obj) => {
                    var process = processes.SingleOrDefault(p => p.Id == obj.ProcessID);
                    if (process == null)
                    {
                        return;
                    }

                    var module = process.Modules
                                 .SingleOrDefault(m => m.Checksum == obj.ImageChecksum && m.FullName == obj.FileName);
                    if (module == null)
                    {
                        module = new Module(obj.FileName, obj.ImageChecksum, scenarioExecutionResult.PerformanceMonitorCounters);
                        process.Modules.Add(module);
                    }
                    module.RuntimeInstances.Add(
                        new RuntimeInstance(new AddressSpace(obj.ImageBase, (uint)obj.ImageSize), obj.TimeStamp));
                };
                parser.ImageUnload += (ImageLoadTraceData obj) => {
                    var process = processes.SingleOrDefault(p => p.Id == obj.ProcessID);
                    if (process == null)
                    {
                        return;
                    }

                    var module = process.Modules
                                 .SingleOrDefault(m => m.Checksum == obj.ImageChecksum && m.FullName == obj.FileName);
                    if (module == null)
                    {
                        return;
                    }

                    var info = module.RuntimeInstances.SingleOrDefault(i => {
                        return(i.AddressSpace.Start == obj.ImageBase &&
                               i.AddressSpace.Size == obj.ImageSize &&
                               i.LifeSpan.End > obj.TimeStamp);
                    });
                    if (info == null)
                    {
                        return; // Managed methods already unloaded.
                    }
                    info.LifeSpan.End = obj.TimeStamp;
                };

                ////////////////////////////////////////////////////////////////
                // "ntoskrnl.exe" data
                parser.ImageDCStart += (ImageLoadTraceData obj) => {
                    if (obj.ProcessID == 0 && obj.FileName.EndsWith("ntoskrnl.exe"))
                    {
                        if (defaultNtoskrnlModule == null)
                        {
                            defaultNtoskrnlModule = new Module(obj.FileName, obj.ImageChecksum, scenarioExecutionResult.PerformanceMonitorCounters);
                            defaultNtoskrnlModule.RuntimeInstances.Add(
                                new RuntimeInstance(new AddressSpace(obj.ImageBase, (uint)obj.ImageSize), obj.TimeStamp));
                        }
                    }
                };

                ////////////////////////////////////////////////////////////////
                // PMC data
                var pmcSamples = new List <PmcSample>();
                parser.PerfInfoCollectionStart += (SampledProfileIntervalTraceData obj) => {
                    // Update the Pmc intervals.
                    if (scenarioExecutionResult.PerformanceMonitorCounters.Any(pmc => pmc.Id == obj.SampleSource))
                    {
                        if (!pmcSamplingIntervals.ContainsKey(obj.SampleSource))
                        {
                            pmcSamplingIntervals.Add(obj.SampleSource, obj.NewInterval);
                        }
                        else
                        {
                            pmcSamplingIntervals[obj.SampleSource] = obj.NewInterval;
                        }
                    }
                };
                parser.PerfInfoPMCSample += (PMCCounterProfTraceData obj) => {
                    var performanceMonitorCounter = scenarioExecutionResult.PerformanceMonitorCounters
                                                    .SingleOrDefault(pmc => pmc.Id == obj.ProfileSource);
                    if (performanceMonitorCounter == null)
                    {
                        return;
                    }

                    var process = processes.SingleOrDefault(p => p.Id == obj.ProcessID);
                    if (process == null)
                    {
                        return;
                    }

                    process.PerformanceMonitorCounterData[performanceMonitorCounter] += pmcSamplingIntervals[obj.ProfileSource];

                    // Is the IP in the kernel (Under this process)?
                    if (defaultNtoskrnlModule != null && obj.IsInTimeAndAddressIntervals(defaultNtoskrnlModule))
                    {
                        var krnlModule = process.Modules
                                         .SingleOrDefault(m => m.Checksum == defaultNtoskrnlModule.Checksum && m.FullName == defaultNtoskrnlModule.FullName);
                        if (krnlModule == null)
                        {
                            krnlModule = new Module(defaultNtoskrnlModule);
                            process.Modules.Add(krnlModule);
                        }
                    }

                    var modules = process.Modules
                                  .Where(m => {
                        return(obj.IsInTimeAndAddressIntervals(m));
                    })
                                  .Select(m => m);

                    if (modules.Count() == 0)
                    {
                        // This might fall in managed code. We need to buffer and test it afterwards.
                        pmcSamples.Add(new PmcSample {
                            InstructionPointer = obj.InstructionPointer,
                            ProcessId          = obj.ProcessID,
                            ProfileSourceId    = obj.ProfileSource,
                            TimeStamp          = obj.TimeStamp,
                            SamplingInterval   = pmcSamplingIntervals[obj.ProfileSource],
                        });
                        return;
                    }

                    modules.ForEach(module => {
                        module.PerformanceMonitorCounterData[performanceMonitorCounter] += pmcSamplingIntervals[obj.ProfileSource];
                    });
                };

                ////////////////////////////////////////////////////////////////
                // .NET modules
                parser.Source.Clr.LoaderModuleLoad += (ModuleLoadUnloadTraceData obj) => {
                    var process = processes.SingleOrDefault(p => p.Id == obj.ProcessID);
                    if (process == null)
                    {
                        return;
                    }

                    var modulePath = string.IsNullOrEmpty(obj.ModuleNativePath) ? obj.ModuleILPath : obj.ModuleNativePath;
                    var module     = process.Modules
                                     .SingleOrDefault(m => m.FullName == modulePath && m.RuntimeInstances.Any(i => i.LifeSpan.IsInInterval(obj.TimeStamp) == 0));
                    if (module == null)
                    {
                        // Not previously loaded (For example, 'Anonymously Hosted DynamicMethods Assembly')
                        module = new DotNetModule(modulePath, DefaultModuleChecksum, scenarioExecutionResult.PerformanceMonitorCounters, obj.ModuleID);
                        process.Modules.Add(module);
                    }
                    else
                    {
                        // Update/Swap the module. It is a .NET module.
                        var dotnetModule = new DotNetModule(module, obj.ModuleID);
                        process.Modules.Remove(module);     // Remove existing
                        process.Modules.Add(dotnetModule);  // Add it back as managed
                    }
                };
                parser.Source.Clr.LoaderModuleUnload += (ModuleLoadUnloadTraceData obj) => {
                    var process = processes
                                  .SingleOrDefault(p => p.Id == obj.ProcessID);
                    if (process == null)
                    {
                        return;
                    }

                    var module = process.Modules
                                 .OfType <DotNetModule>()
                                 .SingleOrDefault(m => m.Id == obj.ModuleID && m.RuntimeInstances.Count > 0);
                    if (module == null)
                    {
                        return;
                    }

                    var info = module.RuntimeInstances
                               .SingleOrDefault(i => i.LifeSpan.IsInInterval(obj.TimeStamp) == 0);
                    if (info == null)
                    {
                        throw new InvalidOperationException($"Unloading non-loaded .NET module: {(string.IsNullOrEmpty(obj.ModuleNativePath) ? obj.ModuleILPath : obj.ModuleNativePath)}");
                    }
                    info.LifeSpan.End = obj.TimeStamp;
                };

                ////////////////////////////////////////////////////////////////
                // .NET methods
                parser.Source.Clr.MethodLoadVerbose += (MethodLoadUnloadVerboseTraceData obj) => {
                    var process = processes
                                  .SingleOrDefault(p => p.Id == obj.ProcessID);
                    if (process == null)
                    {
                        return;
                    }

                    var module = process.Modules
                                 .OfType <DotNetModule>()
                                 .SingleOrDefault(m => m.Id == obj.ModuleID);
                    if (module == null)
                    {
                        var clrHelpersModule = new DotNetModule("$CLRHelpers$", DefaultModuleChecksum, scenarioExecutionResult.PerformanceMonitorCounters, 0);
                        process.Modules.Add(clrHelpersModule);
                        module = clrHelpersModule;
                    }

                    var method = module.Methods
                                 .SingleOrDefault(m => m.Id == obj.MethodID);
                    if (method == null)
                    {
                        method = new DotNetMethod(
                            obj.MethodID,
                            obj.MethodName,
                            obj.MethodNamespace,
                            obj.IsDynamic,
                            obj.IsGeneric,
                            obj.IsJitted
                            );

                        module.Methods.Add(method);
                    }
                    method.RuntimeInstances.Add(
                        new RuntimeInstance(new AddressSpace(obj.MethodStartAddress, (uint)obj.MethodSize), obj.TimeStamp));
                };
                parser.Source.Clr.MethodUnloadVerbose += (MethodLoadUnloadVerboseTraceData obj) => {
                    var process = processes.SingleOrDefault(p => p.Id == obj.ProcessID);
                    if (process == null)
                    {
                        return;
                    }

                    var module = process.Modules
                                 .OfType <DotNetModule>()
                                 .SingleOrDefault(m => m.Id == obj.ModuleID);
                    if (module == null)
                    {
                        return;
                    }

                    var method = module.Methods
                                 .SingleOrDefault(m => m.Id == obj.MethodID);
                    if (method == null)
                    {
                        return;
                    }

                    var info = method.RuntimeInstances.SingleOrDefault(i => {
                        return(i.AddressSpace.Start == obj.MethodStartAddress &&
                               i.AddressSpace.Size == obj.MethodSize &&
                               i.LifeSpan.End > obj.TimeStamp);
                    });
                    if (info == null)
                    {
                        throw new InvalidOperationException($"Unloading non-loaded .NET method: {obj.MethodName}");
                    }
                    info.LifeSpan.End = obj.TimeStamp;
                };

                source.Process();

                // TODO: We could order modules/methods by timestamp, then by address?

                // Map PMC to managed modules.
                for (int i = pmcSamples.Count - 1; i >= 0; i--)
                {
                    var pmc = pmcSamples[i];

                    var performanceMonitorCounter = scenarioExecutionResult.PerformanceMonitorCounters
                                                    .SingleOrDefault(p => p.Id == pmc.ProfileSourceId);
                    if (performanceMonitorCounter == null)
                    {
                        continue;
                    }

                    processes
                    .Single(p => p.Id == pmc.ProcessId).Modules
                    .OfType <DotNetModule>()
                    .ForEach(module => {
                        var methodsCount = module.Methods
                                           .Where(m => {
                            return(m.RuntimeInstances.Any(info => info.LifeSpan.IsInInterval(pmc.TimeStamp) == 0 &&
                                                          info.AddressSpace.IsInInterval(pmc.InstructionPointer) == 0));
                        })
                                           .Count();
                        if (methodsCount != 0)
                        {
                            module.PerformanceMonitorCounterData[performanceMonitorCounter] += pmc.SamplingInterval;
                            pmcSamples.RemoveAt(i);
                        }
                    });
                }

                // Map PMC to Unknown module.
                const string UnknownModuleName = "Unknown";
                pmcSamples
                .GroupBy(pmc => pmc.ProcessId)
                .Select(g1 => {
                    return(new {
                        ProcessId = g1.Key,
                        PerformanceMonitorCounters = g1
                                                     .GroupBy(pmc => pmc.ProfileSourceId)
                                                     .ToDictionary(
                            g2 => scenarioExecutionResult.PerformanceMonitorCounters.Single(pmc => pmc.Id == g2.Key),
                            g2 => g2.Aggregate(0, (long count, PmcSample pmcSample) => count + pmcSample.SamplingInterval)),
                    });
                })
                .ForEach(pmcRollover => {
                    var process   = processes.Single(p => p.Id == pmcRollover.ProcessId);
                    var newModule = new Module(UnknownModuleName, DefaultModuleChecksum, scenarioExecutionResult.PerformanceMonitorCounters);
                    pmcRollover.PerformanceMonitorCounters.ForEach(pair => {
                        newModule.PerformanceMonitorCounterData[pair.Key] = pair.Value;
                    });
                    process.Modules.Add(newModule);
                });

                return(processes);
            }
        }
示例#19
0
        public void FetchEvents()
        {
            var sessionName = "ETWEventSession";
            Action <TraceEvent> logAction = delegate(TraceEvent data)
            {
                string logToMonitor = data.ToString();
                string lg           = logToMonitor.ToLower();
                if (WmiPreId != "0" && (logToMonitor.Contains(WmiPreId) || logToMonitor.Contains("wmiprvse")))
                {
                    return;
                }
                if (Operation == 4)
                {
                    if (PathToWatchList.PathToWatches.Count > 0)
                    {
                        if (PathToWatchList.PathToWatches.FirstOrDefault(x => lg.Contains(x.Path)) != null)
                        {
                            Console.WriteLine(logToMonitor);
                            _xml.LoadXml(logToMonitor.Replace("/>", " Time=\"" + data.TimeStamp + "\" />"));
                            var xdFile = JsonConvert.SerializeXmlNode(_xml);
                            ConqueEvent.Enqueue(xdFile);
                        }
                    }
                }
                else if (Operation == 2)
                {
                    if (KeyToWatchList.KeyToWatches.Count > 0)
                    {
                        if (KeyToWatchList.KeyToWatches.FirstOrDefault(x => lg.Contains(x.Key)) != null)
                        {
                            Console.WriteLine(logToMonitor);
                            _xml.LoadXml(logToMonitor.Replace("/>", " Time=\"" + data.TimeStamp + "\" />"));
                            var xdFile = JsonConvert.SerializeXmlNode(_xml);
                            ConqueEvent.Enqueue(xdFile);
                        }
                    }
                }
                else if (Operation == 3)
                {
                    if (NetConfigList.IpToWatches.Count > 0 || NetConfigList.PortToWatches.Count > 0)
                    {
                        var firstIndex  = logToMonitor.IndexOf("daddr=\"");
                        var lastIndex   = logToMonitor.Substring(firstIndex + 7).IndexOf("\"");// 7 is length daddr="
                        var ipAddr      = Utility.LongToIpAddress(logToMonitor.Substring(firstIndex + 7, lastIndex));
                        var firstIndexp = logToMonitor.IndexOf("sport=\"");
                        var lastIndexp  = logToMonitor.Substring(firstIndexp + 7).IndexOf("\"");// 7 is length sport="
                        var sport       = logToMonitor.Substring(firstIndexp + 7, lastIndexp).Replace("-", "");
                        if (NetConfigList.IpToWatches.FirstOrDefault(x => ipAddr.Contains(x.IpAddress)) != null || NetConfigList.PortToWatches.FirstOrDefault(x => sport.Contains(x.Port)) != null)
                        {
                            Console.WriteLine(logToMonitor);
                            _xml.LoadXml(logToMonitor.Replace("/>", " Time=\"" + data.TimeStamp + "\" />"));
                            var xdFile = JsonConvert.SerializeXmlNode(_xml);
                            ConqueEvent.Enqueue(xdFile);
                        }
                    }
                }
                else
                {
                    var log = new StringBuilder(logToMonitor);
                    Console.WriteLine(logToMonitor);
                    int i = lg.IndexOf("PID", StringComparison.Ordinal);
                    int j = lg.LastIndexOf("PID", StringComparison.Ordinal);
                    if (i != j)
                    {
                        log = log.Remove(j, 3).Insert(j, "PIDD");
                    }

                    _xml.LoadXml(log.ToString().Replace("/>", " Time=\"" + data.TimeStamp + "\" />"));
                    var xd = JsonConvert.SerializeXmlNode(_xml);
                    ConqueEvent.Enqueue(xd);
                }
            };

            if (Operation == 4)//if user choose file event use different session
            {
                //session.EnableProvider(fileProviderGuid, TraceEventLevel.Informational, 0x100);
                using (var kernelSession = new TraceEventSession(KernelTraceEventParser.KernelSessionName, null))
                {
                    using (var kernelSource = new ETWTraceEventSource(KernelTraceEventParser.KernelSessionName, TraceEventSourceType.Session))
                    {
                        var kernelParser = new KernelTraceEventParser(kernelSource);
                        kernelSession.StopOnDispose = true;
                        kernelSession.EnableKernelProvider(
                            //KernelTraceEventParser.Keywords.NetworkTCPIP
                            //  KernelTraceEventParser.Keywords.Process |
                            //KernelTraceEventParser.Keywords.Registry
                            KernelTraceEventParser.Keywords.DiskFileIO |
                            KernelTraceEventParser.Keywords.FileIOInit |
                            KernelTraceEventParser.Keywords.Thread |
                            KernelTraceEventParser.Keywords.FileIO
                            );
                        kernelParser.All += logAction;
                        kernelSource.Process();
                    }
                }
            }
            else
            {
                using (var session = new TraceEventSession(sessionName, null))
                {
                    session.StopOnDispose = true;
                    using (var source = new ETWTraceEventSource(sessionName, TraceEventSourceType.Session))
                    {
                        var registerParser = new RegisteredTraceEventParser(source);
                        registerParser.All += logAction;
                        var processProviderGuid  = TraceEventSession.GetProviderByName("Microsoft-Windows-Kernel-Process");
                        var registryProviderGuid = TraceEventSession.GetProviderByName("Microsoft-Windows-Kernel-Registry");
                        var networkProviderGuid  = TraceEventSession.GetProviderByName("Microsoft-Windows-Kernel-Network");
                        var fileProviderGuid     = TraceEventSession.GetProviderByName("Microsoft-Windows-Kernel-File");
                        if (processProviderGuid == Guid.Empty)
                        {
                            Console.WriteLine("Error could not find Microsoft-Windows-Kernel-Process etw provider.");
                        }
                        switch (Operation)
                        {
                        case 1:
                        {
                            session.EnableProvider(processProviderGuid, TraceEventLevel.Informational, 0x10);
                            source.Process();
                            break;
                        }

                        case 2:
                        {
                            session.EnableProvider(registryProviderGuid, TraceEventLevel.Informational, 0x02100);
                            source.Process();
                            break;
                        }

                        case 3:
                        {
                            session.EnableProvider(networkProviderGuid, TraceEventLevel.Informational, 0x10);
                            source.Process();
                            break;
                        }
                        }

                        //session.EnableProvider(registryProviderGuid, TraceEventLevel.Informational, 0x02100);
                        // session.EnableProvider(networkProviderGuid, TraceEventLevel.Informational, 0x10);
                        // session.EnableProvider(fileProviderGuid, TraceEventLevel.Informational, 0x0200);
                    }
                }
            }
        }
 public WindowsKernelParser(ETWTraceEventSource source)
 {
     parser = new KernelTraceEventParser(source);
 }