protected override void OnStop() { // Guardrail for timeout RequestAdditionalTime(5000); // Check if any collector tasks are registered if (SilkUtility.CollectorTaskList.Any()) { // We pop terminated threads out of the list foreach (CollectorInstance CollectorTask in SilkUtility.CollectorTaskList) { try { CollectorTask.EventSource.StopProcessing(); TraceEventSession.GetActiveSession(CollectorTask.EventParseSessionName).Dispose(); SilkUtility.CollectorTaskList.Remove(CollectorTask); SilkUtility.WriteCollectorGuidMessageToServiceTextLog(CollectorTask.CollectorGUID, "Collector terminated", false); } catch { } } } // Write status to log SilkUtility.WriteToServiceTextLog("[+] SilkService stopped at: " + DateTime.Now); }
protected override void OnStart(string[] args) { SilkUtility.WriteToServiceTextLog("[+] SilkService started at: " + DateTime.Now); List <CollectorParameters> CollectorConfig = SilkParameters.ReadXmlConfig(); if (!CollectorConfig.Any()) { // We didn't find any ETWCollector elements so we stop the service // Logs in ServiceLog text file // Stop -> OnStop -> Change service state Stop(); } else { Boolean IsSuccess = SilkParameters.ValidateCollectorParameters(CollectorConfig); if (!IsSuccess) { // There was an error in parsing the collector parameters so we stop the service // Logs in ServiceLog text file // Stop -> OnStop -> Change service state Stop(); } else { // Check if the config has 1+ Kernel collectors // Check if multiple collectors are writing to the same file int KCCount = 0; Boolean IsSamePath = false; HashSet <String> CCPath = new HashSet <String>(); for (int i = 0; i < CollectorConfig.Count; i++) { if (CollectorConfig[i].CollectorType == CollectorType.Kernel) { KCCount += 1; } if (CollectorConfig[i].OutputType == OutputType.file) { if (!CCPath.Add(CollectorConfig[i].Path)) { IsSamePath = true; } } } if (KCCount > 1 | IsSamePath) { if (KCCount > 1) { SilkUtility.WriteToServiceTextLog("[!] SilkService can only support one Kernel collector.."); } else { SilkUtility.WriteToServiceTextLog("[!] File based output paths must be unique.."); } Stop(); } else { // We spin up the collector threads SilkUtility.WriteToServiceTextLog("[*] Starting collector threads: " + DateTime.Now); foreach (CollectorParameters Collector in CollectorConfig) { // We create a thread for the collector Thread CollectorThread = new Thread(() => { try { SilkUtility.WriteToServiceTextLog(" [+] GUID: " + Collector.CollectorGUID); SilkUtility.WriteToServiceTextLog(" [>] Type: " + Collector.CollectorType); if (Collector.CollectorType == CollectorType.User) { SilkUtility.WriteToServiceTextLog(" [>] Provider: " + Collector.ProviderName); } else { SilkUtility.WriteToServiceTextLog(" [>] Provider: " + Collector.KernelKeywords); } SilkUtility.WriteToServiceTextLog(" [>] Out Type: " + Collector.OutputType); ETWCollector.StartTrace(Collector); } catch (Exception ex) { SilkUtility.WriteToServiceTextLog("[!] " + ex.ToString()); } // If any collectors terminate by internal error we stop the service Stop(); }); // We have to mark threads as background to ensure they exit in a timely fashion CollectorThread.IsBackground = false; // Start the collector thread CollectorThread.Start(); // We wait for the thread to signal and then reset the event SilkUtility.SignalThreadStarted.WaitOne(); SilkUtility.SignalThreadStarted.Reset(); } } } } }
// Spin up collector threads public static Boolean ValidateCollectorParameters(List <CollectorParameters> Collectors) { // Loop collector configs for (int i = 0; i < Collectors.Count; i++) { // Assign list instance to variable CollectorParameters Collector = Collectors[i]; // What type of collector are we creating? if (Collector.CollectorType == CollectorType.None) { SilkUtility.WriteCollectorGuidMessageToServiceTextLog(Collector.CollectorGUID, "Invalid CollectorType specified", true); return(false); } else if (Collector.CollectorType == CollectorType.Kernel) { if (Collector.KernelKeywords == KernelKeywords.None) { SilkUtility.WriteCollectorGuidMessageToServiceTextLog(Collector.CollectorGUID, "Invalid KernelKeywords specified", true); return(false); } } else if (Collector.CollectorType == CollectorType.User) { if (String.IsNullOrEmpty(Collector.ProviderName)) { SilkUtility.WriteCollectorGuidMessageToServiceTextLog(Collector.CollectorGUID, "Invalid ProviderName specified", true); return(false); } // Check and convert UserKeywords to ulong if (String.IsNullOrEmpty((String)Collector.UserKeywords)) { SilkUtility.WriteCollectorGuidMessageToServiceTextLog(Collector.CollectorGUID, "Invalid UserKeywords specified", true); return(false); } else { try { if (((String)Collector.UserKeywords).StartsWith("0x")) { Collector.UserKeywords = Convert.ToUInt64((String)Collector.UserKeywords, 16); } else { Collector.UserKeywords = Convert.ToUInt64((String)Collector.UserKeywords); } } catch { SilkUtility.WriteCollectorGuidMessageToServiceTextLog(Collector.CollectorGUID, "Invalid UserKeywords mask specified", true); return(false); } } } // Validate output parameters if (Collector.OutputType == OutputType.None) { SilkUtility.WriteCollectorGuidMessageToServiceTextLog(Collector.CollectorGUID, "Invalid OutputType specified", true); return(false); } else { if (Collector.OutputType == OutputType.file) { if (String.IsNullOrEmpty(Collector.Path)) { SilkUtility.WriteCollectorGuidMessageToServiceTextLog(Collector.CollectorGUID, "Invalid output path specified", true); return(false); } else { try { FileAttributes CheckAttrib = File.GetAttributes(Collector.Path); if (CheckAttrib.HasFlag(FileAttributes.Directory)) { SilkUtility.WriteCollectorGuidMessageToServiceTextLog(Collector.CollectorGUID, "Output path is a directory, not a file", true); return(false); } } catch { } if (!(Directory.Exists(System.IO.Path.GetDirectoryName(Collector.Path)))) { SilkUtility.WriteCollectorGuidMessageToServiceTextLog(Collector.CollectorGUID, "Output path does not exist", true); return(false); } else { if (!(SilkUtility.DirectoryHasPermission(System.IO.Path.GetDirectoryName(Collector.Path), System.Security.AccessControl.FileSystemRights.Write))) { SilkUtility.WriteCollectorGuidMessageToServiceTextLog(Collector.CollectorGUID, "No write access to output path", true); return(false); } } } } else if (Collector.OutputType == OutputType.url) { if (String.IsNullOrEmpty(Collector.Path)) { SilkUtility.WriteCollectorGuidMessageToServiceTextLog(Collector.CollectorGUID, "No URL specified", true); return(false); } else { Uri uriResult; bool UrlResult = Uri.TryCreate(Collector.Path, UriKind.Absolute, out uriResult) && (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps); if (!UrlResult) { SilkUtility.WriteCollectorGuidMessageToServiceTextLog(Collector.CollectorGUID, "Invalid URL specified", true); return(false); } } } else if (Collector.OutputType == OutputType.eventlog) { Collector.Path = "SilkService-Log"; } } // Validate filter options // None, EventName, ProcessID, ProcessName, Opcode if (Collector.FilterOption != FilterOption.None) { if (String.IsNullOrEmpty((String)Collector.FilterValue)) { SilkUtility.WriteCollectorGuidMessageToServiceTextLog(Collector.CollectorGUID, "Invalid FilterValue specified", true); return(false); } if (Collector.FilterOption == FilterOption.ProcessID) { try { Collector.FilterValue = Convert.ToUInt32((String)Collector.FilterValue); } catch { SilkUtility.WriteCollectorGuidMessageToServiceTextLog(Collector.CollectorGUID, "Invalid ProcessID specified", true); return(false); } } if (Collector.FilterOption == FilterOption.Opcode) { try { Collector.FilterValue = byte.Parse((String)Collector.FilterValue); if ((byte)Collector.FilterValue > 9) { SilkUtility.WriteCollectorGuidMessageToServiceTextLog(Collector.CollectorGUID, "Opcode outside valid range (0-9)", true); return(false); } } catch { SilkUtility.WriteCollectorGuidMessageToServiceTextLog(Collector.CollectorGUID, "Invalid Opcode specified", true); return(false); } } else { Collector.FilterValue = (String)Collector.FilterValue; } } // Validate Yara folder path if (Collector.YaraScan != String.Empty) { try { FileAttributes CheckAttrib = File.GetAttributes(Collector.YaraScan); if (!(CheckAttrib.HasFlag(FileAttributes.Directory))) { SilkUtility.WriteCollectorGuidMessageToServiceTextLog(Collector.CollectorGUID, "YaraScan path is not a directory", true); return(false); } else { List <string> YaraRuleCollection = Directory.GetFiles(Collector.YaraScan, "*.yar", SearchOption.AllDirectories).ToList(); if (YaraRuleCollection.Count == 0) { SilkUtility.WriteCollectorGuidMessageToServiceTextLog(Collector.CollectorGUID, "YaraScan directory does not conatin any *.yar files", true); return(false); } else { // We already initialize yara for performace, // new rules can not be added at runtime. Collector.YaraInstance = new YSInstance(); Collector.YaraContext = new YSContext(); Collector.YaraCompiler = Collector.YaraInstance.CompileFromFiles(YaraRuleCollection, null); Collector.YaraRules = Collector.YaraCompiler.GetRules(); YSReport YaraReport = Collector.YaraCompiler.GetErrors(); if (!(YaraReport.IsEmpty())) { SilkUtility.WriteCollectorGuidMessageToServiceTextLog(Collector.CollectorGUID, "The following yara errors were detected", true); Dictionary <string, List <string> > Errors = YaraReport.Dump(); foreach (KeyValuePair <string, List <string> > Error in Errors) { SilkUtility.WriteToServiceTextLog("==> " + Error.Key); foreach (String ErrorMsg in Error.Value) { SilkUtility.WriteToServiceTextLog(" + " + ErrorMsg); } } return(false); } } } } catch { SilkUtility.WriteCollectorGuidMessageToServiceTextLog(Collector.CollectorGUID, "Invalid YaraScan folder path", true); return(false); } if (Collector.YaraOptions == YaraOptions.None) { SilkUtility.WriteCollectorGuidMessageToServiceTextLog(Collector.CollectorGUID, "Invalid YaraOptions specified", true); return(false); } } // Overwrite list entry Collectors[i] = Collector; // We passed all collector parameter checks SilkUtility.WriteCollectorGuidMessageToServiceTextLog(Collector.CollectorGUID, "Parameter validation success", false); } // Validation complete return(true); }
public static void StartTrace(CollectorParameters Collector) { Boolean WriteEventLogEntry(String Message, EventLogEntryType Type, EventIds EventId, String Path) { //--[Event ID's] // 0 == Collector start // 1 == Collector terminated -> by user // 2 == Collector terminated -> by error // 3 == Event recorded //-- try { // Event log properties String Source = "ETW Collector"; // If the source doesn't exist we have to create it first if (!EventLog.SourceExists(Source)) { EventLog.CreateEventSource(Source, Path); } // Write event using (EventLog Log = new EventLog(Path)) { Log.Source = Source; Log.MaximumKilobytes = 99968; // Max ~100mb size -> needs 64kb increments Log.ModifyOverflowPolicy(OverflowAction.OverwriteAsNeeded, 10); // Always overwrite oldest Log.WriteEntry(Message, Type, (int)EventId); } return(true); } catch { return(false); } } int ProcessJSONEventData(String JSONData, OutputType OutputType, String Path, String YaraScan, YaraOptions YaraOptions, YSInstance YaraInstance, YSRules YaraRules) { // Yara matches List <String> YaraRuleMatches = new List <String>(); // Yara options if (YaraScan != String.Empty) { byte[] JSONByteArray = Encoding.ASCII.GetBytes(JSONData); List <YSMatches> Matches = YaraInstance.ScanMemory(JSONByteArray, YaraRules, null, 0); YaraRuleMatches.Clear(); if (Matches.Count != 0) { foreach (YSMatches Match in Matches) { YaraRuleMatches.Add(Match.Rule.Identifier); } // Dynamically update the JSON object -> List<String> YaraRuleMatches JObject obj = JObject.Parse(JSONData); ((JArray)obj["YaraMatch"]).Add(YaraRuleMatches); JSONData = obj.ToString(Newtonsoft.Json.Formatting.None); } } if (YaraOptions == YaraOptions.All || YaraOptions == YaraOptions.None || (YaraScan != String.Empty && 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); } } // Local variables for StartTrace String EventParseSessionName; Boolean ProcessEventData; // Is elevated? While running as a service this should always be true but // this is kept for edge-case user-fail. if (TraceEventSession.IsElevated() != true) { SilkUtility.WriteCollectorGuidMessageToServiceTextLog(Collector.CollectorGUID, "The collector must be run elevated", true); return; } // Print status SilkUtility.WriteCollectorGuidMessageToServiceTextLog(Collector.CollectorGUID, "Starting trace collector", false); // We tag event sessions with a unique name // While running these are observable with => logman -ets if (Collector.CollectorType == CollectorType.Kernel) { EventParseSessionName = KernelTraceEventParser.KernelSessionName; } else { String RandId = Guid.NewGuid().ToString(); EventParseSessionName = ("SilkServiceUserCollector_" + RandId); } // Create trace session using (var TraceSession = new TraceEventSession(EventParseSessionName)) { // The collector cannot survive process termination (safeguard) TraceSession.StopOnDispose = true; // Create event source using (var EventSource = new ETWTraceEventSource(EventParseSessionName, TraceEventSourceType.Session)) { // 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 (Collector.FilterOption != FilterOption.None) { if (Collector.FilterOption == FilterOption.Opcode && (byte)data.Opcode != (byte)Collector.FilterValue) { ProcessEventData = false; } else if (Collector.FilterOption == FilterOption.ProcessID && data.ProcessID != (UInt32)Collector.FilterValue) { ProcessEventData = false; } else if (Collector.FilterOption == FilterOption.ProcessName && data.ProcessName != (String)Collector.FilterValue) { ProcessEventData = false; } else if (Collector.FilterOption == FilterOption.EventName && data.EventName != (String)Collector.FilterValue) { ProcessEventData = false; } else { ProcessEventData = true; } } else { ProcessEventData = true; } // Only process/serialize events if they match our filter if (ProcessEventData) { 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 }; // Populate Proc name if undefined if (String.IsNullOrEmpty(eRecord.ProcessName)) { try { eRecord.ProcessName = Process.GetProcessById(eRecord.ProcessID).ProcessName; } catch { eRecord.ProcessName = "N/A"; } } 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 = ProcessJSONEventData(JSONEventData, Collector.OutputType, Collector.Path, Collector.YaraScan, Collector.YaraOptions, Collector.YaraInstance, Collector.YaraRules); // Verify that we processed the result successfully if (ProcessResult != 0) { if (ProcessResult == 1) { SilkUtility.WriteCollectorGuidMessageToServiceTextLog(Collector.CollectorGUID, "The collector failed to write to file", true); } else if (ProcessResult == 2) { SilkUtility.WriteCollectorGuidMessageToServiceTextLog(Collector.CollectorGUID, "The collector failed to POST the result", true); } else { SilkUtility.WriteCollectorGuidMessageToServiceTextLog(Collector.CollectorGUID, "The collector failed write to the eventlog", true); } // Write status to eventlog if dictated by the output type if (Collector.OutputType == OutputType.eventlog) { WriteEventLogEntry($"{{\"Collector\":\"Stop\",\"Error\":true,\"ErrorCode\":{ProcessResult}}}", EventLogEntryType.Error, EventIds.StopError, Collector.Path); } // This collector encountered an error, terminate the service TerminateCollector(); } } }; // Specify the providers details if (Collector.CollectorType == CollectorType.Kernel) { TraceSession.EnableKernelProvider((KernelTraceEventParser.Keywords)Collector.KernelKeywords); } 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(Collector.ProviderName, (TraceEventLevel)Collector.UserTraceEventLevel, (ulong)Collector.UserKeywords); } // Write status to eventlog if dictated by the output type if (Collector.OutputType == OutputType.eventlog) { String ConvertKeywords; if (Collector.CollectorType == CollectorType.Kernel) { ConvertKeywords = Enum.GetName(typeof(KernelTraceEventParser.Keywords), Collector.KernelKeywords); } else { ConvertKeywords = "0x" + String.Format("{0:X}", (ulong)Collector.UserKeywords); } String Message = $"{{\"Collector\":\"Start\",\"Data\":{{\"Type\":\"{Collector.CollectorType}\",\"Provider\":\"{Collector.ProviderName}\",\"Keywords\":\"{ConvertKeywords}\",\"FilterOption\":\"{Collector.FilterOption}\",\"FilterValue\":\"{Collector.FilterValue}\",\"YaraPath\":\"{Collector.YaraScan}\",\"YaraOption\":\"{Collector.YaraOptions}\"}}}}"; WriteEventLogEntry(Message, EventLogEntryType.SuccessAudit, EventIds.Start, Collector.Path); } // Populate the trace bookkeeper var CollectorInstance = new CollectorInstance { CollectorGUID = Collector.CollectorGUID, EventSource = EventSource, EventParseSessionName = EventParseSessionName, }; SilkUtility.CollectorTaskList.Add(CollectorInstance); // Signal the ManualResetEvent SilkUtility.SignalThreadStarted.Set(); // Continuously process all new events in the data source EventSource.Process(); void TerminateCollector() { EventSource.StopProcessing(); TraceSession?.Stop(); SilkUtility.WriteCollectorGuidMessageToServiceTextLog(Collector.CollectorGUID, "Collector terminated", false); return; } } } }
// Parse SilkService XML config public static List <CollectorParameters> ReadXmlConfig() { // Load config String ConfigPath = AppDomain.CurrentDomain.BaseDirectory + "\\SilkServiceConfig.xml"; XElement XmlConfigFile = null; try { XmlConfigFile = XElement.Load(ConfigPath); } catch { SilkUtility.WriteToServiceTextLog("[!] SilkServiceConfig.xml configuration file invalid or not found"); return(SilkUtility.SilkServiceParameterSets); } // Define XML elements XName CI = XName.Get("ETWCollector"); XName CG = XName.Get("Guid"); XName CT = XName.Get("CollectorType"); XName KK = XName.Get("KernelKeywords"); XName OT = XName.Get("OutputType"); XName P = XName.Get("Path"); XName PN = XName.Get("ProviderName"); XName UTEL = XName.Get("UserTraceEventLevel"); XName UK = XName.Get("UserKeywords"); XName FO = XName.Get("FilterOption"); XName FV = XName.Get("FilterValue"); XName YS = XName.Get("YaraScan"); XName YO = XName.Get("YaraOptions"); // Initialize result struct var CollectorParamInstance = new CollectorParameters(); // Loop ETWCollector elements try { foreach (XElement Collector in XmlConfigFile.Elements(CI)) { XElement ParamContainer; // Loop all possible params try // (1) --> CollectorGUID, ID of the the collector instance for internal tracking { ParamContainer = Collector.Element(CG); Guid EnumContainer; if (Guid.TryParse(ParamContainer.Value, out EnumContainer)) { CollectorParamInstance.CollectorGUID = EnumContainer; } else { CollectorParamInstance.CollectorGUID = Guid.Empty; } } catch { CollectorParamInstance.CollectorGUID = Guid.Empty; } try // (2) --> CollectorType { ParamContainer = Collector.Element(CT); CollectorType EnumContainer; if (Enum.TryParse(ParamContainer.Value, true, out EnumContainer)) { CollectorParamInstance.CollectorType = EnumContainer; } else { CollectorParamInstance.CollectorType = CollectorType.None; } } catch { CollectorParamInstance.CollectorType = CollectorType.None; } try // (3) --> KernelKeywords { ParamContainer = Collector.Element(KK); KernelKeywords EnumContainer; if (Enum.TryParse(ParamContainer.Value, true, out EnumContainer)) { CollectorParamInstance.KernelKeywords = EnumContainer; } else { CollectorParamInstance.KernelKeywords = KernelKeywords.None; } } catch { CollectorParamInstance.KernelKeywords = KernelKeywords.None; } try // (4) --> OutputType { ParamContainer = Collector.Element(OT); OutputType EnumContainer; if (Enum.TryParse(ParamContainer.Value, true, out EnumContainer)) { CollectorParamInstance.OutputType = EnumContainer; } else { CollectorParamInstance.OutputType = OutputType.None; } } catch { CollectorParamInstance.OutputType = OutputType.None; } try // (5) --> Path { ParamContainer = Collector.Element(P); if (!String.IsNullOrEmpty(ParamContainer.Value)) { CollectorParamInstance.Path = ParamContainer.Value; } else { CollectorParamInstance.Path = String.Empty; } } catch { CollectorParamInstance.Path = String.Empty; } try // (6) --> ProviderName { ParamContainer = Collector.Element(PN); if (!String.IsNullOrEmpty(ParamContainer.Value)) { CollectorParamInstance.ProviderName = ParamContainer.Value; } else { CollectorParamInstance.ProviderName = String.Empty; } } catch { CollectorParamInstance.ProviderName = String.Empty; } try // (7) --> UserTraceEventLevel { ParamContainer = Collector.Element(UTEL); UserTraceEventLevel EnumContainer; if (Enum.TryParse(ParamContainer.Value, true, out EnumContainer)) { CollectorParamInstance.UserTraceEventLevel = EnumContainer; } else { CollectorParamInstance.UserTraceEventLevel = UserTraceEventLevel.Informational; } } catch { CollectorParamInstance.UserTraceEventLevel = UserTraceEventLevel.Informational; } try // (8) --> UserKeywords { ParamContainer = Collector.Element(UK); if (!String.IsNullOrEmpty(ParamContainer.Value)) { CollectorParamInstance.UserKeywords = ParamContainer.Value; } else { CollectorParamInstance.UserKeywords = "0xffffffffffffffff"; } } catch { CollectorParamInstance.UserKeywords = "0xffffffffffffffff"; } try // (9) --> FilterOption { ParamContainer = Collector.Element(FO); FilterOption EnumContainer; if (Enum.TryParse(ParamContainer.Value, true, out EnumContainer)) { CollectorParamInstance.FilterOption = EnumContainer; } else { CollectorParamInstance.FilterOption = FilterOption.None; } } catch { CollectorParamInstance.FilterOption = FilterOption.None; } try // (10) --> FilterValue { ParamContainer = Collector.Element(FV); if (!String.IsNullOrEmpty(ParamContainer.Value)) { CollectorParamInstance.FilterValue = ParamContainer.Value; } else { CollectorParamInstance.FilterValue = String.Empty; } } catch { CollectorParamInstance.FilterValue = String.Empty; } try // (11) --> YaraScan { ParamContainer = Collector.Element(YS); if (!String.IsNullOrEmpty(ParamContainer.Value)) { CollectorParamInstance.YaraScan = ParamContainer.Value; } else { CollectorParamInstance.YaraScan = String.Empty; } } catch { CollectorParamInstance.YaraScan = String.Empty; } try // (12) --> YaraOptions { ParamContainer = Collector.Element(YO); YaraOptions EnumContainer; if (Enum.TryParse(ParamContainer.Value, true, out EnumContainer)) { CollectorParamInstance.YaraOptions = EnumContainer; } else { CollectorParamInstance.YaraOptions = YaraOptions.None; } } catch { CollectorParamInstance.YaraOptions = YaraOptions.None; } // Add result to ouput object SilkUtility.SilkServiceParameterSets.Add(CollectorParamInstance); } } catch { SilkUtility.WriteToServiceTextLog("[!] Parsing error encountered while processing SilkService XML configuration file"); } if (SilkUtility.SilkServiceParameterSets.Count == 0) { SilkUtility.WriteToServiceTextLog("[!] SilkService XML configuration file did not contain any ETWCollector elements"); } return(SilkUtility.SilkServiceParameterSets); }