///////////////////////////////////////////////////// // // // 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); }
///////////////////////////////////////////////////// // // // ConnectAgentButton_Click() // // // ///////////////////////////////////////////////////// //Description: Attempts to establish a new TCP/SSL // connection with the remote server (ie, agent) // using the PFX credentials. // //Returns: void ///////////////////////////////////////////////////// private void ConnectAgentButton_Click(object sender, EventArgs e) { //make sure the admin has supplied a PFX keystore file and password if (AC_CRED_PFX_FILENAME == null || AC_CRED_PFX_FILENAME == "" || AC_CRED_PFX_PASSWORD == null || AC_CRED_PFX_PASSWORD == "") { MessageBox.Show("You must supply a PFX/PKCS-12 certificate store file and password for this admin console. This is required to communicate with the deployed agents securely."); return; } //make sure the PFX password is valid if (!CwCryptoHelper.IsValidPFXPassword(AC_CRED_PFX_FILENAME, AC_CRED_PFX_PASSWORD)) { MessageBox.Show("The password supplied for the selected PFX file is invalid."); return; } //------------------------------------------ // CONNECT TO REMOTE AGENT //------------------------------------------ string agentIP = ConnectToAgentIP.Text; int agentPort = int.Parse(ConnectToAgentPort.Text); //instantiate our SSL/TCP client class CurrentClient = new SslTcpClient(); //set TCP client options for connection, encryption, and cert validation rules. CurrentClient.SetOptions(agentIP, agentPort, AC_CRED_IGNORE_REMOTE_CERT_NAME_MISMATCH, AC_CRED_IGNORE_REMOTE_CERT_CHAIN_ERRORS, AC_CRED_PFX_FILENAME, AC_CRED_PFX_PASSWORD); //connect to the agent try { CurrentClient.OpenConnection(); } catch (Exception ex) { string err = ex.Message; if (CurrentClient.sslErrors != SslPolicyErrors.None) err += "\n\nSSL errors: " + CurrentClient.sslErrors.ToString(); MessageBox.Show(err); return; } //go ahead and toggle the buttons to enabled ToggleButtons(true, false); //clear all panes/listviews/etc LogWindow.Clear(); LastCommandPane.Clear(); AgentResults_RegistryListview.Items.Clear(); AgentResults_FileListview.Items.Clear(); AgentResults_MemoryListview.Items.Clear(); //set our own socket's read timeout to something high - a scan can take some time CurrentClient.SetStreamTimeout("read", CwConstants.STREAM_GETSYSTEMINFO_TASK_TIMEOUT); //------------------------------------------ // GET SYSTEM INFORMATION //------------------------------------------ //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_GETSYSTEMINFO); args.Add(new string[] { "" }); args.Add(CwConstants.STREAM_GETSYSTEMINFO_TASK_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); }
///////////////////////////////////////////////////// // // // CwAdminMitigationWindow() // // // ///////////////////////////////////////////////////// //Description: Constructor // //Returns: void ///////////////////////////////////////////////////// internal CwAdminMitigationWindow(CwXML.CodewordAgentSignatureMatches m, SslTcpClient c) { InitializeComponent(); matches = m; CurrentClient = c; }