Beispiel #1
0
        /////////////////////////////////////////////////////
        //                                                 //
        // 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;
        }
Beispiel #2
0
        /////////////////////////////////////////////////////
        //                                                 //
        // ReadResponse()                                  //
        //                                                 //
        /////////////////////////////////////////////////////
        //Description:  Attempt to read an incoming SSL msg.
        //
        //Throws:       Deserialization error
        //
        //Returns:      the response object
        /////////////////////////////////////////////////////
        internal CwXML.CodewordAgentResponse ReadResponse()
        {
            CwXML.CodewordAgentResponse r = new CwXML.CodewordAgentResponse();
            MemoryStream ms = new MemoryStream();
            Decoder UTF8Decoder = Encoding.UTF8.GetDecoder();
            int bytes = -1;
            byte[] buffer = new byte[2048];

            do
            {
                //read 2048 bytes from the network stream - store in our byte buffer
                //.Read() advances the stream's buffer, so dont worry about an offset.
                try
                {
                    bytes = ClientSslStream.Read(buffer, 0, 2048);
                }
                catch (IOException ex)
                {
                    throw new Exception("ReadResponse():  Caught IO Exception (read " + bytes.ToString() + " bytes):  " + ex.Message);
                }
                catch (Exception ex)
                {
                    throw new Exception("ReadResponse():  Caught other exception (read " + bytes.ToString() + " bytes):  " + ex.Message);
                }

                //decode the data to look for EOF
                StringBuilder messageData = new StringBuilder();
                char[] chars = new char[UTF8Decoder.GetCharCount(buffer, 0, bytes)];
                UTF8Decoder.GetChars(buffer, 0, bytes, chars, 0);
                messageData.Append(chars);

                //write the bytes from the byte buffer to our memory stream
                ms.Write(buffer, 0, bytes);

                //break if EOF.
                if (messageData.ToString().IndexOf("<EOF>") != -1)
                    break;
            }
            while (bytes != 0);

            //convert the memorystream to a string to replace the <EOF>
            //otherwise, xml parsing will fail.
            byte[] bData = ms.ToArray();
            char[] charArray = new char[UTF8Decoder.GetCharCount(bData, 0, bData.Length)];
            UTF8Decoder.GetChars(bData, 0, bData.Length, charArray, 0);
            string s = new string(charArray);
            s=s.Replace("<EOF>", "");
            ms = new MemoryStream(Encoding.UTF8.GetBytes(s));

            //try to deserialize the response data from the memory stream we filled
            XmlSerializer serializer = new XmlSerializer(typeof(CwXML.CodewordAgentResponse));

            //restore the object's state with data from the XML document
            r = (CwXML.CodewordAgentResponse)serializer.Deserialize(ms);

            //DEBUG
            /*
            StreamWriter sw = new StreamWriter("ResponseRead.xml");
            sw.Write(new string(Encoding.UTF8.GetChars(ms.ToArray())));
            sw.Close();
            */

            if (r == null)
                throw new Exception("Response was retrieved, but the object was null.");

            return r;
        }