예제 #1
0
        /////////////////////////////////////////////////////
        //                                                 //
        // LoadAgentSettings()                             //
        //                                                 //
        /////////////////////////////////////////////////////
        //Description:  Loads settings from the agent config file.
        //
        //Returns:      true if successful
        //////////////////////////////////////////////////////
        private static unsafe bool LoadAgentSettings(ref Dictionary <string, string> AgentSettings)
        {
            //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)
            {
                return(false);
            }

            //copy the settings from the CST object to a more usable dictionary<> struct
            int count = 0;

            foreach (string s in cst.FormElementNames)
            {
                AgentSettings[s] = cst.FormElementValues[count];
                count++;
            }

            return(true);
        }
예제 #2
0
        /////////////////////////////////////////////////////
        //                                                 //
        // LoadAgentSettings()                             //
        //                                                 //
        /////////////////////////////////////////////////////
        //Description:  Loads settings from the agent config file.
        //
        //Returns:      true if successful
        //////////////////////////////////////////////////////
        private unsafe bool LoadAgentSettings(ref Dictionary <string, string> AgentSettings)
        {
            //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)
            {
                AgentServiceLog.AppendLine("ERROR:  " + e.Message);
                AgentServiceLog.AppendLine("ERROR:  Failed to load settings, terminating...");
                return(false);
            }

            //copy the settings from the CST object to a more usable dictionary<> struct
            int count = 0;

            foreach (string s in cst.FormElementNames)
            {
                AgentSettings[s] = cst.FormElementValues[count];
                count++;
            }

            AgentServiceLog.AppendLine("INITIALIZE:  Success.");
            return(true);
        }
예제 #3
0
            /////////////////////////////////////////////////////
            //                                                 //
            // ExpandRegistryKey()                             //
            //                                                 //
            /////////////////////////////////////////////////////
            //Description:  Takes a registry key string and replaces
            //              {<var>} with expanded value
            //Returns:      an array of expanded registry key strings or
            //              null if invalid value passed in
            /////////////////////////////////////////////////////
            internal string[] ExpandRegistryKey(string key, CwXML.RegistryGuidSignature[] GuidSignatures)
            {
                int varBegin = key.IndexOf("{<");
                int varEnd = key.IndexOf(">}");

                //there's no opening tag
                if (varBegin < 0)
                {
                    //and no closing tag, so no prob
                    if (varEnd < 0)
                        return new string[] { key };
                    //er..there was a closing tag but no opening tag..
                    else
                        return null;  //remove malformed indicator entry
                }
                //there's an opening tag but no closing tag
                if (varEnd < 0)
                    return null;  //remove malformed indicator entry

                string var = key.Substring(varBegin + 2, varEnd - (varBegin + 2));

                RegistryHelperLog.AppendLine("SCAN:  Expanding registry key '" + key + "'...");

                //EXPAND GUID
                if (var == "GUID")
                {
                    int count = 0;

                    //if there are no static GUIDs to replace {<GUID>} with, return
                    if (GuidSignatures.Length == 0)
                    {
                        RegistryHelperLog.AppendLine("SCAN:  No GUIDs were supplied, skipping this indicator check..");
                        return null;
                    }

                    string[] expandedKeys = new string[GuidSignatures.Length];
                    string tmpKey = key;

                    //loop through static GUIDs we have and insert into given registry key string
                    foreach (CwXML.RegistryGuidSignature sig in GuidSignatures)
                    {
                        //only consider static GUIDs
                        if (sig.GuidType == "Dynamic")
                            continue;

                        //replace {<GUID>} with this GUID
                        tmpKey = key.Replace("<GUID>", sig.GuidValue);

                        RegistryHelperLog.AppendLine("SCAN:  Created expanded registry indicator '" + tmpKey + "'.");
                        expandedKeys[count] = tmpKey;
                        count++;
                    }

                    return expandedKeys;
                }
                //EXPAND SID
                else if (var == "SID")
                {
                    RegistryHelperLog.AppendLine("SCAN:  Expanding SIDs...");

                    //we need to get a list of user account SIDs using WMI,
                    //loop through that list, and generate new registry
                    //indicator checks for each account SID
                    SelectQuery sQuery = new SelectQuery("Win32_UserAccount", "Domain='" + Environment.UserDomainName + "'");
                    ManagementObjectSearcher mSearcher = new ManagementObjectSearcher(sQuery);

                    //start inserting new indicators at the end of the list
                    int count = 0;
                    string[] expandedKeys = new string[mSearcher.Get().Count];

                    //loop through all user accounts and create new indicator
                    foreach (ManagementObject mObject in mSearcher.Get())
                    {
                        string SID = mObject["SID"].ToString();
                        string UserName = mObject["Name"].ToString();
                        string thisExpandedKey = key;

                        //replace var in this expanded key with current SID
                        thisExpandedKey = thisExpandedKey.Replace("{<SID>}", SID);

                        RegistryHelperLog.AppendLine("SCAN:  Created expanded registry indicator  '" + thisExpandedKey + "'...");
                        expandedKeys[count] = thisExpandedKey;
                        count++;
                    }

                    RegistryHelperLog.AppendLine("SCAN:  Successfully created " + count + " new registry indicators.");

                    return expandedKeys;
                }
                else
                {
                    RegistryHelperLog.AppendLine("ERROR:  Invalid embedded variable '" + var + "' in key '" + key + "', skipping this registry indicator.");
                    return null;
                }
            }
예제 #4
0
        /////////////////////////////////////////////////////
        //                                                 //
        // SendResponse()                                  //
        //                                                 //
        /////////////////////////////////////////////////////
        //Description:  Attempts to send a message over SSL.
        //
        //Throws:       Serialization error
        //
        //Returns:      true if successful
        /////////////////////////////////////////////////////
        internal bool SendResponse(CwXML.CodewordAgentResponse response)
        {
            //create an XML serialization object to prepare the command
            XmlSerializer serializer = new XmlSerializer(typeof(CwXML.CodewordAgentResponse));

            //create a memory stream to which we will serialize our response object
            MemoryStream memStream = new MemoryStream();

            //store the object's state in XML format into the memory stream store
            serializer.Serialize(memStream, response);

            //tack on "<EOF>" to the message, so the server knows when to stop reading the socket
            char[] eofbuf = new char[] { '<', 'E', 'O', 'F', '>' };
            memStream.Write(Encoding.UTF8.GetBytes(eofbuf), 0, eofbuf.Length);

            //try to send the raw bytes in the memory stream to the remote socket
            try
            {
                //result of 5 hour debug session:  dont use memstream.getBuffer()
                //it returns all bytes in the buffer, not only the ones used..use ToArray() instead!!
                CurrentSslStream.Write(memStream.ToArray());
                CurrentSslStream.Flush();
            }
            catch (Exception ex)
            {
                throw new Exception("sslStream.Write() exception:  " + ex.Message);
            }

            //DEBUG
            /*
            StreamWriter sw = new StreamWriter("ResponseSent.xml");
            sw.Write(new string(Encoding.UTF8.GetChars(memStream.ToArray())));
            sw.Close();
            */
            try
            {
                memStream.Close();
            }
            catch (Exception) { }

            return true;
        }
예제 #5
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;
        }
