private RegisteredTraceEventParser RegisterParser(ETWTraceEventSource source) { var registeredParser = new RegisteredTraceEventParser(source); registeredParser.All += _aggregator.TraceEventAvailable; return(registeredParser); }
static void UserLogon() { Console.WriteLine("Waiting for a user to log on..."); var sessionName = "UserSession"; //Change this for OPSEC using (var session = new TraceEventSession(sessionName, null)) { session.StopOnDispose = true; using (var source = new ETWTraceEventSource(sessionName, TraceEventSourceType.Session)) //Use a realtime session { var parser = new RegisteredTraceEventParser(source); parser.All += delegate(TraceEvent data) { string message = data.FormattedMessage; if (!string.IsNullOrEmpty(message) && message.Contains("Authentication stopped. Result 0")) { Console.WriteLine("User login detected"); DoEvil(); } }; Guid provider = new Guid("DBE9B383-7CF3-4331-91CC-A3CB16A3B538"); session.EnableProvider(provider, TraceEventLevel.Verbose); source.Process(); Console.CancelKeyPress += (object s, ConsoleCancelEventArgs args) => session.Stop(); session.Dispose(); }; } }
public void MonitorNetwork() { var sessionName = "NT Kernel Logger"; using (var session = new TraceEventSession(sessionName, null)) // the null second parameter means 'real time session' { session.StopOnDispose = true; using (var source = new ETWTraceEventSource(sessionName, TraceEventSourceType.Session)) { Action <TraceEvent> action = delegate(TraceEvent data) { if (ready) { tHandler = new TimeoutHandler(1); tHandler.SessionTimeout += tHandler_SessionTimeout; ready = false; addData(data); } }; var registeredParser = new RegisteredTraceEventParser(source); registeredParser.All += action; session.EnableKernelProvider(KernelTraceEventParser.Keywords.NetworkTCPIP); source.Process(); } } }
/// <summary> /// Create dissector for one provider /// </summary> /// <param name="providerName">Name of provider</param> /// <param name="outputPath">Path to putput file</param> static void CreateDissectorFromProvider(string providerName, string outputPath) { try { var xml = RegisteredTraceEventParser.GetManifestForRegisteredProvider(providerName); XmlSerializer serializer = new XmlSerializer(typeof(Manifest)); using (TextReader reader = new StringReader(xml)) { Manifest manifest = (Manifest)serializer.Deserialize(reader); using (var stream = new FileStream(outputPath, FileMode.Create)) { new DissectorLUA(manifest).create(stream); } } } catch (System.ApplicationException e) { Console.WriteLine(e.Message); } catch (System.InvalidOperationException) { // sometimes XML generate by RegisteredTraceEventParser can't be parsed by the microsoft parser... } }
public void Load(string fileName) { ETWTraceEventSource source = new ETWTraceEventSource(fileName); RegisteredTraceEventParser parser = new RegisteredTraceEventParser(source); parser.All += Parser_All; source.Process(); }
public static void X() { // Create a new session, turn on some events, and get the stream of events var session = new TraceEventSession("MySession"); session.EnableProvider(TraceEventProviders.GetEventSourceGuidFromName("MyEventSource")); var eventStream = session.Source; // Create an in memory GENERIC list of parsed (basically string) records that can hold the results GenericEventSource eventSource = new GenericEventSource(); // Hook up the ETW eventStream to the generic in memory event source. var dynamicParser = new DynamicTraceEventParser(eventStream); Action <TraceEvent> sendToEventStore = delegate(TraceEvent data) { var processName = data.ProcessName; if (!processName.StartsWith("(")) { processName += " (" + data.ProcessID + ")"; } var fieldNames = data.PayloadNames; var fields = new string[fieldNames.Length]; for (int i = 0; i < fields.Length; i++) { fields[i] = data.PayloadString(i); } var genericRecord = new GenericEventRecord(data.EventName, data.ProcessName, data.TimeStampRelativeMSec, fieldNames, fields); eventSource.Records.AddRecord(genericRecord); }; dynamicParser.All += sendToEventStore; var registeredParser = new RegisteredTraceEventParser(eventStream); registeredParser.All += sendToEventStore; eventStream.UnhandledEvents += sendToEventStore; // Start processing ETW events and filling the in-memory list (which the GUI is observing). var thread = new Thread(delegate() { session.Source.Process(); }); thread.Start(); var window = new EventWindow(GuiApp.MainWindow, eventSource); window.Show(); }
/// <summary> /// Dump the provider if the manifest does not exist /// If the provider is not manifest based exception will be raised /// Uses the same function perfview uses to dump the providers /// </summary> /// <param name="providerName">name of the ETW providers</param> static void DumpProvider(string providerName) { string manifestFileName = providerName + ".xml"; string manifestFilePath = Path.Combine(manifestsDirectory, manifestFileName); if (File.Exists(manifestFilePath)) { return; } Console.WriteLine("[+] Writing " + manifestFileName); string manifest = RegisteredTraceEventParser.GetManifestForRegisteredProvider(providerName); File.WriteAllText(manifestFilePath, manifest); }
public void Start() { if (this.session != null) { throw new InvalidOperationException("The session is already started."); } CloseExistingSession(this.name); this.session = new TraceEventSession(this.name, null); this.session.StopOnDispose = true; this.session.EnableProvider(KernelProcessProviderId, TraceEventLevel.Informational, ulong.MaxValue, 0x10); this.eventSource = new ETWTraceEventSource(this.name, TraceEventSourceType.Session); this.parser = new RegisteredTraceEventParser(this.eventSource); this.parser.All += this.OnEventRead; // Process() blocks until the session is shut down, so we'll run this on another thread. this.cts = new CancellationTokenSource(); this.processTask = Task.Factory.StartNew(() => this.eventSource.Process(), TaskCreationOptions.LongRunning); }
private static void CallThis() { var sessionName = "ProcessMonitorSession"; using (var session = new TraceEventSession(sessionName, null)) { session.StopOnDispose = true; using (var source = new ETWTraceEventSource(sessionName, TraceEventSourceType.Session)) { var registeredParser = new RegisteredTraceEventParser(source); registeredParser.All += delegate(TraceEvent data) { var taskName = data.TaskName; if (taskName == "ProcessStart" || taskName == "ProcessStop") { string exe = (string)data.PayloadByName("ImageName"); string exeName = Path.GetFileNameWithoutExtension(exe); int processId = (int)data.PayloadByName("ProcessID"); if (taskName == "ProcessStart") { int parentProcessId = (int)data.PayloadByName("ParentProcessID"); // log: //string.Format("{0:HH:mm:ss.fff}: {1,-12}: {2} ID: {3} ParentID: {4}", data.TimeStamp, taskName, exeName, processId, parentProcessId); } else { int exitCode = (int)data.PayloadByName("ExitCode"); long cpuCycle = (long)data.PayloadByName("CPUCycleCount"); // log: //string.Format("{0:HH:mm:ss.fff}: {1,-12}: {2} ID: {3} EXIT: {4} CPU Cycles: {5:n0}", data.TimeStamp, taskName, exeName, processId, exitCode, cpuCycle); } } }; //var processProviderGuid = TraceEventSession. } } }
/// <summary> /// Build a correct forwarder with the matched Parser /// Follow the factory model /// </summary> /// <param name="provider">ProviderGuid input provider</param> /// <returns></returns> public static Forwarder Build(ProviderGuid provider) { switch (provider.Type) { case ProviderGuid.ProviderType.Manifest: var xml = RegisteredTraceEventParser.GetManifestForRegisteredProvider(provider.Guid); XmlSerializer serializer = new XmlSerializer(typeof(Manifest.Manifest)); using (TextReader reader = new StringReader(xml)) { var manifest = (Manifest.Manifest)serializer.Deserialize(reader); return(new Forwarder(new ManifestParser(manifest))); } case ProviderGuid.ProviderType.TL: return(new Forwarder(new TraceLoggingParser())); case ProviderGuid.ProviderType.WPP: return(new Forwarder(new NullParser())); } throw new NotImplementedException(); }
private void DoViewManifestClick(object sender, RoutedEventArgs e) { StatusBar log = GuiApp.MainWindow.StatusBar; string selectedProvider = ProviderNameListBox.SelectedItem as string; if (selectedProvider == null) { log.LogError("No provider selected"); return; } log.Log("[Looking up manifest for " + selectedProvider + " ]"); string manifestString = RegisteredTraceEventParser.GetManifestForRegisteredProvider(selectedProvider); var textEditorWindow = new TextEditorWindow(); textEditorWindow.Width = 1200; textEditorWindow.Height = 800; textEditorWindow.TextEditor.IsReadOnly = true; textEditorWindow.TextEditor.AppendText(manifestString); textEditorWindow.Show(); }
/// <summary> /// Adds the appropriate handlers to <see cref="TraceEventSource"/> based on the value of /// <see cref="ProcessEventTypes"/> and processes the events in the source. /// </summary> protected void ProcessEvents() { if (this.ProcessEventTypes.HasFlag(EventTypes.Registered)) { var registeredEventParser = new RegisteredTraceEventParser(this.TraceEventSource); registeredEventParser.All += this.ProcessEvent; } if (this.ProcessEventTypes.HasFlag(EventTypes.EventSource)) { // We don't pre-process to get manifests, instead we hold onto unhandled events until we see their // provider get activated, then we attempt to re-process them. This sort of goofs up ordering, but // ETW wasn't reliably ordered to begin with. In general the expectation is that the manifests will // show up near the initial events so these queues are not expected to grow substantially. // We can only do this if the user isn't asking for unknown events, however. if (!this.ProcessEventTypes.HasFlag(EventTypes.Unknown)) { this.TraceEventSource.UnhandledEvents += this.ProcessUnhandledEvent; this.UnhandledEvents = new Dictionary<Guid, Queue<TraceEvent>>(); } this.TraceEventSource.Dynamic.All += this.ProcessEvent; } if (this.ProcessEventTypes.HasFlag(EventTypes.Clr)) { this.TraceEventSource.Clr.All += this.ProcessEvent; } if (this.ProcessEventTypes.HasFlag(EventTypes.Kernel)) { this.TraceEventSource.Kernel.All += this.ProcessEvent; } if (this.ProcessEventTypes.HasFlag(EventTypes.Unknown)) { this.MaximumBufferTimeForUnknownEvents = TimeSpan.Zero; this.TraceEventSource.UnhandledEvents += this.ProcessEvent; } this.OnSessionStart(this.CurrentSessionName, this.TraceEventSource.SessionStartTime); long beginCount = this.Count; long beginUnreadable = this.UnreadableEvents; this.TraceEventSource.Process(); this.EventsLost += this.TraceEventSource.EventsLost; // Calculate the number of events we never managed to read. if (this.UnhandledEvents != null) { foreach (var unhandledList in this.UnhandledEvents.Values) { this.UnreadableEvents += unhandledList.Count; } } // If the session is realtime then the end time will basically be nonsense, but we can pretty // reasonably infer it just ended right now. this.OnSessionEnd(this.CurrentSessionName, (this.TraceEventSource.SessionEndTime == DateTime.MaxValue ? DateTime.Now : this.TraceEventSource.SessionEndTime), this.Count - beginCount, this.TraceEventSource.EventsLost, this.UnreadableEvents - beginUnreadable); }
static void Main() { /* * output all ETW events in a single line 'grep-able' format per provider * * Microsoft.Diagnostics.Tracing does the heavy lifting and provides us with a (partial) ETW manifest, * but lallousx86's WEPExplorer provides improved metadata for providers that are also * Eventlog Providers (i.e. channel, message template). * Unfortunately it it doesn't output event names, so we need to combine both. * * This ticket would remove the need for the dependency on WEPExplorer - * https://github.com/microsoft/perfview/issues/1067 * * And these two tickets would improve the quality of the generated manifest XML * https://github.com/microsoft/perfview/issues/1068 * https://github.com/microsoft/perfview/issues/1069 * * For convenience, I also use the manifest parsing code from EtwExplorer. * And was about to contribute back my MOF parsing code. */ /* * you need to separately build WEPExplorer and copy cli.exe to your working directory * https://github.com/lallousx86/WinTools/tree/master/WEPExplorer */ var useWEPExplorer = File.Exists(WinTools.Cli.CLI_PATH); if (!useWEPExplorer) { Console.WriteLine($"{Cli.CLI_PATH} from WEPExplorer is missing - Eventlog provider data will be incomplete"); } var outputDir = "output"; var manifestOutputDir = Path.Combine(outputDir, "manifest"); var mofOutputDir = Path.Combine(outputDir, "mof"); var unknownOutputDir = Path.Combine(outputDir, "unknown"); Directory.CreateDirectory(outputDir); Directory.CreateDirectory(manifestOutputDir); Directory.CreateDirectory(mofOutputDir); Directory.CreateDirectory(unknownOutputDir); var product = Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion", "ProductName", "").ToString(); var release = Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion", "ReleaseId", "").ToString(); var build = Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion", "BuildLabEx", "").ToString(); using (var windowsVersionFile = new StreamWriter(Path.Combine(outputDir, "version.txt"))) { windowsVersionFile.WriteLine($"{product} {release} ({build})"); } foreach (var provider in TraceEventProviders.GetPublishedProviders()) { var name = TraceEventProviders.GetProviderName(provider); // use the provider name as the output filename, but... // ':' is not a valid filename character - use a dash instead // and I just don't like spaces in filenames - use an underscore instead var tsvFilename = $"{name}.tsv".Replace(' ', '_').Replace(':', '-'); bool foundProviderDetails = false; EtwManifest manifest = null; // is this is manifest-based provider? string manifestXML = string.Empty; try { manifestXML = RegisteredTraceEventParser.GetManifestForRegisteredProvider(provider); using (var tsvFile = new StreamWriter(Path.Combine(manifestOutputDir, tsvFilename))) { // Summary: // Given a provider GUID that has been registered with the operating system, get // a string representing the ETW manifest for that provider. Note that this manifest // is not as rich as the original source manifest because some information is not // actually compiled into the binary manifest that is registered with the OS. // a few hacky escaping fixes so that we can parse the xml... if (name == "Microsoft-Windows-AppXDeployment-Server") { manifestXML = manifestXML.Replace("\"any\"", ""any""); } if (name == "Microsoft-Windows-GroupPolicy") { manifestXML = manifestXML.Replace("\"No loopback mode\"", ""No loopback mode""); manifestXML = manifestXML.Replace("\"Merge\"", ""Merge""); manifestXML = manifestXML.Replace("\"Replace\"", ""Replace""); } if (name == "Microsoft-Windows-NetworkProvider") { manifestXML = manifestXML.Replace("<Property>", "<Property>"); manifestXML = manifestXML.Replace("<Value>", "<Value>"); manifestXML = manifestXML.Replace("<Integer>", "<Integer>"); manifestXML = manifestXML.Replace("<Quoted String>", "<Quoted String>"); } if (name == "Microsoft-Windows-Ntfs") { manifestXML = manifestXML.Replace("\"CHKDSK /SCAN\"", ""CHKDSK /SCAN""); manifestXML = manifestXML.Replace("\"CHKDSK /SPOTFIX\"", ""CHKDSK /SPOTFIX""); manifestXML = manifestXML.Replace("\"CHKDSK /F\"", ""CHKDSK /F""); manifestXML = manifestXML.Replace("\"REPAIR-VOLUME <drive:> -SCAN\"", ""REPAIR-VOLUME <drive:> -SCAN""); manifestXML = manifestXML.Replace("\"REPAIR-VOLUME <drive:>\"", ""REPAIR-VOLUME <drive:>""); manifestXML = manifestXML.Replace("<unknown>", "<unknown>"); } manifest = ManifestParser.Parse(manifestXML); foundProviderDetails = true; tsvFile.WriteLine($"provider\tevent_id\tversion\tevent(fields)\topcode\tkeywords\ttask\tlevel\tevtlog_channel\tevtlog_message"); foreach (var evt in manifest.Events) { var fields = string.Empty; try { foreach (var param in manifest.Templates.First(t => t.Id == evt.Template).Items) { if (fields != string.Empty) { fields += ", "; } fields += $"{param.Type} {param.Name}"; } } catch (InvalidOperationException) { } // no fields var Channel = string.Empty; var Message = string.Empty; if (useWEPExplorer) { // add channel and message from WEPExplorer (if available) var xmlNode = WEPExplorer.GetProviderMetadataXml(name); try { if (xmlNode != null && xmlNode.HasChildNodes) { foreach (XmlNode xnEvent in xmlNode.SelectNodes($"/{WEPExplorer.XML_PROVIDERS}/{WEPExplorer.XML_PROVIDER}/{WEPExplorer.XML_EVENT_METADATA}/{WEPExplorer.XML_EVENT}[{WEPExplorer.XML_ID}={evt.Value}][{WEPExplorer.XML_VERSION}={evt.Version}]")) { Channel = WEPExplorer.xnGetText(xnEvent, WEPExplorer.XML_CHANNEL); Message = WEPExplorer.xnGetText(xnEvent, WEPExplorer.XML_MESSAGE).Replace("\r", @"\r").Replace("\n", @"\n"); } } } catch { var errorFilename = "ERROR_WEPExplorer.xml"; Console.WriteLine($"WEPExplorer XML PARSE FAILURE - name={name} file={errorFilename}"); using (var errorFile = new StreamWriter(Path.Combine(outputDir, errorFilename))) { errorFile.WriteLine(xmlNode.OuterXml); } } } var etwEvent = $"{name}\t{evt.Value}\t{evt.Version}\t{evt.Symbol}({fields})\t{evt.Opcode}\t{evt.Keyword}\t{evt.Task}\t{evt.Level}\t{Channel}\t{Message}"; etwEvent = etwEvent.Replace(""", "\"").Replace("<", "<").Replace(">", ">"); tsvFile.WriteLine(etwEvent); } } } catch (Exception e) { if (manifestXML.Length != 0) { var errorFilename = "ERROR_Manifest.xml"; Console.WriteLine($"MANIFEST PARSE FAILURE - name={name} size={manifestXML.Length} file={errorFilename}"); using (var errorFile = new StreamWriter(Path.Combine(outputDir, errorFilename))) { errorFile.WriteLine(manifestXML); } throw e; } } // is this a legacy (MOF-based) provider manifest = null; try { manifest = ManifestParser.ParseWmiEventTraceClass(provider); } catch (ApplicationException) { } if (manifest != null) { foundProviderDetails = true; using (var tsv_file = new StreamWriter(Path.Combine(mofOutputDir, tsvFilename))) { tsv_file.WriteLine($"provider\tcategory\tevent_id\tversion\tevent(fields)\tevent_type\tdescription"); foreach (var evt in manifest.Events) { var fields = string.Empty; try { foreach (var param in manifest.Templates.First(t => t.Id == evt.Template).Items) { if (!string.IsNullOrEmpty(fields)) { fields += ", "; } fields += $"{param.Type} {param.Name}"; } } catch (InvalidOperationException) { } // no fields var etwEvent = $"{name}\t{evt.Task}\t{evt.Value}\t{evt.Version}\t{evt.Symbol}({fields})\t{evt.Opcode}\t{evt.Keyword}"; etwEvent = etwEvent.Replace(""", "\"").Replace("<", "<").Replace(">", ">"); tsv_file.WriteLine(etwEvent); } } } // no manifest and no MOF... if (!foundProviderDetails) { using (var tsv_file = new StreamWriter(Path.Combine(unknownOutputDir, tsvFilename))) { tsv_file.WriteLine($"provider"); tsv_file.WriteLine(name); } } } Console.WriteLine("All done"); }
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); }
public CWatcherGC() { // 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; } Process[] pr = null; while (pr == null) { pr = Process.GetProcessesByName(/*"TradeSystem"*/ "P2ConnectorNativeImp"); Thread.Sleep(1000); } _procId = pr[0].Id; // As mentioned below, sessions can outlive the process that created them. Thus you need a way of // naming the session so that you can 'reconnect' to it from another process. This is what the name // is for. It can be anything, but it should be descriptive and unique. If you expect mulitple versions // of your program to run simultaneously, you need to generate unique names (e.g. add a process ID suffix) var sessionName = "ProessMonitorSession"; using (var session = new TraceEventSession(sessionName, null)) // the null second parameter means 'real time session' { // Note that sessions create a OS object (a session) that lives beyond the lifetime of the process // that created it (like Filles), thus you have to be more careful about always cleaning them up. // An importanty way you can do this is to set the 'StopOnDispose' property which will cause the session to // stop (and thus the OS object will die) when the TraceEventSession dies. Because we used a 'using' // statement, this means that any exception in the code below will clean up the OS object. session.StopOnDispose = true; // By default, if you hit Ctrl-C your .NET objects may not be disposed, so force it to. It is OK if dispose is called twice. 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) { if (data.ProcessID == _procId) { // if (data.EventName == "GC/SuspendEEStart" || data.EventName == "GC/SuspendEEStop") //Console.WriteLine("GOT EVENT: " + data.ToString()); _logger.Log(data.ToString()); } // _logger.Log(" MSec=" + data.TimeStampRelativeMSec + " Tid=" + data.ThreadID + " " + data.EventName+ // " preocessorN=" + data.ProcessorNumber); /* var taskName = data.TaskName; * if (taskName == "ProcessStart" || taskName == "ProcessStop") * { * string exe = (string) data.PayloadByName("ImageName"); * string exeName = Path.GetFileNameWithoutExtension(exe); * * int processId = (int) data.PayloadByName("ProcessID"); * if (taskName == "ProcessStart") * { * int parentProcessId = (int)data.PayloadByName("ParentProcessID"); * Console.WriteLine("{0:HH:mm:ss.fff}: {1,-12}: {2} ID: {3} ParentID: {4}", * data.TimeStamp, taskName, exeName, processId, parentProcessId); * } * else * { * int exitCode = (int) data.PayloadByName("ExitCode"); * long cpuCycles = (long) data.PayloadByName("CPUCycleCount"); * Console.WriteLine("{0:HH:mm:ss.fff}: {1,-12}: {2} ID: {3} EXIT: {4} CPU Cycles: {5:n0}", * data.TimeStamp, taskName, exeName, processId, exitCode, cpuCycles); * } * } */ }; // 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; // You can also simply use 'logman query providers' to find out the GUID yourself and wire it in. //var processProviderGuid = TraceEventSession.GetProviderByName("Microsoft-Windows-Kernel-Process"); var processProviderGuid = TraceEventSession.GetProviderByName("Microsoft-Windows-DotNETRuntime"); if (processProviderGuid == Guid.Empty) { Console.WriteLine("Error could not find Microsoft-Windows-Kernel-Process etw provider."); return;//-1; } // Using logman query providers Microsoft-Windows-Kernel-Process I get // 0x0000000000000010 WINEVENT_KEYWORD_PROCESS // 0x0000000000000020 WINEVENT_KEYWORD_THREAD // 0x0000000000000040 WINEVENT_KEYWORD_IMAGE // 0x0000000000000080 WINEVENT_KEYWORD_CPU_PRIORITY // 0x0000000000000100 WINEVENT_KEYWORD_OTHER_PRIORITY // 0x0000000000000200 WINEVENT_KEYWORD_PROCESS_FREEZE // 0x8000000000000000 Microsoft-Windows-Kernel-Process/Analytic // So 0x10 is WINEVENT_KEYWORD_PROCESS session.EnableProvider(processProviderGuid, TraceEventLevel.Informational, 0x10); //session.EnableProvider(processProviderGuid, TraceEventLevel.Always, 0x0000000000000001); ; session.EnableProvider(processProviderGuid, TraceEventLevel.Always, 0x0000000000000000);; 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"); } } }
/// <summary> /// Adds the appropriate handlers to <see cref="TraceEventSource"/> based on the value of /// <see cref="ProcessEventTypes"/> and processes the events in the source. /// </summary> protected void ProcessEvents() { if (this.ProcessEventTypes.HasFlag(EventTypes.Registered)) { var registeredEventParser = new RegisteredTraceEventParser(this.TraceEventSource); registeredEventParser.All += this.ProcessEvent; } if (this.ProcessEventTypes.HasFlag(EventTypes.EventSource)) { // We don't pre-process to get manifests, instead we hold onto unhandled events until we see their // provider get activated, then we attempt to re-process them. This sort of goofs up ordering, but // ETW wasn't reliably ordered to begin with. In general the expectation is that the manifests will // show up near the initial events so these queues are not expected to grow substantially. // We can only do this if the user isn't asking for unknown events, however. if (!this.ProcessEventTypes.HasFlag(EventTypes.Unknown)) { this.TraceEventSource.UnhandledEvents += this.ProcessUnhandledEvent; this.UnhandledEvents = new Dictionary <Guid, Queue <TraceEvent> >(); } this.TraceEventSource.Dynamic.All += this.ProcessEvent; } if (this.ProcessEventTypes.HasFlag(EventTypes.Clr)) { this.TraceEventSource.Clr.All += this.ProcessEvent; } if (this.ProcessEventTypes.HasFlag(EventTypes.Kernel)) { this.TraceEventSource.Kernel.All += this.ProcessEvent; } if (this.ProcessEventTypes.HasFlag(EventTypes.Unknown)) { this.MaximumBufferTimeForUnknownEvents = TimeSpan.Zero; this.TraceEventSource.UnhandledEvents += this.ProcessEvent; } this.OnSessionStart(this.CurrentSessionName, this.TraceEventSource.SessionStartTime); long beginCount = this.Count; long beginUnreadable = this.UnreadableEvents; this.TraceEventSource.Process(); this.EventsLost += this.TraceEventSource.EventsLost; // Calculate the number of events we never managed to read. if (this.UnhandledEvents != null) { foreach (var unhandledList in this.UnhandledEvents.Values) { this.UnreadableEvents += unhandledList.Count; } } // If the session is realtime then the end time will basically be nonsense, but we can pretty // reasonably infer it just ended right now. this.OnSessionEnd(this.CurrentSessionName, (this.TraceEventSource.SessionEndTime == DateTime.MaxValue ? DateTime.Now : this.TraceEventSource.SessionEndTime), this.Count - beginCount, this.TraceEventSource.EventsLost, this.UnreadableEvents - beginUnreadable); }
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); } } } }