public AgentScanner() { AgentScanLog = new StringBuilder(); AgentSettings = new Dictionary<string, string>(); AgentHeuristicMatches = new CwXML.CodewordAgentHeuristicMatches(); AgentHeuristicMatches.KernelModeMatches = new CwXML.KernelModeHeuristicMatches(); AgentHeuristicMatches.UserModeMatches = new CwXML.UserModeHeuristicMatches(); AgentSignatureMatches = new CwXML.CodewordAgentSignatureMatches(); AgentSignatureMatches.RegistrySignatureMatches = new CwXML.RegistrySignatureMatch[0]; AgentSignatureMatches.MemorySignatureMatches = new CwXML.MemorySignatureMatch[0]; AgentSignatureMatches.FileSignatureMatches = new CwXML.FileSignatureMatch[0]; }
///////////////////////////////////////////////////// // // // GetMitigateItems() // // // ///////////////////////////////////////////////////// //Description: Crawls the GUI listview controls that // hold the registry, file and memory // signature matches. It builds an XML // structure from these values in preparation // for sending them to the agent for mitigation. // //Returns: void ///////////////////////////////////////////////////// private CwXML.CodewordAgentSignatureMatches GetCollectMitigateItems(ref string outputMessage, string mitigateOrCollectMsg) { int numRegMitigate = 0,numFileMitigate=0,numMemMitigate=0; int count = 0; bool mitigateAll = false; CwXML.CodewordAgentSignatureMatches matches = new CwXML.CodewordAgentSignatureMatches(); outputMessage = ""; //------------------------------------- // CALCULATE COUNTS //------------------------------------- foreach (ListViewItem lvi in AgentResults_RegistryListview.Items) if (lvi.Checked) numRegMitigate++; foreach (ListViewItem lvi in AgentResults_FileListview.Items) if (lvi.Checked) numFileMitigate++; foreach (ListViewItem lvi in AgentResults_MemoryListview.Items) if (lvi.Checked) numMemMitigate++; //if there were no items selected, prompt to mitigate all findings if ((numRegMitigate + numFileMitigate + numMemMitigate) == 0) { if (MessageBox.Show("No findings were selected. Would you like to "+mitigateOrCollectMsg+" all findings?", mitigateOrCollectMsg+" all findings?", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question) != DialogResult.Yes) return null; numRegMitigate = AgentResults_RegistryListview.Items.Count; numFileMitigate = AgentResults_FileListview.Items.Count; numMemMitigate = AgentResults_MemoryListview.Items.Count; mitigateAll = true; } CwXML.RegistrySignatureMatch[] regMatchesToMitigate = new CwXML.RegistrySignatureMatch[numRegMitigate]; CwXML.FileSignatureMatch[] fileMatchesToMitigate = new CwXML.FileSignatureMatch[numFileMitigate]; CwXML.MemorySignatureMatch[] memMatchesToMitigate = new CwXML.MemorySignatureMatch[numMemMitigate]; //------------------------------------- // REGISTRY //------------------------------------- if (numRegMitigate > 0) { outputMessage += "Registry findings (" + numRegMitigate + "):\n"; //build list of registry signature matches to mitigate foreach (ListViewItem lvi in AgentResults_RegistryListview.Items) { if (!lvi.Checked && !mitigateAll) continue; //add to display based on action selected for this finding outputMessage += " " + lvi.SubItems[0].Text + "\\" + lvi.SubItems[1] + " : " + lvi.SubItems[5].Text + "\n"; regMatchesToMitigate[count] = new CwXML.RegistrySignatureMatch(); regMatchesToMitigate[count].RegistryKeyName = lvi.SubItems[0].Text; regMatchesToMitigate[count].RegistryValueName = lvi.SubItems[1].Text; regMatchesToMitigate[count].RegistryValueData = lvi.SubItems[2].Text; regMatchesToMitigate[count].RegistryChangeValueData = lvi.SubItems[3].Text; try { regMatchesToMitigate[count].IsFileOnDisk = bool.Parse(lvi.SubItems[4].Text); } catch (Exception) { regMatchesToMitigate[count].IsFileOnDisk = false; } regMatchesToMitigate[count].Action = lvi.SubItems[5].Text; try { regMatchesToMitigate[count].ActionSuccessful = bool.Parse(lvi.SubItems[6].Text); } catch (Exception) { regMatchesToMitigate[count].ActionSuccessful = false; } count++; } count = 0; } //------------------------------------- // FILE //------------------------------------- if (numFileMitigate > 0) { outputMessage += "File findings (" + numFileMitigate + "):\n"; //build list of registry signature matches to mitigate foreach (ListViewItem lvi in AgentResults_FileListview.Items) { if (!lvi.Checked && !mitigateAll) continue; //add to display based on action selected for this finding if (lvi.SubItems[0].Text != "") //filename outputMessage += " " + lvi.SubItems[1].Text + " : " + lvi.SubItems[8].Text + "\n"; else if (lvi.SubItems[3].Text != "") //hash outputMessage += " [Hash=" + lvi.SubItems[3].Text + "] : " + lvi.SubItems[8].Text + "\n"; else if (lvi.SubItems[2].Text != "") //filesize outputMessage += " [FileSize=" + lvi.SubItems[2].Text + "] : " + lvi.SubItems[8].Text + "\n"; fileMatchesToMitigate[count] = new CwXML.FileSignatureMatch(); fileMatchesToMitigate[count].FileName = lvi.SubItems[0].Text; fileMatchesToMitigate[count].FullPath = lvi.SubItems[1].Text; long.TryParse(lvi.SubItems[2].Text, out fileMatchesToMitigate[count].FileSize); fileMatchesToMitigate[count].FileHash = lvi.SubItems[3].Text; fileMatchesToMitigate[count].FilePEHeaderSignature = lvi.SubItems[4].Text; fileMatchesToMitigate[count].FileCreationDate = lvi.SubItems[5].Text; fileMatchesToMitigate[count].FileLastAccessDate = lvi.SubItems[6].Text; fileMatchesToMitigate[count].FileLastModifiedDate = lvi.SubItems[7].Text; fileMatchesToMitigate[count].Action = lvi.SubItems[8].Text; try { fileMatchesToMitigate[count].ActionSuccessful = bool.Parse(lvi.SubItems[9].Text); } catch (Exception) { fileMatchesToMitigate[count].ActionSuccessful = false; } count++; } count = 0; } //------------------------------------- // MEMORY //------------------------------------- if (numMemMitigate > 0) { outputMessage += "Memory findings (" + numMemMitigate + "):\n"; //build list of registry signature matches to mitigate foreach (ListViewItem lvi in AgentResults_MemoryListview.Items) { if (!lvi.Checked && !mitigateAll) continue; outputMessage += " " + lvi.SubItems[2].Text + " (" + lvi.SubItems[0].Text + ") : " + lvi.SubItems[7].Text; //we cant populate all the fields of the memorysignaturematch structure, //because we didn't populate the GUI listview with all these fields (there are too many) //however, memory mitigation consists of killing the process by name/pid or suspending the thread. //so we dont need all that crap anyway. memMatchesToMitigate[count] = new CwXML.MemorySignatureMatch(); uint.TryParse(lvi.SubItems[0].Text, out memMatchesToMitigate[count].ProcessId); uint.TryParse(lvi.SubItems[1].Text, out memMatchesToMitigate[count].ParentProcessId); memMatchesToMitigate[count].ProcessName = lvi.SubItems[2].Text; memMatchesToMitigate[count].ChildThreadIds = lvi.SubItems[6].Text; memMatchesToMitigate[count].Action = lvi.SubItems[7].Text; try { memMatchesToMitigate[count].ActionSuccessful = bool.Parse(lvi.SubItems[8].Text); } catch (Exception) { memMatchesToMitigate[count].ActionSuccessful = false; } count++; } } matches.RegistrySignatureMatches = regMatchesToMitigate; matches.FileSignatureMatches = fileMatchesToMitigate; matches.MemorySignatureMatches = memMatchesToMitigate; return matches; }
///////////////////////////////////////////////////// // // // StartScanTask() // // // ///////////////////////////////////////////////////// //Description: This function only performs the setup // necessary to perform a scan of registry, // disk and memory, and to report those // results back to the admin console. // //Returns: a stringbuilder object containing log data. ///////////////////////////////////////////////////// internal StringBuilder StartScanTask(ref CwXML.CodewordAgentAnomalyReport anomalyReport) { //clear any existing results anomalyReport = new CwXML.CodewordAgentAnomalyReport(); AgentHeuristicMatches = new CwXML.CodewordAgentHeuristicMatches(); AgentHeuristicMatches.KernelModeMatches = new CwXML.KernelModeHeuristicMatches(); AgentHeuristicMatches.UserModeMatches = new CwXML.UserModeHeuristicMatches(); AgentSignatureMatches = new CwXML.CodewordAgentSignatureMatches(); AgentSignatureMatches.RegistrySignatureMatches = new CwXML.RegistrySignatureMatch[0]; AgentSignatureMatches.MemorySignatureMatches = new CwXML.MemorySignatureMatch[0]; AgentSignatureMatches.FileSignatureMatches = new CwXML.FileSignatureMatch[0]; // //1. Load settings from XML file extracted to local dir from MSI // AgentScanLog.AppendLine("INITIALIZE: Loading scan settings..."); if (!LoadAgentSettings(ref AgentSettings)) return AgentScanLog; // //2. Load signatures - this only needs to be done once here for the whole file // AgentScanLog.AppendLine("SCAN: Loading signatures from XML file..."); if (!LoadAgentSignatures()) return AgentScanLog; // //3. Disable .NET security // EnvironmentHelper.ToggleDotnetSecurity("Off", "INITIALIZE"); // //4. kick off scan // AgentScanLog.AppendLine("SCAN: Scan starting on " + DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss")); DoSignatureScan(); //IMPORTANT: pin the scan results object so the garbage collector doesn't mangle it... //GCHandle gchAgentSignatureMatches = GCHandle.Alloc(AgentSignatureMatches, GCHandleType.Pinned); //only auto-mitigate if option set. if (AgentSettings["Option_AutoMitigate"] == "True") DoMitigate(); DoUserModeHeuristics(); DoKernelModeHeuristics(); AgentScanLog.AppendLine("SCAN: Scan finished on " + DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss")); // //5. re-enable .NET security // EnvironmentHelper.ToggleDotnetSecurity("On", "FINALIZE"); // //6. return our results object byref // //sanitize the XML by escaping invalid characters first int count = 0; foreach (CwXML.RegistrySignatureMatch match in AgentSignatureMatches.RegistrySignatureMatches) { match.RegistryValueData = CwXML.ReplaceInvalidXmlChars(match.RegistryValueData); match.RegistryValueName = CwXML.ReplaceInvalidXmlChars(match.RegistryValueName); AgentSignatureMatches.RegistrySignatureMatches[count] = match; count++; } count = 0; foreach (CwXML.MemorySignatureMatch match in AgentSignatureMatches.MemorySignatureMatches) { //keywords are not required in memory search - could just be looking for presence of a process name if (match.Keywords != null) match.Keywords = CwXML.ReplaceInvalidXmlChars(match.Keywords); match.MatchingBlock = CwXML.ReplaceInvalidXmlChars(match.MatchingBlock); AgentSignatureMatches.MemorySignatureMatches[count] = match; count++; } //assign the fields of the passed-in object byref anomalyReport.SignatureMatches = AgentSignatureMatches; anomalyReport.HeuristicMatches = AgentHeuristicMatches; //release our pinned handle to results //gchAgentSignatureMatches.Free(); return AgentScanLog; }