예제 #6
0
        /////////////////////////////////////////////////////
        //                                                 //
        // ReceiveFiles()                                  //
        //                                                 //
        /////////////////////////////////////////////////////
        //Description:  Receives as many files as the agent sends.
        //              Saves them to the specified folder.
        //
        //Throws:       read error
        //
        //Returns:      the binary data
        /////////////////////////////////////////////////////
        internal bool ReceiveFiles(string SaveToFolder, CwXML.FileSignatureMatch[] collectionTargets)
        {
            MemoryStream ms = new MemoryStream();
            Decoder UTF8Decoder = Encoding.UTF8.GetDecoder();
            int numBytesRead = -1;
            byte[] fileDataBuffer;

            //loop through all files in the collection target and download them
            foreach(CwXML.FileSignatureMatch fileMatch in collectionTargets)
            {
                string fileNameToCollect = fileMatch.FileName;
                string filePathToCollect = fileMatch.FullPath;
                long fileSizeToCollect = fileMatch.FileSize;
                string fileHashToCollect = fileMatch.FileHash;
                string fileHashTypeToCollect = fileMatch.FileHashType;

                //create a new buffer to store this file - size is the file's size
                fileDataBuffer = new byte[fileSizeToCollect];

                //====================================
                //DOWNLOAD FILE BYTES
                //====================================
                try
                {
                    //store a max of 2048 bytes starting at offset 0 in the buffer array
                    numBytesRead = ClientSslStream.Read(fileDataBuffer, 0, (int)fileSizeToCollect);
                }
                catch (IOException ex)
                {
                    throw new Exception("ReceiveFiles():  Caught IO Exception (read " + numBytesRead.ToString() + " bytes):  " + ex.Message);
                }
                catch (Exception ex)
                {
                    throw new Exception("ReceiveFiles():  Caught other exception (read " + numBytesRead.ToString() + " bytes):  " + ex.Message);
                }

                //throw an error if the file was corrupted
                if (numBytesRead != fileSizeToCollect)
                    throw new Exception("ReceiveFiles():  The downloaded file size (" + numBytesRead.ToString() + ") does not match the expected file size (" + fileSizeToCollect.ToString() + ")!");

                //do a binary write to save this file to the target folder
                string outputFullPath = SaveToFolder + "\\" + fileNameToCollect;
                StreamWriter sw = new StreamWriter(outputFullPath);
                BinaryWriter bw = new BinaryWriter(sw.BaseStream);
                bw.Write(fileDataBuffer);
                bw.Flush();
                bw.Close();

                //MATCH MD-5 HASH IF SPECIFIED
                if (fileHashTypeToCollect == "MD5" && fileHashToCollect != "")
                {
                    string thisMD5=GetMD5HashOfFile(outputFullPath);
                    if (thisMD5 != fileHashToCollect)
                        throw new Exception("ReceiveFiles():  The MD5 hash of the download evidence file (" + thisMD5.ToString() + ") does not match the expected MD5 hash (" + fileHashToCollect.ToString() + ")!");
                }
                //MATCH SHA-1 HASH IF SPECIFIED
                else if (fileHashTypeToCollect == "SHA1" && fileHashToCollect != "")
                {
                    string thisSHA1 = GetSHA1HashOfFile(outputFullPath);

                    if (thisSHA1 != fileHashToCollect)
                        throw new Exception("ReceiveFiles():  The SHA1 hash of the download evidence file (" + thisSHA1.ToString() + ") does not match the expected SHA1 hash (" + fileHashToCollect.ToString() + ")!");
                }
            }

            return true;
        }
예제 #7
0
        /////////////////////////////////////////////////////
        //                                                 //
        // FindAndUpdateMatchRecord()                      //
        //                                                 //
        /////////////////////////////////////////////////////
        //Description:  Updates the signature findings listviews
        //              with the result of a mitigation operation
        //
        //Returns:      void
        /////////////////////////////////////////////////////
        private void FindAndUpdateMatchRecords(CwXML.CodewordAgentSignatureMatches updatedMatchRecords)
        {
            //--------------------------------------
            //                REGISTRY
            //--------------------------------------
            if (updatedMatchRecords.RegistrySignatureMatches != null)
            {
                CwXML.RegistrySignatureMatch[] regMatches = updatedMatchRecords.RegistrySignatureMatches;

                //loop through all registry signature matches that were mitigated, trying to find a
                //corresponding signature match in our old global var.
                foreach (CwXML.RegistrySignatureMatch rNew in regMatches)
                {
                    int matchIndex = 0;
                    //loop through all the signature matches currently stored in our global var.
                    foreach (CwXML.RegistrySignatureMatch rOld in LastAnomalyReport.SignatureMatches.RegistrySignatureMatches)
                    {
                        if (rOld.RegistryKeyName == rNew.RegistryKeyName &&
                            rOld.RegistryValueName == rNew.RegistryValueName &&
                            rOld.Action == rNew.Action)
                        {
                            LastAnomalyReport.SignatureMatches.RegistrySignatureMatches[matchIndex].ActionSuccessful = rNew.ActionSuccessful;
                            break;
                        }
                        matchIndex++;
                    }
                }
            }
            //--------------------------------------
            //                FILE
            //--------------------------------------
            if (updatedMatchRecords.FileSignatureMatches != null)
            {
                CwXML.FileSignatureMatch[] fileMatches = updatedMatchRecords.FileSignatureMatches;

                //loop through all file signature matches that were mitigated, trying to find a
                //corresponding signature match in our old global var.
                foreach (CwXML.FileSignatureMatch fNew in fileMatches)
                {
                    int matchIndex = 0;
                    //loop through all the signature matches currently stored in our global var.
                    foreach (CwXML.FileSignatureMatch fOld in LastAnomalyReport.SignatureMatches.FileSignatureMatches)
                    {
                        if (fOld.FullPath == fNew.FullPath &&
                            fOld.FileSize == fNew.FileSize &&
                            fOld.FileHash == fNew.FileHash &&
                            fOld.Action == fNew.Action)
                        {
                            LastAnomalyReport.SignatureMatches.FileSignatureMatches[matchIndex].ActionSuccessful = fNew.ActionSuccessful;
                            break;
                        }
                        matchIndex++;
                    }
                }
            }
            //--------------------------------------
            //                MEMORY
            //--------------------------------------
            if (updatedMatchRecords.MemorySignatureMatches != null)
            {
                CwXML.MemorySignatureMatch[] memMatches = updatedMatchRecords.MemorySignatureMatches;

                //loop through all memory signature matches that were mitigated, trying to find a
                //corresponding signature match in our old global var.
                foreach (CwXML.MemorySignatureMatch mNew in memMatches)
                {
                    int matchIndex = 0;
                    //loop through all the signature matches currently stored in our global var.
                    foreach (CwXML.MemorySignatureMatch mOld in LastAnomalyReport.SignatureMatches.MemorySignatureMatches)
                    {
                        if (mOld.ProcessId == mNew.ProcessId &&
                            mOld.ProcessName == mNew.ProcessName)
                        {
                            LastAnomalyReport.SignatureMatches.MemorySignatureMatches[matchIndex].ActionSuccessful = mNew.ActionSuccessful;
                            break;
                        }
                        matchIndex++;
                    }
                }
            }
        }
