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); }
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(); }
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); }
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); }
/// <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); } } }
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(); }
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(); }
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(); }
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)); }
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; }; }
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)); }
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"); } }
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); } } }
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; } }; }
/// <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); } }
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); }