///////////////////////////////////////////////////// // // // InitiateScanThread() // // // ///////////////////////////////////////////////////// //Description: Kicks of a scan of the host in a separate // thread. ServiceMain() will wait for // this thread to complete. This function // is only called in Enterprise mode. // //Returns: void ////////////////////////////////////////////////////// internal void InitiateScanThread() { AgentScanner scanner = new AgentScanner(); CwXML.CodewordAgentAnomalyReport anomalyReport = new CwXML.CodewordAgentAnomalyReport(); //this wont modify our global variable "ScanResultsLog", so we have to write it to a file //in this child thread and then once back in the main thread, slurp it back up try { ScanResultsLog = scanner.StartScanTask(ref anomalyReport); StreamWriter sw = new StreamWriter("xxzz1tmp1"); sw.Write(ScanResultsLog.ToString()); sw.Close(); } catch (Exception ex) { StreamWriter sw = new StreamWriter("errcw.txt"); sw.WriteLine(ex.Message); if (ex.InnerException != null) { sw.WriteLine(ex.InnerException.Message); } sw.Close(); } return; }
///////////////////////////////////////////////////// // // // InitiateScanThread() // // // ///////////////////////////////////////////////////// //Description: Kicks of a scan of the host in a separate // thread. ServiceMain() will wait for // this thread to complete. This function // is only called in Enterprise mode. // //Returns: void ////////////////////////////////////////////////////// internal void InitiateScanThread() { AgentScanner scanner = new AgentScanner(); CwXML.CodewordAgentAnomalyReport anomalyReport = new CwXML.CodewordAgentAnomalyReport(); //this wont modify our global variable "ScanResultsLog", so we have to write it to a file //in this child thread and then once back in the main thread, slurp it back up try { ScanResultsLog = scanner.StartScanTask(ref anomalyReport); StreamWriter sw = new StreamWriter("xxzz1tmp1"); sw.Write(ScanResultsLog.ToString()); sw.Close(); } catch (Exception ex) { StreamWriter sw = new StreamWriter("errcw.txt"); sw.WriteLine(ex.Message); if (ex.InnerException != null) sw.WriteLine(ex.InnerException.Message); sw.Close(); } return; }
///////////////////////////////////////////////////// // // // ExecuteCommand() // // // ///////////////////////////////////////////////////// //Description: Executes the given command and returns // a response object. // //Returns: A response code, one of the following: // RESPONSE_EXITING - connection closing // RESPONSE_OK - command completed successfully // RESPONSE_FAIL = command failed ///////////////////////////////////////////////////// internal CwXML.CodewordAgentResponse ExecuteCommand(CwXML.CodewordAgentCommand command) { CwXML.CodewordAgentResponse response = new CwXML.CodewordAgentResponse(); response.CommandReceiveDate = DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss"); response.CommandProcessingStartDate = DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss"); response.ResponseCode = CwConstants.AGENTRESPONSE_OK; response.CommandCodeReceived = command.CommandCode; //------------------------------------------------------------- // // GET SYSTEM INFORMATION // //------------------------------------------------------------- #region GET SYSTEM INFORMATION if (command.CommandCode == CwConstants.AGENTCMD_GETSYSTEMINFO) { response.ResponseInfo = "System information retrieved."; CwXML.CodewordSystemInformation sysinfo = new CwXML.CodewordSystemInformation(); sysinfo.HostInformation = new CwXML.HostInformation(); sysinfo.AgentInformation = new CwXML.AgentInformation(); //host info sysinfo.HostInformation.AgentCurrentDirectory = Environment.CurrentDirectory; sysinfo.HostInformation.MachineName = Environment.MachineName; sysinfo.HostInformation.NumProcessors = Environment.ProcessorCount.ToString(); sysinfo.HostInformation.OSVersionShort = Environment.OSVersion.VersionString; sysinfo.HostInformation.LogicalDrives = string.Join(",", Environment.GetLogicalDrives()); sysinfo.HostInformation.IPAddresses = string.Join(",", AgentScanner.EnvironmentHelper.GetIPAddresses()); sysinfo.HostInformation.OSVersionLong = AgentScanner.EnvironmentHelper.GetOSName(); sysinfo.HostInformation.UserDomainName = Environment.UserDomainName; sysinfo.HostInformation.UserName = Environment.UserName; sysinfo.HostInformation.WorkingSetSize = (Environment.WorkingSet / 1000000).ToString() + "MB"; //agent info sysinfo.AgentInformation.Version = Assembly.GetExecutingAssembly().GetName().ToString(); //use XML settings file in current directory - "CwAgentConfiguration.xml" //this will allow us to deserialize the XML data into class structures CwXML xml = new CwXML(); CwXML.CodewordSettingsTemplate cst = new CwXML.CodewordSettingsTemplate(); try { cst = xml.LoadSettingsXML("CwAgentConfiguration.xml"); } catch (Exception e) { response.ResponseInfo = "There was an error retrieving the agent settings: " + e.Message; } sysinfo.AgentInformation.AgentSettings = cst; //use XML signatures file in current directory - "CwAgentSignatures.xml" //this will allow us to deserialize the XML data into class structures xml = new CwXML(); CwXML.CodewordSignatureTemplate sigs = new CwXML.CodewordSignatureTemplate(); try { sigs = xml.ImportSignatureTemplate("CwAgentSignatures.xml"); } catch (Exception e) { response.ResponseInfo = "There was an error retrieving the agent signatures: " + e.Message; } sysinfo.AgentInformation.AgentSignatures = sigs; //assign sysinfo object to return response response.ResponseSystemInformation = sysinfo; } #endregion //------------------------------------------------------------- // // DOWNLOAD EVIDENCE FILES (COLLECT) // //------------------------------------------------------------- #region DOWNLOAD EVIDENCE FILES (COLLECT) else if (command.CommandCode == CwConstants.AGENTCMD_COLLECT) { //=================================================================== // SEND INTERMEDIATE RESPONSE TO TELL HOST TO START RECEIVING FILES //=================================================================== //send a response then prepare to send WriteConnectionLog("CONNECT: Got command to send evidence files..."); CwXML.CodewordAgentResponse response2 = new CwXML.CodewordAgentResponse(); response2.CommandReceiveDate = DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss"); response2.CommandProcessingStartDate = DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss"); response2.ResponseCode = CwConstants.AGENTRESPONSE_OK_RECVFILE; response2.CommandCodeReceived = command.CommandCode; WriteConnectionLog("CONNECT: Sending response..."); //send response try { SendResponse(response2); } catch (Exception ex) { WriteConnectionLog("Failed to send response in preparation for evidence collection: " + ex.Message); response.ResponseCode = CwConstants.AGENTRESPONSE_FAIL; response.ResponseInfo = "Failed to send response in preparation for evidence collection: " + ex.Message; return response; } WriteConnectionLog("CONNECT: Sending files.."); //=================================================================== // SEND EVIDENCE FILES //=================================================================== //get list of files tos end CwXML.FileSignatureMatch[] fileSigsToSend = command.CommandCollectOrMitigationTask.SignatureMatches.FileSignatureMatches; int count = 0; //send the files foreach (CwXML.FileSignatureMatch match in fileSigsToSend) { try { SendBinaryFile(match.FullPath); } catch (Exception ex) { response.ResponseCode = CwConstants.AGENTRESPONSE_FAIL; response.ResponseInfo = "Failed to send binary file '" + match.FullPath + "': " + ex.Message; break; } count++; } if (response.ResponseCode == CwConstants.AGENTRESPONSE_OK) response.ResponseInfo = "Successfully sent " + count + " evidence files."; } #endregion //------------------------------------------------------------- // // PERFORM MITIGATION TASK // //------------------------------------------------------------- #region PERFORM MITIGATION TASK else if (command.CommandCode == CwConstants.AGENTCMD_MITIGATE) { //the mitigation task is stored in the command object as an anomaly report CwXML.CodewordAgentAnomalyReport MitigationTask = command.CommandCollectOrMitigationTask; if (MitigationTask != null) { CwXML.CodewordAgentSignatureMatches matches = MitigationTask.SignatureMatches; //mitigate registry items if (matches.RegistrySignatureMatches != null) { if (matches.RegistrySignatureMatches.Length > 0) { CwXML.RegistrySignatureMatch[] regMatches = matches.RegistrySignatureMatches; AgentScanner.RegistryHelper RegistryScanner = new AgentScanner.RegistryHelper(); RegistryScanner.LoadNtUserDatFiles(false); RegistryScanner.CleanRegistryFindings(ref regMatches, false); RegistryScanner.LoadNtUserDatFiles(true); response.ResponseLog = RegistryScanner.RegistryHelperLog.ToString(); //assign the matches back to our main object, so the ActionSuccessful variable gets sent back matches.RegistrySignatureMatches = regMatches; } } //mitigate file items if (matches.FileSignatureMatches != null) { if (matches.FileSignatureMatches.Length > 0) { CwXML.FileSignatureMatch[] fileMatches = matches.FileSignatureMatches; AgentScanner.FileHelper FileScanner = new AgentScanner.FileHelper(); FileScanner.CleanFileFindings(ref fileMatches); response.ResponseLog = FileScanner.FileHelperLog.ToString(); //assign the matches back to our main object, so the ActionSuccessful variable gets sent back matches.FileSignatureMatches = fileMatches; } } //mitigate memory items if (matches.MemorySignatureMatches != null) { if (matches.MemorySignatureMatches.Length > 0) { CwXML.MemorySignatureMatch[] memMatches = matches.MemorySignatureMatches; AgentScanner.MemoryHelper MemoryScanner = new AgentScanner.MemoryHelper(); MemoryScanner.CleanMemoryFindings(ref memMatches); response.ResponseLog = MemoryScanner.MemoryHelperLog.ToString(); //assign the matches back to our main object, so the ActionSuccessful variable gets sent back matches.MemorySignatureMatches = memMatches; } } //assign the main object to the response's anomaly report response.ResponseAnomalyReport = new CwXML.CodewordAgentAnomalyReport(); response.ResponseAnomalyReport.SignatureMatches = matches; } else { response.ResponseInfo = "Error completing mitigation task: the mitigation object was null!"; response.ResponseCode = CwConstants.AGENTRESPONSE_FAIL; } } #endregion //------------------------------------------------------------- // // START A NEW SCAN // //------------------------------------------------------------- #region START A NEW SCAN else if (command.CommandCode == CwConstants.AGENTCMD_STARTSCAN) { //ENTERPRISE MODE CHECK: //make sure there isnt an already-completed scan from //starting up in enterprise mode. if (EnterpriseModeScanLog != null) { response.ResponseLog = EnterpriseModeScanLog.ToString(); response.ResponseInfo = "These results are from a previous scan issued during agent startup. To run a new scan, please re-issue the scan command."; //clear the enterprise scan results EnterpriseModeScanLog = null; } //otherwise, issue a completely new scan task //warning: this can be a lengthy operation (> 10 min) else { CwXML.CodewordAgentAnomalyReport anomalyReport = new CwXML.CodewordAgentAnomalyReport(); AgentScanner scanner = new AgentScanner(); StringBuilder scannerLog = new StringBuilder(); try { scannerLog = scanner.StartScanTask(ref anomalyReport); } catch (Exception ex) { StreamWriter sw = new StreamWriter("AgentScanLog.txt", false); sw.WriteLine(ex.Message); sw.WriteLine(""); if (AgentScanner.AgentScanLog != null) sw.WriteLine(AgentScanner.AgentScanLog.ToString()); sw.Close(); } if (scannerLog != null && anomalyReport != null) { response.ResponseAnomalyReport = anomalyReport; //invalid xml chars replaced in AgentScanner.StartScanTask() response.ResponseInfo = "Scan complete."; response.ResponseLog = CwXML.ReplaceInvalidXmlChars(scannerLog.ToString()); } else { response.ResponseCode = CwConstants.AGENTRESPONSE_FAIL; response.ResponseInfo = "An unrecoverable error occured during the scan."; } } } #endregion //------------------------------------------------------------- // // EXIT, NO MORE COMMANDS // //------------------------------------------------------------- #region EXIT else if (command.CommandCode == CwConstants.AGENTCMD_EXIT || command.CommandCode == CwConstants.AGENTCMD_NOMORECOMMANDS) { // //NO ACTION REQUIRED // } #endregion //------------------------------------------------------------- // // INVALID COMMAND // //------------------------------------------------------------- #region INVALID COMMAND else if (command.CommandCode == CwConstants.AGENTCMD_UNKNOWN) { response.ResponseCode = CwConstants.AGENTRESPONSE_FAIL; //the error is stored in this member of the fake command we created earlier response.ResponseInfo = string.Join(",", command.CommandParameters); } #endregion //------------------------------------------------------------- // // RECEIVE NEW SIGNATURE UPDATE FILE // //------------------------------------------------------------- #region RECEIVE NEW SIGNATURE UPDATE FILE else if (command.CommandCode == CwConstants.AGENTCMD_UPDATESIG) { //send a response then prepare to receive WriteConnectionLog("CONNECT: Got command to download new signature file..."); CwXML.CodewordAgentResponse response2 = new CwXML.CodewordAgentResponse(); response2.CommandReceiveDate = DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss"); response2.CommandProcessingStartDate = DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss"); response2.ResponseCode = CwConstants.AGENTRESPONSE_OK_SENDFILE; response2.CommandCodeReceived = command.CommandCode; WriteConnectionLog("CONNECT: Sending response..."); //send response try { SendResponse(response2); } catch (Exception ex) { WriteConnectionLog("Failed to send response in preparation for file retrieval: " + ex.Message); response.ResponseCode = CwConstants.AGENTRESPONSE_FAIL; response.ResponseInfo = "Failed to send response in preparation for file retrieval: " + ex.Message; return response; } byte[] filedata; WriteConnectionLog("CONNECT: Waiting for file..."); //receive the file try { filedata = ReceiveFile(); } catch (Exception ex) { WriteConnectionLog("Failed to receive file contents: " + ex.Message); response.ResponseCode = CwConstants.AGENTRESPONSE_FAIL; response.ResponseInfo = "Failed to receive file contents: " + ex.Message; return response; } WriteConnectionLog("CONNECT: File retrieved, saving locally..."); //overwrite our current XML signature file try { if (File.Exists("CwAgentSignatures.xml")) File.Delete("CwAgentSignatures.xml"); AgentScanner.EnvironmentHelper.BinaryWrite("CwAgentSignatures.XML", filedata); } catch (Exception ex) { WriteConnectionLog("Failed to write new signature file: " + ex.Message); response.ResponseCode = CwConstants.AGENTRESPONSE_FAIL; response.ResponseInfo = "Failed to write new signature file: " + ex.Message; return response; } //success! response.ResponseInfo = "Successfully updated signatures file."; } #endregion response.CommandProcessingEndDate = DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss"); return response; }
///////////////////////////////////////////////////// // // // PerformMitigationTasksButton_Click() // // // ///////////////////////////////////////////////////// //Description: Applies mitigation actions to selected // rows of listviews. // //Returns: void ///////////////////////////////////////////////////// private void PerformMitigationTasksButton_Click(object sender, EventArgs e) { //make sure we are connected first if (!CurrentClient.IsConnected()) { MessageBox.Show("Error: Connection to remote agent has been lost."); ToggleButtons(false, false); return; } if (LastAnomalyReport == null) { MessageBox.Show("There are no signature matches to mitigate."); return; } if (LastAnomalyReport.SignatureMatches == null) { MessageBox.Show("There are no signature matches to mitigate."); return; } //set our own socket's read timeout to something high - a scan can take some time CurrentClient.SetStreamTimeout("read", CwConstants.STREAM_MITIGATE_TASK_TIMEOUT); //prepare an anomaly report object for mitigation tasks. CwXML.CodewordAgentAnomalyReport report = new CwXML.CodewordAgentAnomalyReport(); //parse GUI listview items into an XML structure for transport. string outputMsg = ""; CwXML.CodewordAgentSignatureMatches matches = GetCollectMitigateItems(ref outputMsg, "mitigate"); //if none were selected, and the user declined to mitigate all items, just bail. if (matches == null) return; //verify the operation if (MessageBox.Show("The following irreversible mitigation operations are about to be issued:\n\n" + outputMsg + "\n\nAre you SURE?", "Review mitigation tasks", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question) != DialogResult.Yes) return; report.SignatureMatches = matches; report.HeuristicMatches = new CwXML.CodewordAgentHeuristicMatches(); //empty //disable buttons until response is received. //this prevents duplicate or conflicting commands from being issued ToggleButtons(false, true); //do lengthy operation in background worker thread //here we will need to setup any args the lengthy operation will need in the separate thread ArrayList args = new ArrayList(); args.Add(CurrentClient); args.Add(CwConstants.AGENTCMD_MITIGATE); args.Add(new string[]{""}); args.Add(CwConstants.STREAM_MITIGATE_TASK_TIMEOUT); args.Add(true); args.Add(report); //a special 6th argument for mitigation commands. AgentTaskBackgroundWorker = new BackgroundWorker(); AgentTaskBackgroundWorker.WorkerReportsProgress = true; AgentTaskBackgroundWorker.DoWork += new DoWorkEventHandler(BackgroundWorker_DoWork); AgentTaskBackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(BackgroundWorker_RunWorkerCompleted); AgentTaskBackgroundWorker.ProgressChanged += new ProgressChangedEventHandler(BackgroundWorker_ProgressChanged); AgentTaskBackgroundWorker.RunWorkerAsync(args); }
///////////////////////////////////////////////////// // // // BackgroundWorker_DoWork() // // // ///////////////////////////////////////////////////// //Description: This function is called as the entry point // to the background worker thread which handles // lengthy operations on behalf of the main // GUI thread, so that the UI doesn't stall. // // NOTE: Since this function runs in a separate // thread, it does not have access to any global // variables or GUI controls from the main thread. // //Returns: void ///////////////////////////////////////////////////// private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e) { //get arguments ArrayList args = (ArrayList)e.Argument; SslTcpClient client = (SslTcpClient)args[0]; int agentCommand = (int)args[1]; string[] parameters = (string[])args[2]; int timeout = (int)args[3]; bool required = (bool)args[4]; CwXML.CodewordAgentAnomalyReport CollectionOrMitigationTask = new CwXML.CodewordAgentAnomalyReport(); //this 6th argument is ONLY used when we are sending a MITIGATION command if (args.Count == 6) CollectionOrMitigationTask = (CwXML.CodewordAgentAnomalyReport)args[5]; //setup return object //return the agent command issued even if an error occurs ArrayList result = new ArrayList(); result.Add(agentCommand); //send command try { //------------------------------------------------ // AGENT COMMAND PRE-PROCESSING //------------------------------------------------ //*DO NOT* forward this command to the agent. //send the XML update file the agent is waiting on. if (agentCommand == CwConstants.AGENTCMD_SENDUPDATEFILE) { client.SendFile(UpdateFilename); } //*DO NOT* forward this command to the agent. //receive the evidence files the agent is waiting to send us. else if (agentCommand == CwConstants.AGENTCMD_RECVEVIDENCEFILES) { //get the file names and file sizes to download - this will be used in ReceiveFiles() CwXML.FileSignatureMatch[] fileSigsToDownload = CollectionOrMitigationTask.SignatureMatches.FileSignatureMatches; client.ReceiveFiles(SaveCollectionEvidenceToFolder,fileSigsToDownload); } //*DO* forward this command to the agent for direct processing. else { client.SendCommand(agentCommand, parameters, timeout, required, CollectionOrMitigationTask); } } catch (Exception ex) { /* result.Add(CwConstants.ADMINCONSOLE_ERROR_CMDFAILED); result.Add(ex.Message); e.Result = result; return; * */ } AgentTaskBackgroundWorker.ReportProgress(50); //receive response CwXML.CodewordAgentResponse response = null; try { response = client.ReadResponse(); } catch (Exception ex) { /* result.Add(CwConstants.ADMINCONSOLE_ERROR_RESPONSEFAILED); result.Add(ex.Message); e.Result = result; return; * */ } AgentTaskBackgroundWorker.ReportProgress(100); //add the response object to the return result.Add(response); e.Result = result; return; }
///////////////////////////////////////////////////// // // // BackgroundWorker_RunWorkerCompleted() // // // ///////////////////////////////////////////////////// //Description: This function is called when the background // worker thread signals that it is finished. // It runs in the context of the main thread, // so it is safe to modify GUI or reference // main thread global variables here. // //Returns: void ///////////////////////////////////////////////////// private void BackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { ArrayList result = (ArrayList)e.Result; int commandSent = (int)result[0]; //cast the response object from the thread's result object CwXML.CodewordAgentResponse response = (CwXML.CodewordAgentResponse)result[1]; //if there are 3 objects in this arraylist, we KNOW the command failed. //if (result.Count == 3) if (response == null) { /* int errorCode = (int)result[1]; string errMsg = (string)result[2]; if (errorCode == CwConstants.ADMINCONSOLE_ERROR_CMDFAILED) MessageBox.Show("Failed to send command " + commandSent.ToString() + ": " + errMsg); else MessageBox.Show("Failed to receive response: " + errMsg); */ MessageBox.Show("No response was sent from the client."); if (!CurrentClient.IsConnected()) ToggleButtons(false, false); AgentTaskProgressBarLabel.Text = "Task complete."; AgentTaskProgressBar.Value = 0; AgentTaskProgressBar.Refresh(); AgentTaskProgressBarLabel.Refresh(); //always re-enable all buttons if the command failed ToggleButtons(true, false); return; } //------------------------------------------------------------- // // GET SYSTEM INFORMATION // //------------------------------------------------------------- #region GET SYSTEM INFORMATION if (commandSent == CwConstants.AGENTCMD_GETSYSTEMINFO) { //extract the agent results object if (response.ResponseSystemInformation != null) { //save in our global variable LatestSystemInformation = response.ResponseSystemInformation; //force GUI update UpdateSystemInformationListview(); } CopyResponseToLogWindow(response); //add to recently viewed agents string agentIP = ConnectToAgentIP.Text; int agentPort = int.Parse(ConnectToAgentPort.Text); bool addToList = true; foreach (TreeNode node in RecentAgentsTreeview.Nodes) if (node.Text == agentIP) addToList = false; if (addToList) RecentAgentsTreeview.Nodes.Add(agentIP); } #endregion //------------------------------------------------------------- // // START A NEW SCAN // //------------------------------------------------------------- #region START A NEW SCAN else if (commandSent == CwConstants.AGENTCMD_STARTSCAN) { //extract the agent results object if (response.ResponseAnomalyReport != null) { //save in our global variable LastAnomalyReport = response.ResponseAnomalyReport; //force GUI update UpdateResultsListviews(); } } #endregion //------------------------------------------------------------- // // SEND NEW SIGNATURE FILE // //------------------------------------------------------------- #region SEND NEW SIGNATURE FILE else if (commandSent == CwConstants.AGENTCMD_UPDATESIG) { //CASE 1: we are arriving from the first thread completing, in which case we need //to send the actual update file if (response.ResponseCode == CwConstants.AGENTRESPONSE_OK_SENDFILE) { //we have to do something tricky here, so that our DoWork() function //doesnt send the internal command AGENTCMD_SENDUPDATEFILE to the remote agent. //create a second thread to actually send the update file. //we previously created a thread to send the command to notify the agent we are //about to send a file. we are at the point right now where the response from //the agent has been received, and it is awaiting the actual file. so send it. ArrayList args = new ArrayList(); args.Add(CurrentClient); args.Add(CwConstants.AGENTCMD_SENDUPDATEFILE); args.Add(new string[] { "" }); args.Add(CwConstants.STREAM_UPDATE_SIGNATURES_TIMEOUT); args.Add(true); AgentTaskBackgroundWorker = new BackgroundWorker(); AgentTaskBackgroundWorker.WorkerReportsProgress = true; AgentTaskBackgroundWorker.DoWork += new DoWorkEventHandler(BackgroundWorker_DoWork); AgentTaskBackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(BackgroundWorker_RunWorkerCompleted); AgentTaskBackgroundWorker.ProgressChanged += new ProgressChangedEventHandler(BackgroundWorker_ProgressChanged); AgentTaskBackgroundWorker.RunWorkerAsync(args); } //CASE 2: we are arriving from the second thread completing, in which case //we are done; the update file was sent and received successfully. else { //..and we dont need to do anything! } } #endregion //------------------------------------------------------------- // // MITIGATE ITEMS // //------------------------------------------------------------- #region MITIGATE ITEMS else if (commandSent == CwConstants.AGENTCMD_MITIGATE) { if (LastAnomalyReport == null) LastAnomalyReport = new CwXML.CodewordAgentAnomalyReport(); if (response.ResponseAnomalyReport != null) { //update our signatures listview with the copy we got back. //the copy sent back to us contains ONLY THE FINDINGS THAT WERE MITIGATED. //since the user has the option of selecting only a few for mitigation, we must //search through all of the results in the GUI and update the ones that were changed. FindAndUpdateMatchRecords(response.ResponseAnomalyReport.SignatureMatches); //now repopulate the listviews with the udpated match records. UpdateResultsListviews(); } } #endregion //------------------------------------------------------------- // // COLLECT EVIDENCE ITEMS // //------------------------------------------------------------- #region COLLECT EVIDENCE ITEMS else if (commandSent == CwConstants.AGENTCMD_COLLECT) { //CASE 1: we are arriving from the first thread completing, in which case we need //to prepare to receive the evidence files - send an internal msg to ourselves if (response.ResponseCode == CwConstants.AGENTRESPONSE_OK_RECVFILE) { //we have to do something tricky here, so that our DoWork() function //doesnt send the internal command AGENTCMD_RECVEVIDENCEFILE to the remote agent. //create a second thread to actually receive the evidence file. //we previously created a thread to send the command to notify the agent we want it //to find and send us a file. we are at the point right now where the response from //the agent has been received, and it is waiting to send us the file. so grab it! ArrayList args = new ArrayList(); args.Add(CurrentClient); args.Add(CwConstants.AGENTCMD_RECVEVIDENCEFILES); args.Add(new string[] { "" }); args.Add(CwConstants.STREAM_COLLECT_TASK_TIMEOUT); args.Add(true); args.Add(LastCollectionTask); AgentTaskBackgroundWorker = new BackgroundWorker(); AgentTaskBackgroundWorker.WorkerReportsProgress = true; AgentTaskBackgroundWorker.DoWork += new DoWorkEventHandler(BackgroundWorker_DoWork); AgentTaskBackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(BackgroundWorker_RunWorkerCompleted); AgentTaskBackgroundWorker.ProgressChanged += new ProgressChangedEventHandler(BackgroundWorker_ProgressChanged); AgentTaskBackgroundWorker.RunWorkerAsync(args); } //CASE 2: we are arriving from the second thread completing, in which case //we are done downloading. else { //nothing to do.. } } #endregion //------------------------------------------------------------- // // DISCONNECT // //------------------------------------------------------------- #region DISCONNECT else if (commandSent == CwConstants.AGENTCMD_NOMORECOMMANDS) { //make sure the remote end didnt terminate first if (CurrentClient.IsConnected()) CurrentClient.CloseConnection(); CurrentClient = null; } #endregion CopyResponseToLogWindow(response); AgentTaskProgressBarLabel.Text = "Task complete."; AgentTaskProgressBar.Value = 0; AgentTaskProgressBar.Refresh(); AgentTaskProgressBarLabel.Refresh(); //always re-enable toolbar buttons unless this was a disconnect or halt command if (commandSent == CwConstants.AGENTCMD_EXIT || commandSent == CwConstants.AGENTCMD_NOMORECOMMANDS) ToggleButtons(false, false); else ToggleButtons(true, false); }
///////////////////////////////////////////////////// // // // 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; }