예제 #8
0
            /////////////////////////////////////////////////////
            //                                                 //
            // ScanForRegistrySignatures()                     //
            //                                                 //
            /////////////////////////////////////////////////////
            //Description:  Scans the registry for the given
            //              signatures, storing any findings in
            //              the passed-in matches structure.
            //Returns:      none
            /////////////////////////////////////////////////////
            internal void ScanForRegistrySignatures(CwXML.RegistrySignature[] signatures, CwXML.RegistryGuidSignature[] guidSignatures, ref CwXML.RegistrySignatureMatch[] matches)
            {
                string keyName, valueName, valueData, action, hive, keyWithoutHive;
                int firstSlashInKeyName = 0;
                RegistryKey key;
                Regex filePathValidator = new Regex(@"^(([a-zA-Z]\:)|(\\))(\\{1}|((\\{1})[^\\]([^/:*?<>""|]*))+)$");
                string[] expandedKeys;
                ArrayList matchList = new ArrayList();

                //loop through all registry indicators - admin and user
                foreach (CwXML.RegistrySignature signature in signatures)
                {
                    //extract values from object
                    keyName = signature.KeyName;
                    valueName = signature.ValueName;
                    valueData = signature.ValueData;
                    action = signature.Action;

                    firstSlashInKeyName = keyName.IndexOf('\\');
                    hive = keyName.Substring(0, firstSlashInKeyName);
                    keyWithoutHive = keyName.Substring(firstSlashInKeyName, keyName.Length - firstSlashInKeyName);

                    if (hive == "HKLM")
                        key = Registry.LocalMachine;
                    else if (hive == "HKCR")
                        key = Registry.ClassesRoot;
                    else if (hive == "HKU")
                        key = Registry.Users;
                    else if (hive == "HKCC")
                        key = Registry.CurrentConfig;
                    else
                    {
                        RegistryHelperLog.AppendLine("WARNING:  Invalid hive detected in registry indicator:");
                        RegistryHelperLog.AppendLine("          Key:  '" + keyName + "'");
                        RegistryHelperLog.AppendLine("          Parsed hive:  '" + hive + "'");
                        RegistryHelperLog.AppendLine("WARNING:  Skipping this indicator...");
                        continue; //skip if bad hive
                    }

                    RegistryHelperLog.AppendLine("SCAN:  Using hive '" + hive + "'.");

                    //expand any {<var>} expandable values in registry key string
                    expandedKeys = ExpandRegistryKey(keyWithoutHive, guidSignatures);

                    //only returns null if there was a malformed var, so skip that check
                    if (expandedKeys == null)
                        continue;

                    //loop through the record/checks we built, or didn't build - if there was no var
                    //to expand, we just got the same record back.
                    foreach (string expandedKey in expandedKeys)
                    {
                        if (expandedKey == null)
                            continue;

                        //remove leading and trailing slashes
                        keyName = expandedKey.Trim(new char[] { ' ', '\\' });

                        RegistryHelperLog.AppendLine("SCAN:  Scanning for signature '" + hive + "\\" + keyName + "\\" + valueName + "'...");
                        RegistryKey parentKey = key.OpenSubKey(keyName, true);

                        //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                        //                SIGNATURE HIT
                        //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                        //if the key exists, we have a match.
                        if (parentKey != null)
                        {
                            try
                            {
                                ArrayList valnames = new ArrayList();

                                //build an arraylist of value names to look for
                                //if the valueName supplied in the signature is empty, we will copy
                                //all valueName's in this registry key.
                                if (valueName == "" || valueName == null)
                                {
                                    foreach (string valname in parentKey.GetValueNames())
                                        valnames.Add(valname);
                                    //if there are no value names, add the (Default) one, represented by "" in .net
                                    if (valnames.Count == 0)
                                        valnames.Add("");
                                }
                                else
                                {
                                    //otherwise we just want a single value name underneath this key
                                    valnames.Add(valueName);
                                }

                                //loop thru all value names to look for and add a new match record
                                foreach (string v in valnames)
                                {
                                    //get the value name
                                    object obj = parentKey.GetValue(v);

                                    //parse the value data - binary, expand string, etc...
                                    if (obj != null)
                                    {
                                        string displayData = "";
                                        string valdata = "";

                                        RegistryHelperLog.AppendLine("SCAN:  Signature matched on host!");

                                        //create a new RegistrySignatureMatch object
                                        CwXML.RegistrySignatureMatch matchRecord = new CwXML.RegistrySignatureMatch();
                                        matchRecord.RegistryKeyName = hive+"\\"+keyName; //the expanded registry key name plus hive
                                        matchRecord.RegistryValueName = v;
                                        matchRecord.Action = action;

                                        //get the value data of this value name based on type
                                        if (parentKey.GetValueKind(v) == RegistryValueKind.Binary)
                                        {
                                            StringBuilder str = GetEncodingsFromBinaryRegData((byte[])parentKey.GetValue(v));
                                            valdata = str.ToString();
                                            displayData = valdata;
                                        }
                                        //handle DWORD and QWORD reg data
                                        else if (parentKey.GetValueKind(v) == RegistryValueKind.DWord || parentKey.GetValueKind(v) == RegistryValueKind.QWord)
                                        {
                                            valdata = parentKey.GetValue(v).ToString();
                                            //first value will be in decimal, hex in parenthesis
                                            displayData = "'" + int.Parse(valdata).ToString() + "' (0x" + int.Parse(valdata).ToString("x") + ")";
                                        }
                                        else
                                        {
                                            valdata = parentKey.GetValue(v).ToString();
                                            displayData = "'" + valdata + "'";
                                        }

                                        matchRecord.RegistryValueData = valdata;

                                        //if it's a file, mark the appropriate field in the registry signature entry.
                                        //later on , these files will be deleted if settings dictate it.
                                        if (filePathValidator.IsMatch(valdata))
                                            matchRecord.IsFileOnDisk = true;
                                        else
                                            matchRecord.IsFileOnDisk = false;

                                        //log it in pretty format
                                        RegistryHelperLog.AppendLine("       " + v + " = '" + displayData + "'");

                                        //add it to our result set
                                        matchList.Add(matchRecord);
                                    }
                                    //otherwise teh value name coudl not be retrieved, so no real match here.
                                    else
                                    {
                                        RegistryHelperLog.AppendLine("SCAN:  The value name '" + keyName + "\\" + v + "' doesn't exist.");
                                    }
                                }
                            }
                            catch (Exception e)
                            {
                                RegistryHelperLog.AppendLine("SCAN:  Caught exception '" + e.Message + "', can't get this value name.");
                            }
                        }
                        else
                        {
                            RegistryHelperLog.AppendLine("SCAN:  The parent key '" + keyName + "' doesn't exist.");
                        }
                    } //end looping through expanded reg values for this reg indicator
                } // end looping through ALL registry indicators

                //re-initialize our return object to the number of items in arraylist
                int i = 0;

                matches = new CwXML.RegistrySignatureMatch[matchList.Count];

                //add all registry findings in the arraylist to our matches object
                foreach (CwXML.RegistrySignatureMatch match in matchList)
                {
                    matches[i] = new CwXML.RegistrySignatureMatch();
                    matches[i] = match;
                    i++;
                }
            }
예제 #9
0
        /////////////////////////////////////////////////////
        //                                                 //
        // LoadAgentSettings()                             //
        //                                                 //
        /////////////////////////////////////////////////////
        //Description:  Loads settings from the agent config file.
        //
        //Returns:      true if successful
        //////////////////////////////////////////////////////
        private unsafe bool LoadAgentSettings(ref Dictionary<string, string> AgentSettings)
        {
            //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)
            {
                AgentServiceLog.AppendLine("ERROR:  " + e.Message);
                AgentServiceLog.AppendLine("ERROR:  Failed to load settings, terminating...");
                return false;
            }

            //copy the settings from the CST object to a more usable dictionary<> struct
            int count = 0;
            foreach (string s in cst.FormElementNames)
            {
                AgentSettings[s] = cst.FormElementValues[count];
                count++;
            }

            AgentServiceLog.AppendLine("INITIALIZE:  Success.");
            return true;
        }
예제 #10
0
            /////////////////////////////////////////////////////
            //                                                 //
            // CleanMemoryFindings()                           //
            //                                                 //
            /////////////////////////////////////////////////////
            //Description:  kills/suspends offending processes
            //Returns:      none
            /////////////////////////////////////////////////////
            internal void CleanMemoryFindings(ref CwXML.MemorySignatureMatch[] MemorySignatureMatches)
            {
                //the line below is added for compatibility when calling this function
                //over remote channels from the admin console
                if (MemoryHelperLog == null)
                    MemoryHelperLog = new StringBuilder();

                int count = 0;

                //Possible actions:
                /*
                Terminate process if exists
                Terminate process if keyword found
                Suspend containing thread if keyword found
                */
                foreach (CwXML.MemorySignatureMatch match in MemorySignatureMatches)
                {
                    string action = match.Action;
                    IntPtr hProcess = Win32Helper.OpenProcess(Win32Helper.PROCESS_TERMINATE, false, match.ProcessId);

                    //try to obtain a handle to the process to kill/suspend
                    if(hProcess == IntPtr.Zero)
                    {
                        MemoryHelperLog.AppendLine("CLEAN:  Failed to open process PID " + match.ProcessId.ToString() + ":  " + Win32Helper.GetLastError32());
                        MemorySignatureMatches[count].ActionSuccessful = false;
                        count++;
                        continue;
                    }

                    // * TERMINATE PROCESS *
                    if (action == "Terminate process if exists" || action == "Terminate process if keyword found")
                    {
                        //note:  experience has shown you cant trust the return value of ZwTerminateProcess().
                        //dont even bother to validate it, assume success (we do have elevated privs!)
                        Win32Helper.ZwTerminateProcess(hProcess, Win32Helper.STATUS_SUCCESS);
                        Win32Helper.CloseHandle(hProcess);
                        MemorySignatureMatches[count].ActionSuccessful = true;
                    }
                    //* SUSPEND CONTAINING THREAD *
                    else if (action == "Suspend containing thread if keyword found")
                    {
                        //
                        //TODO
                        //
                        MemoryHelperLog.AppendLine("CLEAN:  Warning:  Suspending thread not implemented.");
                        MemorySignatureMatches[count].ActionSuccessful = false;
                    }

                    count++;
                }

                return;
            }
