public static int ProcessJSONEventData(String JSONData, OutputType OutputType, String Path, String YaraScan, YaraOptions YaraOptions) { // Yara options if (YaraScan != String.Empty) { byte[] JSONByteArray = Encoding.ASCII.GetBytes(JSONData); List <YSMatches> Matches = SilkUtility.YaraInstance.ScanMemory(JSONByteArray, SilkUtility.YaraRules, null, 0); SilkUtility.YaraRuleMatches.Clear(); if (Matches.Count != 0) { foreach (YSMatches Match in Matches) { SilkUtility.YaraRuleMatches.Add(Match.Rule.Identifier); lock (ConsoleWriterLock) { SilkUtility.ReturnStatusMessage($" -> Yara match: {Match.Rule.Identifier}", ConsoleColor.Magenta); } } // Dynamically update the JSON object -> List<String> YaraRuleMatches JObject obj = JObject.Parse(JSONData); ((JArray)obj["YaraMatch"]).Add(SilkUtility.YaraRuleMatches); JSONData = obj.ToString(Newtonsoft.Json.Formatting.None); } } if (YaraOptions == YaraOptions.All || YaraOptions == YaraOptions.None || (YaraScan != String.Empty && SilkUtility.YaraRuleMatches.Count > 0)) { //--[Return Codes] // 0 == OK // 1 == File write failed // 2 == URL POST request failed // 3 == Eventlog write failed //-- // Process JSON if (OutputType == OutputType.file) { try { if (!File.Exists(Path)) { File.WriteAllText(Path, (JSONData + Environment.NewLine)); } else { File.AppendAllText(Path, (JSONData + Environment.NewLine)); } return(0); } catch { return(1); } } else if (OutputType == OutputType.url) { try { string responseFromServer = string.Empty; HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(Path); webRequest.Timeout = 10000; // 10 second timeout webRequest.Method = "POST"; webRequest.ContentType = "application/json"; webRequest.Accept = "application/json"; using (var streamWriter = new StreamWriter(webRequest.GetRequestStream())) { streamWriter.Write(JSONData); streamWriter.Flush(); streamWriter.Close(); } var httpResponse = (HttpWebResponse)webRequest.GetResponse(); using (var streamReader = new StreamReader(httpResponse.GetResponseStream())) { var result = streamReader.ReadToEnd(); } return(0); } catch { return(2); } } else { Boolean WriteEvent = WriteEventLogEntry(JSONData, EventLogEntryType.Information, EventIds.Event, Path); if (WriteEvent) { return(0); } else { return(3); } } } else { return(0); } }
public static void StartTrace(CollectorType CollectorType, ulong TraceKeywords, OutputType OutputType, String Path, FilterOption FilterOption, Object FilterValue, String YaraScan, YaraOptions YaraOptions, String ProviderName = "", UserTraceEventLevel UserTraceEventLevel = UserTraceEventLevel.Informational) { // Is elevated? if (TraceEventSession.IsElevated() != true) { SilkUtility.ReturnStatusMessage("[!] The collector must be run as Administrator..", ConsoleColor.Red); return; } // Print status SilkUtility.ReturnStatusMessage("[>] Starting trace collector (Ctrl-c to stop)..", ConsoleColor.Yellow); SilkUtility.ReturnStatusMessage("[?] Events captured: 0", ConsoleColor.Green); // We will update this dynamically // The kernel collector has naming requirements if (CollectorType == CollectorType.Kernel) { SilkUtility.EventParseSessionName = KernelTraceEventParser.KernelSessionName; } else { // We add a GUID in case of concurrent SilkETW execution String RandId = Guid.NewGuid().ToString(); SilkUtility.EventParseSessionName = ("SilkETWUserCollector_" + RandId); } // Create trace session using (var TraceSession = new TraceEventSession(SilkUtility.EventParseSessionName)) { // The collector cannot survive process termination (safeguard) TraceSession.StopOnDispose = true; // Create event source using (var EventSource = new ETWTraceEventSource(SilkUtility.EventParseSessionName, TraceEventSourceType.Session)) { // Ctrl-c callback handler SilkUtility.SetupCtrlCHandler(() => { TerminateCollector(); }); // A DynamicTraceEventParser can understand how to read the embedded manifests that occur in the dataStream var EventParser = new DynamicTraceEventParser(EventSource); // Loop events as they arrive EventParser.All += delegate(TraceEvent data) { // It's a bit ugly but ... ¯\_(ツ)_/¯ if (FilterOption != FilterOption.None) { if (FilterOption == FilterOption.Opcode && (byte)data.Opcode != (byte)FilterValue) { SilkUtility.ProcessEventData = false; } else if (FilterOption == FilterOption.ProcessID && data.ProcessID != (UInt32)FilterValue) { SilkUtility.ProcessEventData = false; } else if (FilterOption == FilterOption.ProcessName && data.ProcessName != (String)FilterValue) { SilkUtility.ProcessEventData = false; } else if (FilterOption == FilterOption.EventName && data.EventName != (String)FilterValue) { SilkUtility.ProcessEventData = false; } else { SilkUtility.ProcessEventData = true; } } else { SilkUtility.ProcessEventData = true; } // Only process/serialize events if they match our filter if (SilkUtility.ProcessEventData) { // Display running event count SilkUtility.RunningEventCount += 1; SilkUtility.UpdateEventCount("[?] Events captured: " + SilkUtility.RunningEventCount); var eRecord = new EventRecordStruct { ProviderGuid = data.ProviderGuid, YaraMatch = new List <String>(), ProviderName = data.ProviderName, EventName = data.EventName, Opcode = data.Opcode, OpcodeName = data.OpcodeName, TimeStamp = data.TimeStamp, ThreadID = data.ThreadID, ProcessID = data.ProcessID, ProcessName = data.ProcessName, PointerSize = data.PointerSize, EventDataLength = data.EventDataLength }; var EventProperties = new Hashtable(); // Try to parse event XML try { StringReader XmlStringContent = new StringReader(data.ToString()); XmlTextReader EventElementReader = new XmlTextReader(XmlStringContent); while (EventElementReader.Read()) { for (int AttribIndex = 0; AttribIndex < EventElementReader.AttributeCount; AttribIndex++) { EventElementReader.MoveToAttribute(AttribIndex); EventProperties.Add(EventElementReader.Name, EventElementReader.Value); } } } catch { // For debugging (?), never seen this fail EventProperties.Add("XmlEventParsing", "false"); } eRecord.XmlEventData = EventProperties; // Serialize to JSON String JSONEventData = Newtonsoft.Json.JsonConvert.SerializeObject(eRecord); int ProcessResult = SilkUtility.ProcessJSONEventData(JSONEventData, OutputType, Path, YaraScan, YaraOptions); // Verify that we processed the result successfully if (ProcessResult != 0) { if (ProcessResult == 1) { SilkUtility.ReturnStatusMessage("[!] The collector failed to write to file", ConsoleColor.Red); } else { SilkUtility.ReturnStatusMessage("[!] The collector failed to POST the result", ConsoleColor.Red); } // Shut down the collector TerminateCollector(); } } }; // Specify the providers details if (CollectorType == CollectorType.Kernel) { TraceSession.EnableKernelProvider((KernelTraceEventParser.Keywords)TraceKeywords); } else { // Note that the collector doesn't know if you specified a wrong provider name, // the only tell is that you won't get any events ;) TraceSession.EnableProvider(ProviderName, (TraceEventLevel)UserTraceEventLevel, TraceKeywords); } // Continuously process all new events in the data source EventSource.Process(); // Helper to clean up colloector void TerminateCollector() { EventSource.StopProcessing(); TraceSession?.Stop(); Console.CursorVisible = true; SilkUtility.ReturnStatusMessage("[+] Collector terminated", ConsoleColor.Green); } } } }