예제 #11
0
        private void loadSettingsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //-----------------------------------------------
            //              DETERMINE IMPORT FILENAME
            //-----------------------------------------------
            //show browse dialog to select file
            OpenFileDialog dlg = new OpenFileDialog();
            dlg.CheckFileExists = true;
            dlg.CheckPathExists = true;
            dlg.DefaultExt = ".xml"; //default extension
            dlg.Title = "Select settings file";
            dlg.Filter = "XML Files|*.xml";
            dlg.Multiselect = false;
            CwXML xml = new CwXML();
            CwXML.CodewordSettingsTemplate cst=new CwXML.CodewordSettingsTemplate();

            //the user clicked cancel
            if (dlg.ShowDialog() != DialogResult.OK)
                return;

            string filename = dlg.FileName;

            try
            {
                cst=xml.LoadSettingsXML(filename);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                return;
            }

            //we successfully deserialized the XML document, now load it into
            //the GUI form at the appropriate locations
            //
            int numInvalid = 0, numSuccess = 0, count = 0;

            //
            //loop through form element names stored in the settings document
            //and try to set them in the Window's form.
            //
            foreach (string elementName in cst.FormElementNames)
            {
                //if we looped through all tab pages and didnt find this element name,
                //it must be deprecated - store for error msg later
                if (!((bool)CrawlTabPages("SetFormValue", elementName, cst.FormElementValues[count])))
                    numInvalid++;
                else
                    numSuccess++;
                count++;
            }

            MessageBox.Show("Successfully loaded " + numSuccess + " settings!\n\nThere were " + numInvalid + " invalid setting items.");
        }
예제 #12
0
            /////////////////////////////////////////////////////
            //                                                 //
            // PrintMemoryFindings()                           //
            //                                                 //
            /////////////////////////////////////////////////////
            //Description:  outputs memory findings
            //Returns:      none
            /////////////////////////////////////////////////////
            internal void PrintMemoryFindings(CwXML.MemorySignatureMatch[] MemorySignatureMatches, ref StringBuilder output)
            {
                output.AppendLine("");
                output.AppendLine("REPORT:  ******************************");
                output.AppendLine("REPORT:  Memory Findings");
                output.AppendLine("REPORT:  ******************************");
                output.AppendLine("");
                output.AppendLine("Process\t\tPID (PPID)\t\tKeywords\t\tMatching Block\t\tChild ThreadIds\t\tMalicious Module(s)\t\tSuspicious Heap Blockp\t\tAction\t\tAction Successful\t");

                if (MemorySignatureMatches.Length == 0)
                {
                    output.AppendLine("REPORT:  No memory signatures were found.");
                }
                else
                {
                    //loop through all match records
                    foreach (CwXML.MemorySignatureMatch match in MemorySignatureMatches)
                    {
                        output.AppendLine("");
                        output.Append(match.ProcessName + "\t\t");
                        output.Append(match.ProcessId.ToString() + "("+match.ParentProcessId.ToString()+"\t\t");
                        output.Append(match.Keywords + "\t\t");
                        output.Append(match.MatchingBlock + "\t\t");
                        output.Append(match.ChildThreadIds + "\t\t");
                        output.Append(match.MaliciousLoadedModuleName + ","+match.MaliciousLoadedModuleSize+" bytes,"+match.MaliciousLoadedModuleBaseAddr+" base addr\t\t");
                        output.Append(match.SuspiciousHeapBlockRange + "\t\t");
                        output.Append(match.Action + "\t\t");
                        output.Append(match.ActionSuccessful.ToString() + "\t\t");
                    }
                }

                output.AppendLine("");
                output.AppendLine("REPORT:  ******************************");
                output.AppendLine("");
            }
예제 #13
0
            /////////////////////////////////////////////////////
            //                                                 //
            // ScanForMemorySignatures()                       //
            //                                                 //
            /////////////////////////////////////////////////////
            //Description:  this function searches the heap space of
            //              process(es) of interest for supplied keyword(s)
            //Returns:      true if keyword found
            /////////////////////////////////////////////////////
            internal unsafe void ScanForMemorySignatures(CwXML.RegistrySignatureMatch[] RegistryFindings, CwXML.MemorySignature[] MemorySignatures, ref CwXML.MemorySignatureMatch[] matches, bool SearchCmdline, bool SearchHeap, bool searchModuleList, bool searchRegistryFindings)
            {
                //we will use this regex to validate whether a given keyword is a valid filename/path or not
                //this is used when we are walking the module list
                Regex filePathValidator = new Regex(@"^(([a-zA-Z]\:)|(\\))(\\{1}|((\\{1})[^\\]([^/:*?<>""|]*))+)$");
                ArrayList Findings=new ArrayList();

                //
                //loop through each memory signature and search
                //
                foreach (CwXML.MemorySignature m in MemorySignatures)
                {
                    //is this process name for this signature in the list of active processes?
                    string ProcessName = m.ProcessName;
                    ArrayList ProcessInfo = GetActiveProcessInfo(ProcessName);
                    string action = m.Action;

                    //if not, skip it.
                    if (ProcessInfo == null)
                    {
                        MemoryHelperLog.AppendLine("SCAN:  The target process " + ProcessName + " is not running, skipping this signature...");
                        continue;
                    }
                    if (ProcessInfo.Count == 0)
                    {
                        MemoryHelperLog.AppendLine("SCAN:  The target process " + ProcessName + " did not return a full data set, skipping this signature...");
                        continue;
                    }

                    //* PROCESS OF INTEREST IS IN THE LIST OF RUNNING PROCESSES... *//
                    uint pid = (uint)ProcessInfo[0];
                    uint ppid = (uint)ProcessInfo[1];
                    uint threadCount = (uint)ProcessInfo[2];

                    //were any keywords given to search this process heap/cmdline/modlist?
                    string[] Keywords = m.Keywords.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);

                    //if no keywords were given, then we can conclude our task was only to identify that
                    //this process name was running on the system.  if that's the case, return a hit.
                    if (Keywords.Length == 0)
                    {
                        MemoryHelperLog.AppendLine("SCAN:  Match found for process name '" + ProcessName + "'!");
                        CwXML.MemorySignatureMatch matchRecord = new CwXML.MemorySignatureMatch();
                        matchRecord.MatchingBlock = ProcessName;
                        matchRecord.ProcessId = pid;
                        matchRecord.ParentProcessId = ppid;
                        matchRecord.ProcessName = ProcessName;
                        matchRecord.Keywords = "";
                        matchRecord.ChildThreadIds = GetChildThreadIds((uint)pid);
                        matchRecord.Action = action;

                        //note:  we are adding the match this way to be consistent with how
                        //we have to add them in SearchProcessCmdLine() and other funcs
                        ArrayList tmpMatches = new ArrayList();
                        tmpMatches.Add(matchRecord);

                        Findings.Add(tmpMatches);
                        continue;
                    }

                    //otherwise, we need to search either the process heap, cmd line, or module list
                    //for the given keywords in this memory signature.
                    ArrayList KeywordList = new ArrayList();
                    KeywordList.AddRange(Keywords);

                    //if the user wants to use registry findings in our keyword scan, add them now
                    if (searchRegistryFindings)
                        foreach (CwXML.RegistrySignatureMatch regMatch in RegistryFindings)
                            if (regMatch.RegistryValueData != null)
                                if (regMatch.RegistryValueData.Length < 300)
                                    KeywordList.Add(regMatch.RegistryValueData);

                    //*********************************
                    //      SCAN OPTIONS
                    //*********************************
                    //perform the following per-process scans, depending on user options:
                    // 1) use WMI to search the Cmdline for this process for keywords/indicators
                    // 2) use Win32 API to search the module list for keywords/indicators
                    // 3) use Win32 API to search the heap space for keywords/indicators

                    MemoryHelperLog.AppendLine("SCAN:  Searching target process " + ProcessName + " (PID=" + pid.ToString() + ")...");
                    MemoryHelperLog.AppendLine("SCAN:  Using keyword search list (" + KeywordList.Count + "):  '" + string.Join(",", ((string[])KeywordList.ToArray(typeof(string)))) + "'");

                    //*********************************
                    //      PERFORM SCANS
                    //*********************************
                    // 1) use WMI to search the Cmdline for this process for keywords/indicators
                    if (SearchCmdline)
                    {
                        ArrayList cmdlineFindings = new ArrayList();

                        MemoryHelperLog.Append("SCAN:  Searching command line ...");
                        if (!SearchProcessCmdline(pid, ppid, action, KeywordList, ref cmdlineFindings))
                            MemoryHelperLog.Append("nothing.");
                        else
                        {
                            MemoryHelperLog.Append(cmdlineFindings.Count + " matches!");
                            Findings.Add(cmdlineFindings);
                        }
                        MemoryHelperLog.AppendLine();
                    }
                    // 2) use Win32 API to search the module list for keywords/indicators
                    if (searchModuleList)
                    {
                        ArrayList modListFindings = new ArrayList();

                        MemoryHelperLog.Append("SCAN:  Searching loaded module list ...");
                        if (!SearchProcessLoadedModuleList(pid, ppid, ProcessName, action, KeywordList, ref modListFindings))
                            MemoryHelperLog.Append("nothing.");
                        else
                        {
                            MemoryHelperLog.Append(modListFindings.Count + " matches!");
                            Findings.Add(modListFindings);
                        }
                        MemoryHelperLog.AppendLine();
                    }
                    // 3) use Win32 API to search the heap space for keywords/indicators
                    if (SearchHeap)
                    {
                        ArrayList heapFindings = new ArrayList();

                        MemoryHelperLog.AppendLine("SCAN:  Searching heap space ...");
                        if (!SearchProcessHeap((uint)pid, ppid, ProcessName, action, KeywordList, ref heapFindings))
                            MemoryHelperLog.Append("SCAN:  Nothing.");
                        else
                        {
                            MemoryHelperLog.AppendLine("SCAN:  "+heapFindings.Count + " matches!");
                            Findings.Add(heapFindings);
                        }
                        MemoryHelperLog.AppendLine();
                    }
                }

                MemoryHelperLog.AppendLine("SCAN:  Done scanning processes, collating results...");

                //first find out how many findings we had
                if (Findings.Count > 0)
                {
                    MemoryHelperLog.AppendLine("SCAN:  There are " + Findings.Count + " memory finding set matches.");

                    int retBufSize = 0, i = 0;
                    foreach (ArrayList ar in Findings)
                        foreach (CwXML.MemorySignatureMatch m in ar)
                            retBufSize++;

                    matches = new CwXML.MemorySignatureMatch[retBufSize];

                    //loop through all matches and add them to findings
                    foreach (ArrayList ar in Findings)
                    {
                        foreach (CwXML.MemorySignatureMatch m in ar)
                        {
                            matches[i] = new CwXML.MemorySignatureMatch();
                            matches[i] = m;
                            i++;
                        }
                    }
                }
                else
                    matches = new CwXML.MemorySignatureMatch[0];
            }
예제 #14
0
        /////////////////////////////////////////////////////
        //                                                 //
        // 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;
        }
예제 #15
0
        /////////////////////////////////////////////////////
        //                                                 //
        // LoadAgentSignatures()                           //
        //                                                 //
        /////////////////////////////////////////////////////
        //Description:  Loads signatures from the agent sig file.
        //
        //Returns:      true if successful
        //////////////////////////////////////////////////////
        private unsafe bool LoadAgentSignatures()
        {
            //use XML signature template file in current directory - "CwAgentSignatures.xml"
            //this will allow us to deserialize the XML data into class structures
            CwXML xml = new CwXML();
            CwXML.CodewordSignatureTemplate sigs = new CwXML.CodewordSignatureTemplate();
            try
            {
                sigs = xml.ImportSignatureTemplate("CwAgentSignatures.xml");
            }
            catch (Exception e)
            {
                AgentScanLog.AppendLine("ERROR:  " + e.Message);
                AgentScanLog.AppendLine("ERROR:  Failed to load signatures, terminating...");
                return false;
            }

            //save the values into global variables for all funcs to access
            AgentRegistrySignatures = sigs.RegistrySignatures;
            AgentRegistryGuidSignatures = sigs.RegistryGuidSignatures;
            AgentFileSignatures = sigs.FileSignatures;
            AgentMemorySignatures = sigs.MemorySignatures;

            return true;
        }
예제 #16
0
        /////////////////////////////////////////////////////
        //                                                 //
        // SendCommand()                                   //
        //                                                 //
        /////////////////////////////////////////////////////
        //Description:  Attempts to send a message over SSL.
        //
        //Throws:       Serialization error
        //
        //Returns:      true if successful
        /////////////////////////////////////////////////////
        internal bool SendCommand(int commandCode, string[] args, int timeout, bool responseRequired, CwXML.CodewordAgentAnomalyReport CollectOrMitigationTask)
        {
            CwXML.CodewordAgentCommand cmd = new CwXML.CodewordAgentCommand();
            cmd.CommandCode = commandCode;
            cmd.CommandParameters = args;
            cmd.CommandTimeout = timeout;
            cmd.ResponseRequired = responseRequired;
            cmd.CommandCollectOrMitigationTask = CollectOrMitigationTask;

            //create an XML serialization object to prepare the command
            XmlSerializer serializer = new XmlSerializer(typeof(CwXML.CodewordAgentCommand));

            //create a memory stream to which we will serialize our response object
            MemoryStream memStream = new MemoryStream();

            //store the object's state in XML format into the memory stream store
            serializer.Serialize(memStream, cmd);

            //tack on "<EOF>" to the message, so the server knows when to stop reading the socket
            char[] eofbuf = new char[] { '<', 'E', 'O', 'F', '>' };
            memStream.Write(Encoding.UTF8.GetBytes(eofbuf), 0, eofbuf.Length);

            //try to send the raw bytes in the memory stream to the remote socket
            try
            {
                //result of 5 hour debug session:  dont use memstream.getBuffer()
                //it returns all bytes in the buffer, not only the ones used..use ToArray() instead!!
                ClientSslStream.Write(memStream.ToArray());
                ClientSslStream.Flush();
            }
            catch (Exception ex)
            {
                throw new Exception("ClientSslStream.Write() error:  " + ex.Message);
            }

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

            memStream.Close();

            return true;
        }
예제 #17
0
            /////////////////////////////////////////////////////
            //                                                 //
            // LoadDynamicGUIDs()                              //
            //                                                 //
            /////////////////////////////////////////////////////
            //Description:  loads all dynamic GUIDs supplied and adds
            //              a static guid to our registry guid signatures
            //              object for each expanded value.
            //
            //Returns:      true if successful
            /////////////////////////////////////////////////////
            internal bool LoadDynamicGUIDs(ref CwXML.RegistryGuidSignature[] GuidSignatures)
            {
                Regex GUIDvalidator = new Regex(@"^(\{){0,1}[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}(\}){0,1}$", RegexOptions.Compiled);

                //first get a count of how many Dynamic Guids there are
                int NumDynamicGuids = 0;
                foreach (CwXML.RegistryGuidSignature sig in GuidSignatures)
                    if (sig.GuidType == "Dynamic")
                        NumDynamicGuids++;

                //none to process.
                if (NumDynamicGuids == 0)
                    return true;

                //allocate a new object to store that many dynamic guids
                ArrayList DynamicSigsToAdd = new ArrayList(NumDynamicGuids);

                //loop through all our GUID signatures and extract GUIDs from this live system's registry
                //that are stored at the registry key indicated by the given Dynamic GUID signature
                foreach (CwXML.RegistryGuidSignature sig in GuidSignatures)
                {
                    string keyName = sig.GuidValue;
                    string type = sig.GuidType;//"Static" or "Dynamic"
                    string GUID = keyName;  //by default, we assume it's static
                    string valueName = "";

                    //skip any static Guid Signatures -- our goal here is to MAKE static sigs
                    //from dynamic sigs that must be populated at runtime
                    if (type == "Static")
                        continue;

                    //hive parsing vars
                    int firstSlashInKeyName = keyName.IndexOf('\\');
                    string hive = keyName.Substring(0, firstSlashInKeyName);
                    string keyWithoutHive = keyName.Substring(firstSlashInKeyName, keyName.Length - firstSlashInKeyName);
                    keyName = keyWithoutHive;
                    RegistryKey key;

                    if (hive == "HKLM")
                        key = Registry.LocalMachine;
                    else if (hive == "HKCR")
                        key = Registry.ClassesRoot;
                    else if (hive == "HKU")
                        key = Registry.Users;
                    else if (hive == "HKCC")
                        key = Registry.CurrentConfig;
                    else
                    {
                        RegistryHelperLog.AppendLine("ERROR:  Invalid hive supplied in GUID:  '" + keyName + "', skipping..");
                        continue;
                    }

                    //it is possible this Dynamic Guid signature has an embedded {SID} expansion var.
                    //so try to expand this key.
                    string[] expandedKeys = ExpandRegistryKey(keyName, GuidSignatures);
                    string thisKeyName;

                    //if nothing was expanded, use the original key
                    if (expandedKeys == null)
                        expandedKeys = new string[] { keyName };

                    //loop through all resulting records that were expanded,
                    foreach (string expandedKey in expandedKeys)
                    {
                        thisKeyName = expandedKey.Trim(new char[] { ' ', '\\' });

                        //try to open the (by now chopped up) keyName ..
                        RegistryKey loadedKey = key.OpenSubKey(thisKeyName);

                        //bail if cant open key
                        if (loadedKey == null)
                        {
                            RegistryHelperLog.AppendLine("ERROR:  Could not load GUID, invalid key specified: '" + thisKeyName + "', skipping...");
                            continue;
                        }

                        //great!  loaded the key.. now try to get the value data stored at the value Name
                        object obj = loadedKey.GetValue(valueName);

                        if (obj == null)
                        {
                            RegistryHelperLog.AppendLine("ERROR:  Could not load GUID, invalid value name specified: '" + valueName + "', skipping...");
                            continue;
                        }

                        //sweet!  got the value name data..make sure it's a legit GUID
                        if (!GUIDvalidator.IsMatch(obj.ToString()))
                        {
                            RegistryHelperLog.AppendLine("ERROR:  Found a GUID value, but it's invalid: '" + obj.ToString() + "', skipping...");
                            continue;
                        }

                        //store the value
                        GUID = (string)obj.ToString();

                        //strip out curly braces from GUID if present
                        GUID = GUID.Replace("{", "");
                        GUID = GUID.Replace("}", "");

                        //add it as a static GUID to our tmp signatures
                        CwXML.RegistryGuidSignature g = new CwXML.RegistryGuidSignature();
                        g.GuidType = "Static";
                        g.GuidValue = GUID;
                        DynamicSigsToAdd.Add(g);
                    }
                }

                //add all dynamic guids that are now static guids into our guid sigs array
                foreach (CwXML.RegistryGuidSignature g in DynamicSigsToAdd)
                {
                    if (g.GuidType != null && g.GuidValue != null)
                    {
                        //resize our permanent array by 1
                        Array.Resize(ref GuidSignatures, GuidSignatures.Length + 1);
                        GuidSignatures[GuidSignatures.Length] = g;
                    }
                }

                return true;
            }
예제 #18
0
        //
        //Allows the user to select a template file that represents predefined file, registry,
        //and memory signatures for a given piece of malware
        //
        private void loadSignatureTemplateToolStripMenuItem_Click(object sender, EventArgs e)
        {
            int numRegImported = 0;
            int numRegGuidImported = 0;
            int numFileImported = 0;
            int numMemoryImported = 0;
            int numDuplicatesIgnored = 0;
            int numErrorSkipped = 0;

            //-----------------------------------------------
            //              DETERMINE IMPORT FILENAME
            //-----------------------------------------------
            //show browse dialog to select file
            OpenFileDialog dlg = new OpenFileDialog();
            dlg.CheckFileExists = true;
            dlg.CheckPathExists = true;
            dlg.DefaultExt = ".xml"; //default extension
            dlg.Title = "Select signature template file";
            dlg.Filter = "XML Files|*.xml";
            dlg.Multiselect = true;

            //the user clicked cancel
            if (dlg.ShowDialog() != DialogResult.OK)
                return;

            int filecount = dlg.FileNames.Length;
            CwXML.CodewordSignatureTemplate cwt = new CwXML.CodewordSignatureTemplate();
            CwXML xml = new CwXML();

            //
            //loop through list of filenames selected and deserialize each XML
            //document into an instantation of the CwTemplate class
            //
            foreach (string filename in dlg.FileNames)
            {
                //deserialize the data stored in this signature file
                try
                {
                    cwt = xml.ImportSignatureTemplate(filename);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                    return;
                }

                //we successfully deserialized the XML document, now load it into
                //the GUI form at the appropriate locations
                CwXML.RegistrySignature[] regSigs = cwt.RegistrySignatures;
                CwXML.RegistryGuidSignature[] regGuidSigs = cwt.RegistryGuidSignatures;
                CwXML.FileSignature[] fileSigs = cwt.FileSignatures;
                CwXML.MemorySignature[] memSigs = cwt.MemorySignatures;

                //REG sigs
                foreach (CwXML.RegistrySignature rs in regSigs)
                {
                    ListViewItem lvi = new ListViewItem(new string[] { rs.KeyName, rs.ValueName, rs.ValueData, rs.ChangeValueData, rs.Action });

                    if (RegistrySignatures_Listview.Items.Contains(lvi))
                    {
                        numDuplicatesIgnored++;
                        continue;
                    }
                    RegistrySignatures_Listview.Items.Add(lvi);
                    numRegImported++;
                }
                //REG GUID sigs
                foreach (CwXML.RegistryGuidSignature rsg in regGuidSigs)
                {
                    ListViewItem lvi = new ListViewItem(new string[] { rsg.GuidValue, rsg.GuidType });
                    if (RegistryGuidSignatures_Listview.Items.Contains(lvi))
                    {
                        numDuplicatesIgnored++;
                        continue;
                    }
                    RegistryGuidSignatures_Listview.Items.Add(lvi);
                    numRegGuidImported++;
                }
                //FILE sigs
                foreach (CwXML.FileSignature fs in fileSigs)
                {
                    ListViewItem lvi = new ListViewItem(new string[] { fs.FileName, fs.FileHash, fs.FileHashType, fs.FileSize.ToString(), fs.FilePEHeaderSignature, fs.Action });
                    if (FileSignatures_Listview.Items.Contains(lvi))
                    {
                        numDuplicatesIgnored++;
                        continue;
                    }
                    FileSignatures_Listview.Items.Add(lvi);
                    numFileImported++;
                }
                //MEM sigs
                foreach (CwXML.MemorySignature ms in memSigs)
                {
                    ListViewItem lvi = new ListViewItem(new string[] { ms.ProcessName, ms.Keywords, ms.Action });
                    if (MemorySignatures_Listview.Items.Contains(lvi))
                    {
                        numDuplicatesIgnored++;
                        continue;
                    }
                    MemorySignatures_Listview.Items.Add(lvi);
                    numMemoryImported++;
                }
            }

            MessageBox.Show("Successfully imported signatures from " + filecount + " files!\n\nSignatures imported:\nRegistry:  " + numRegImported + "\nRegistry GUID:  " + numRegGuidImported + "\nFile:  " + numFileImported + "\nMemory:  " + numMemoryImported + "\n\nDuplicates ignored:  " + numDuplicatesIgnored + "\nSkipped due to errors:  " + numErrorSkipped);
        }
예제 #19
0
            /////////////////////////////////////////////////////
            //                                                 //
            // PrintRegistryFindings()                         //
            //                                                 //
            /////////////////////////////////////////////////////
            //Description:  stores findings in passed-in stringbuilder
            //Returns:      nothing
            /////////////////////////////////////////////////////
            internal void PrintRegistryFindings(CwXML.RegistrySignatureMatch[] matches, ref StringBuilder output)
            {
                output.AppendLine("");
                output.AppendLine("REPORT:  ******************************");
                output.AppendLine("REPORT:  Registry Findings");
                output.AppendLine("REPORT:  ******************************");
                output.AppendLine("");
                output.AppendLine("Key Name\t\tValue Name\t\tValue Data\t\tAction\t\tAction Successful\t\tOn Disk?");

                if (matches.Length == 0)
                {
                    output.AppendLine("REPORT:  No registry signatures were found.");
                }
                else
                {
                    //loop through all match records
                    foreach (CwXML.RegistrySignatureMatch match in matches)
                    {
                        output.AppendLine("");
                        output.Append(match.RegistryKeyName + "\t\t");
                        output.Append(match.RegistryValueName + "\t\t");
                        output.Append(match.RegistryValueData + "\t\t");
                        output.Append(match.Action + "\t\t");
                        output.Append(match.ActionSuccessful.ToString() + "\t\t");
                        output.Append(match.IsFileOnDisk.ToString());
                    }
                }

                output.AppendLine("");
                output.AppendLine("REPORT:  ******************************");
                output.AppendLine("");
            }
예제 #20
0
            /////////////////////////////////////////////////////
            //                                                 //
            // PrintFileFindings()                             //
            //                                                 //
            /////////////////////////////////////////////////////
            //Description:  prints file signature findings
            //Returns:      nothing
            /////////////////////////////////////////////////////
            internal void PrintFileFindings(CwXML.FileSignatureMatch[] matches, ref StringBuilder output)
            {
                output.AppendLine("");
                output.AppendLine("REPORT:  ******************************");
                output.AppendLine("REPORT:  File Findings");
                output.AppendLine("REPORT:  ******************************");
                output.AppendLine("");
                output.AppendLine("Full Path\t\tSize\t\tHash (Type)\t\tPE Sig.\t\tCreated\t\tAccessed\t\tModified\t\tAction\t\tAction Successful\t\tOn Disk?");

                if (matches.Length == 0)
                {
                    output.AppendLine("REPORT:  No file signatures were found.");
                }
                else
                {
                    //loop through all match records
                    foreach (CwXML.FileSignatureMatch match in matches)
                    {
                        output.AppendLine("");
                        output.Append(match.FullPath + "\t\t");
                        output.Append(match.FileSize.ToString() + "\t\t");
                        output.Append(match.FileHash+" ("+match.FileHashType+")" + "\t\t");
                        output.Append(match.FilePEHeaderSignature + "\t\t");
                        output.Append(match.FileCreationDate + "\t\t");
                        output.Append(match.FileLastAccessDate + "\t\t");
                        output.Append(match.FileLastModifiedDate + "\t\t");
                        output.Append(match.Action + "\t\t");
                        output.Append(match.ActionSuccessful.ToString() + "\t\t");
                    }
                }

                output.AppendLine("");
                output.AppendLine("REPORT:  ******************************");
                output.AppendLine("");
            }
예제 #21
0
            /////////////////////////////////////////////////////
            //                                                 //
            // CleanRegistryFindings()                         //
            //                                                 //
            /////////////////////////////////////////////////////
            //Description:  Applies desired action to all registry
            //              findings and stores the result in
            //              the passed-in structure (success/fail).
            //Returns:      none
            /////////////////////////////////////////////////////
            internal void CleanRegistryFindings(ref CwXML.RegistrySignatureMatch[] matches, bool RemoveFileReferencesFromDisk)
            {
                //the line below is added for compatibility when calling this function
                //over remote channels from the admin console
                if (RegistryHelperLog == null)
                    RegistryHelperLog = new StringBuilder();

                RegistryHelperLog.AppendLine("CLEAN:  Cleaning "+matches.Length.ToString()+" registry findings...");

                RegistryKey key;
                int count = 0;

                //*************************************
                //      DELETE ANY BAD FILES FROM DISK
                //      THAT WERE FOUND IN REGISTRY
                //*************************************
                if (RemoveFileReferencesFromDisk)
                {
                    RegistryHelperLog.AppendLine("CLEAN:  Removing any malware files referenced in registry findings...");

                    //loop through all registry findings and if "ISFileOnDisk" = "true", then delete it
                    foreach (CwXML.RegistrySignatureMatch match in matches)
                    {
                        if (match.IsFileOnDisk)
                        {
                            try
                            {
                                File.Delete(match.RegistryValueData);
                            }
                            catch(Exception ex)
                            {
                                RegistryHelperLog.AppendLine("CLEAN:  Failed to delete file '"+match.RegistryValueData+"':  "+ex.Message);
                                matches[count].ActionSuccessful = false;
                                count++;
                                continue;
                            }
                            matches[count].ActionSuccessful = true;
                        }
                        count++;
                    }
                }

                count = 0;

                //*************************************
                //      APPLY GIVEN ACTION TO MATCH
                //*************************************
                //now loop thru the value names again and delete as necessary
                foreach (CwXML.RegistrySignatureMatch match in matches)
                {
                    string keyName = match.RegistryKeyName;
                    string valueName = match.RegistryValueName;
                    string action = match.Action;
                    string valueData = match.RegistryValueData;
                    string changeValueData = match.RegistryChangeValueData;

                    int firstSlashInKeyName = keyName.IndexOf('\\');
                    string hive = keyName.Substring(0, firstSlashInKeyName).ToUpper();
                    string keyWithoutHive = keyName.Substring(firstSlashInKeyName+1, keyName.Length - (firstSlashInKeyName+1));
                    keyName = keyWithoutHive;

                    if (hive == "HKLM")
                        key = Registry.LocalMachine;
                    else if (hive == "HKCR")
                        key = Registry.ClassesRoot;
                    else if (hive == "HKU")
                        key = Registry.Users;
                    else if (hive == "HKCC")
                        key = Registry.CurrentConfig;
                    else
                    {
                        RegistryHelperLog.AppendLine("WARNING:  Invalid hive detected in registry indicator:");
                        RegistryHelperLog.AppendLine("          Key:  '" + keyName + "'");
                        RegistryHelperLog.AppendLine("          Parsed hive:  '" + hive + "'");
                        RegistryHelperLog.AppendLine("WARNING:  Skipping this indicator...");
                        continue; //skip if bad hive
                    }

                    RegistryKey parentKey = key.OpenSubKey(keyName, true);

                    if (parentKey != null)
                    {
                        try
                        {
                            object obj = parentKey.GetValue(valueName);

                            if (obj != null)
                            {
                                //try to delete just this value name
                                if (action == "Delete" || action == "Delete All")
                                {
                                    RegistryHelperLog.AppendLine("SCAN:  Deleting '" + keyName + "\\" + valueName + "'...");

                                    try
                                    {
                                        parentKey.DeleteValue(valueName);
                                    }
                                    catch (Exception e)
                                    {
                                        matches[count].ActionSuccessful = false;
                                        count++;
                                        RegistryHelperLog.AppendLine("ERROR:  Caught exception '" + e.Message + "', not deleting this value name.");
                                        continue;
                                    }
                                    matches[count].ActionSuccessful = true;
                                }
                                else if (action == "Change...")
                                {
                                    //the value data will be what we want to change it to
                                    RegistryHelperLog.AppendLine("SCAN:  Setting '" + keyName + "\\" + valueName + "' = '" + changeValueData + "'...");

                                    try
                                    {
                                        parentKey.SetValue(valueName, changeValueData);
                                    }
                                    catch (Exception e)
                                    {
                                        matches[count].ActionSuccessful = false;
                                        count++;
                                        RegistryHelperLog.AppendLine("ERROR:  Caught exception '" + e.Message + "', not changing this value name.");
                                        continue;
                                    }
                                    matches[count].ActionSuccessful = true;
                                }
                                else if (action == "Clear")
                                {
                                    //the value data will be what we want to change it to
                                    RegistryHelperLog.AppendLine("SCAN:  Clearing '" + keyName + "\\" + valueName + "'...");

                                    try
                                    {
                                        parentKey.SetValue(valueName, "");
                                    }
                                    catch (Exception e)
                                    {
                                        matches[count].ActionSuccessful = false;
                                        count++;
                                        RegistryHelperLog.AppendLine("ERROR:  Caught exception '" + e.Message + "', not clearing this value name.");
                                        continue;
                                    }
                                    matches[count].ActionSuccessful = true;
                                }
                            }
                            else
                            {
                                RegistryHelperLog.AppendLine("SCAN:  The value name '" + keyName + "\\" + valueName + "' doesn't exist, not modifying.");
                                matches[count].ActionSuccessful = false;
                            }
                        }
                        catch (Exception e)
                        {
                            RegistryHelperLog.AppendLine("SCAN:  Caught exception '" + e.Message + "', can't get this value name.");
                            matches[count].ActionSuccessful = false;
                            count++;
                            continue;
                        }
                    }
                    else
                    {
                        matches[count].ActionSuccessful = false;
                        RegistryHelperLog.AppendLine("SCAN:  Failed to open parent key '" + keyName + "'...");
                    }
                    count++;
                }

                // ** EXTREMELY IMPORTANT ** //
                //must FLUSH the registry to force oS to synch in-memory cached registry
                //to the on-disk registry so that subsequent scans dont pick up results
                //that were cleaned but not synched yet.
                //This "out of synch" issue occasionally happens and shouldn't according to MSDN:
                /*
                 * "It is not necessary to call Flush to write out changes to a key. Registry changes are flushed
                 * to disk when the registry uses its lazy flusher. Lazy flushing occurs automatically and
                 * regularly after a system-specified time interval. Registry changes are also flushed to disk at system shutdown.
                 * Unlike Close, the Flush function returns only when all the data has been written to the registry.
                 * The Flush function might also write out parts of or all of the other keys. Calling this function excessively
                 * can have a negative effect on an application's performance.
                 * An application should only call Flush if it must be absolute certain that registry changes are recorded to disk.
                 * In general, Flush rarely, if ever, need be used."
                 * */
                //flush them all, even if we didn't write to them.
                Registry.LocalMachine.Flush();
                Registry.ClassesRoot.Flush();
                Registry.Users.Flush();
                Registry.CurrentConfig.Flush();
            }
예제 #22
0
        /////////////////////////////////////////////////////
        //                                                 //
        // CopyResponseToLogWindow()                       //
        //                                                 //
        /////////////////////////////////////////////////////
        //Description:  copies the fields of the given response
        //              object to the log window pane.
        //
        //Returns:      void
        /////////////////////////////////////////////////////
        private void CopyResponseToLogWindow(CwXML.CodewordAgentResponse response)
        {
            string currentLogWindowText = LogWindow.Text;
            string newLogText = "";

            LastCommandPane.Text = "";
            LastCommandPane.Text += "COMMAND:  " + response.CommandCodeReceived.ToString() + "\r\n";
            LastCommandPane.Text += "RESPONSE:  " + response.ResponseCode + "\r\n";

            //ResponseInfo is optional, so check for null
            if (response.ResponseInfo != null)
                LastCommandPane.Text += "INFO:  " + response.ResponseInfo + "\r\n";

            //ResponseLog is optional, so check for null
            if (response.ResponseLog != null)
                newLogText += response.ResponseLog.Replace("\n", "\r\n");
            //ResponseData is optional
            if (response.ResponseData != null)
                newLogText += response.ResponseData.Replace("\n", "\r\n");

            //tack on the new info to the top of the log window
            if (newLogText != "")
                newLogText += "\r\n\r\n++++++++++++++++++++++++++++++\r\n";

            LogWindow.Text = newLogText+currentLogWindowText+"\r\n";
        }
예제 #23
0
            /////////////////////////////////////////////////////
            //                                                 //
            // CleanFileFindings()                             //
            //                                                 //
            /////////////////////////////////////////////////////
            //Description:  deletes any files from disk if indicated.
            //Returns:      nothing; side-effect on passed-in results
            /////////////////////////////////////////////////////
            internal bool CleanFileFindings(ref CwXML.FileSignatureMatch[] FileSignatureMatches)
            {
                //the line below is added for compatibility when calling this function
                //over remote channels from the admin console
                if (AgentScanLog == null)
                    AgentScanLog = new StringBuilder();

                int count = 0;
                //
                //clean files as directed for file sig matches
                //
                foreach (CwXML.FileSignatureMatch match in FileSignatureMatches)
                {
                    string action = match.Action;

                    //try to delete the file
                    if (action == "Delete if found")
                    {
                        try
                        {
                            File.Delete(match.FullPath);
                        }
                        catch(Exception ex)
                        {
                            string t = ex.Message;
                            AgentScanLog.AppendLine("CLEAN:  Failed to remove file '"+match.FullPath+"'!");
                            FileSignatureMatches[count].ActionSuccessful = false;
                            count++;
                            continue;
                        }
                        FileSignatureMatches[count].ActionSuccessful = true;
                    }
                    count++;
                }

                return true;
            }
예제 #24
0
            /////////////////////////////////////////////////////
            //                                                 //
            // ScanForFileSignatures()                         //
            //                                                 //
            /////////////////////////////////////////////////////
            //Description:  Scans all logical drives for the given
            //              file signatures.
            //Returns:      nothing; side-effect on passed-in results
            /////////////////////////////////////////////////////
            internal void ScanForFileSignatures(CwXML.FileSignature[] FileSignatures, ref CwXML.FileSignatureMatch[] matches)
            {
                //get list of logical drives
                string[] drives = Environment.GetLogicalDrives();
                int numMalware=0;
                ArrayList matchList;
                ArrayList matchRecordsList=new ArrayList();

                AgentScanLog.AppendLine("SCAN:  Drives:  " + string.Join(",", drives));

                //-----------------------------------------------------------
                //      SCAN DISKS FOR FILE SIGNATURE MATCHES
                //-----------------------------------------------------------
                //loop through all our disk drives - returns it as C:\, D:\, F:\
                foreach (string drive in drives)
                {
                    AgentScanLog.AppendLine("SCAN:  Scanning " + drive + "...");

                    //loop through all signatures
                    foreach (CwXML.FileSignature signature in FileSignatures)
                    {
                        //perform search based on parameters above (some may be empty)
                        try
                        {
                            matchList = FileSearch(drive, signature.FileName, signature.FileHash, signature.FileHashType, signature.FileSize.ToString(), signature.FilePEHeaderSignature);
                        }
                        catch (Exception ex)
                        {
                            AgentScanLog.AppendLine("SCAN:  Failed to scan drive:  " + ex.Message);
                            break; //dont continue scanning for signatures on this drive.
                        }

                        AgentScanLog.AppendLine("SCAN:  There were "+matchList.Count.ToString()+" matches for this signature.");

                        //if we got a match, add those results to our array of arrays
                        if (matchList.Count > 0)
                        {
                            AgentScanLog.AppendLine("file search matches:  " + string.Join(",", (string[])matchList.ToArray(typeof(string))));

                            foreach (string fullPathToMatch in matchList)
                            {
                                //get info about this file
                                FileInfo f;
                                try
                                {
                                    f = new FileInfo(fullPathToMatch);
                                }
                                catch (Exception ex)
                                {
                                    AgentScanLog.AppendLine("SCAN:  Error querying file '" + fullPathToMatch + "':  " + ex.Message);
                                    continue;
                                }

                                CwXML.FileSignatureMatch fm = new CwXML.FileSignatureMatch();
                                fm.FileName = f.Name;
                                fm.FileSize = f.Length;
                                fm.FullPath = f.FullName;
                                //if no file hash was specified in the signature, create one now (MD5 only)
                                if (signature.FileHash == "")
                                {
                                    fm.FileHash = GetMD5HashOfFile(f.FullName);
                                    fm.FileHashType = "MD5";
                                }
                                else
                                {
                                    fm.FileHash = signature.FileHash;
                                    fm.FileHashType = signature.FileHashType;
                                }
                                //if PE header signature was given in signature, save it
                                if (signature.FilePEHeaderSignature != "")
                                    fm.FilePEHeaderSignature = signature.FilePEHeaderSignature;
                                fm.Action = signature.Action;
                                //get various file attribs
                                fm.FileLastAccessDate = f.LastAccessTime.ToLongDateString();
                                fm.FileLastModifiedDate = f.LastWriteTime.ToLongDateString();
                                fm.FileCreationDate = f.CreationTime.ToLongDateString();

                                //add it to list
                                matchRecordsList.Add(fm);
                            }
                            numMalware++;
                        }
                    }

                    AgentScanLog.AppendLine("SCAN:  Scan of " + drive + " complete (" + numMalware.ToString() + " malicious files found).");
                    numMalware = 0;
                }

                //we've scanned all disks for all file signatures.
                //if we got matches, create a match record for them
                if (matchRecordsList.Count > 0)
                {
                    matches = new CwXML.FileSignatureMatch[matchRecordsList.Count];
                    int i = 0;

                    foreach (CwXML.FileSignatureMatch matchRecord in matchRecordsList)
                    {
                        matches[i] = new CwXML.FileSignatureMatch();
                        matches[i] = matchRecord;
                        i++;
                    }
                }
                else
                    matches = new CwXML.FileSignatureMatch[0];
            }