예제 #1
0
        public static Dictionary <string, ulong> YaraScanFile(string fileName)
        {
            Dictionary <string, ulong> beaconScanMatches = new Dictionary <string, ulong>();

            using (var ctx = new YaraContext())
            {
                Rules rules = null;

                try
                {
                    using (Compiler compiler = new Compiler())
                    {
                        // Retrieve YARA rules from YaraRules static class and compile them for scanning
                        foreach (string rule in YaraRules.meterpreterRules)
                        {
                            compiler.AddRuleString(rule);
                        }

                        compiler.AddRuleString(YaraRules.cobaltStrikeRule);

                        rules = compiler.GetRules();
                    }

                    // Scanner and ScanResults do not need to be disposed.
                    var scanner = new Scanner();
                    var results = scanner.ScanFile(fileName, rules);

                    foreach (ScanResult result in results)
                    {
                        if (result.MatchingRule.Identifier.Contains("CobaltStrike"))
                        {
                            // Get Version 3 match - find the first occurrence of the config string
                            if (result.Matches.ContainsKey(v3))
                            {
                                beaconScanMatches.Add(v3, result.Matches[v3][0].Offset);
                            }

                            // Get Version 4 match
                            if (result.Matches.ContainsKey(v4))
                            {
                                beaconScanMatches.Add(v4, result.Matches[v4][0].Offset);
                            }
                        }
                    }
                }
                finally
                {
                    // Rules and Compiler objects must be disposed.
                    if (rules != null)
                    {
                        rules.Dispose();
                    }
                }

                return(beaconScanMatches);
            }
        }
예제 #2
0
        /// <summary>
        /// Perform YARA scan on process memory to detect meterpreter or Cobalt Strike payloads.
        /// </summary>
        /// <param name="processBytes">Byte array of target process to be scanned</param>
        public static Dictionary <string, ulong> YaraScanBytes(byte[] processBytes)
        {
            Dictionary <string, ulong> beaconScanMatches = new Dictionary <string, ulong>();

            using (var ctx = new YaraContext())
            {
                Rules rules = null;

                try
                {
                    using (Compiler compiler = new Compiler())
                    {
                        // Retrieve YARA rules from YaraRules static class and compile them for scanning
                        foreach (string rule in YaraRules.meterpreterRules)
                        {
                            compiler.AddRuleString(rule);
                        }

                        compiler.AddRuleString(YaraRules.cobaltStrikeRule);

                        rules = compiler.GetRules();
                    }

                    // Perform scan on process memory byte[]
                    Scanner scanner = new Scanner();
                    var     results = scanner.ScanMemory(processBytes, rules);

                    // Check for rule matches in process bytes
                    foreach (ScanResult result in results)
                    {
                        if (result.MatchingRule.Identifier.Contains("CobaltStrike"))
                        {
                            // Get Version 3 match - find the first occurrence of the config string
                            if (result.Matches.ContainsKey(v3))
                            {
                                beaconScanMatches.Add(v3, result.Matches[v3][0].Offset);
                            }

                            // Get Version 4 match
                            if (result.Matches.ContainsKey(v4))
                            {
                                beaconScanMatches.Add(v4, result.Matches[v4][0].Offset);
                            }
                        }
                    }
                }
                finally
                {
                    if (rules != null)
                    {
                        rules.Dispose();
                    }
                }
                return(beaconScanMatches);
            }
        }
예제 #3
0
        public void CheckMemoryNotMatchTest()
        {
            // Initialize yara context
            using (YaraContext ctx = new YaraContext())
            {
                // Compile yara rules
                CompiledRules rules = null;

                using (var compiler = new Compiler())
                {
                    compiler.AddRuleString("rule foo: bar {strings: $a = \"nml\" condition: $a}");

                    rules = compiler.Compile();
                }

                if (rules != null)
                {
                    // Initialize the scanner
                    var scanner = new Scanner();

                    Encoding encoding = Encoding.ASCII;

                    byte[] buffer = encoding.GetBytes("abcdefgjiklmnoprstuvwxyz");

                    List <ScanResult> scanResult = scanner.ScanMemory(ref buffer, rules);

                    Assert.True(scanResult.Count == 0);
                }
            }
        }
예제 #4
0
        public void CheckStringNotMatchTest()
        {
            // Initialize yara context
            using (YaraContext ctx = new YaraContext())
            {
                // Compile yara rules
                CompiledRules rules = null;

                using (var compiler = new Compiler())
                {
                    compiler.AddRuleString("rule foo: bar {strings: $a = \"nml\" condition: $a}");

                    rules = compiler.Compile();
                }

                if (rules != null)
                {
                    // Initialize the scanner
                    var scanner = new Scanner();
                    List <ScanResult> scanResult = scanner.ScanString("abcdefgjiklmnoprstuvwxyz", rules);

                    Assert.True(scanResult.Count == 0);
                }
            }
        }
예제 #5
0
        public void CheckExternalVariableRuleTest()
        {
            // Initialize yara context
            using (YaraContext ctx = new YaraContext())
            {
                using (var compiler = new Compiler())
                {
                    //must declare this or the compiler will complain it doesn't exist when a rule references it
                    compiler.DeclareExternalStringVariable("filename");

                    //declare rule with an external variable available
                    compiler.AddRuleString("rule foo: bar {strings: $a = \"lmn\" condition: $a and filename matches /\\.txt$/is}");
                    CompiledRules compiledRules = compiler.Compile();

                    Assert.True(compiledRules.RuleCount == 1);

                    Encoding encoding = Encoding.ASCII;
                    byte[]   buffer   = encoding.GetBytes("abcdefgjiklmnoprstuvwxyz");

                    // Initialize a customscanner we can add variables to
                    var scanner = new CustomScanner(compiledRules);

                    ExternalVariables externalVariables = new ExternalVariables();
                    externalVariables.StringVariables.Add("filename", "Alphabet.txt");

                    List <ScanResult> compiledScanResults = scanner.ScanMemory(ref buffer, externalVariables);

                    Assert.True(compiledScanResults.Count == 1);
                    Assert.Equal("foo", compiledScanResults[0].MatchingRule.Identifier);

                    //release before falling out of the yara context
                    scanner.Release();
                }
            }
        }
예제 #6
0
        /// <summary>
        /// Perform YARA scan on process memory to detect meterpreter or Cobalt Strike payloads.
        /// </summary>
        /// <param name="processBytes">Byte array of target process to be scanned</param>
        public static List <BeaconMatch> YaraScanBytes(byte[] processBytes)
        {
            List <BeaconMatch> beaconScanMatches = new List <BeaconMatch>();

            using (var ctx = new YaraContext())
            {
                Rules rules = null;

                try
                {
                    using (Compiler compiler = new Compiler())
                    {
                        // Retrieve YARA rules from YaraRules static class and compile them for scanning

                        /*
                         * foreach (string rule in YaraRules.meterpreterRules)
                         * {
                         *  compiler.AddRuleString(rule);
                         * }
                         */

                        compiler.AddRuleString(YaraRules.cobaltStrikeRule);

                        rules = compiler.GetRules();
                    }

                    // Perform scan on process memory byte[]
                    Scanner scanner = new Scanner();
                    var     results = scanner.ScanMemory(processBytes, rules);

                    beaconScanMatches = ParseScanResults(results);
                }
                finally
                {
                    if (rules != null)
                    {
                        rules.Dispose();
                    }
                }
                return(beaconScanMatches);
            }
        }
예제 #7
0
        public void CheckSaveLoadRuleTest()
        {
            // Initialize yara context
            using (YaraContext ctx = new YaraContext())
            {
                using (var compiler = new Compiler())
                {
                    compiler.AddRuleString("rule foo: bar {strings: $a = \"lmn\" condition: $a}");
                    CompiledRules compiledRules = compiler.Compile();
                    Assert.True(compiledRules.RuleCount == 1);

                    Encoding encoding = Encoding.ASCII;
                    byte[]   buffer   = encoding.GetBytes("abcdefgjiklmnoprstuvwxyz");

                    // Initialize the scanner
                    var scanner = new Scanner();

                    List <ScanResult> compiledScanResults = scanner.ScanMemory(ref buffer, compiledRules);
                    Assert.True(compiledScanResults.Count == 1);
                    Assert.Equal("foo", compiledScanResults[0].MatchingRule.Identifier);


                    //save the rule to disk
                    string tempfile = System.IO.Path.GetTempFileName();
                    bool   saved    = compiledRules.Save(tempfile);
                    Assert.True(saved);

                    //load the saved rule to a new ruleset
                    CompiledRules loadedRules = new CompiledRules(tempfile);

                    List <ScanResult> loadedScanResults = scanner.ScanMemory(ref buffer, loadedRules);

                    Assert.True(loadedScanResults.Count == 1);
                    Assert.Equal("foo", loadedScanResults[0].MatchingRule.Identifier);

                    System.IO.File.Delete(tempfile);
                }
            }
        }
예제 #8
0
        public void CheckIterateRulesTest()
        {
            string ruleText = @"rule foo: bar {
                meta:
                    bool_meta = true
                    int_meta = 10
                    string_meta = ""what a long, drawn-out thing this is!""
                strings:
                    $a = ""nml""
                condition:
                    $a
                }";

            // Initialize yara context
            using (YaraContext ctx = new YaraContext())
            {
                // Compile yara rules
                CompiledRules rules = null;

                using (var compiler = new Compiler())
                {
                    compiler.AddRuleString(ruleText);

                    rules = compiler.Compile();
                }

                if (rules != null)
                {
                    var rule = rules.Rules.ToList()[0];
                    Assert.NotEmpty(rules.Rules);
                    Assert.Equal("foo", rule.Identifier);
                    Assert.Equal("bar", rule.Tags[0]);
                    Assert.Equal(true, rule.Metas["bool_meta"]);
                    Assert.Equal((long)10, rule.Metas["int_meta"]);
                    Assert.Equal("what a long, drawn-out thing this is!", rule.Metas["string_meta"]);
                }
            }
        }
예제 #9
0
        /// <summary>
        /// Compile all yara rules in the directory to memory and disk signature blobs, containing the respective rules enabled in the settings
        /// </summary>
        /// <param name="rulesDir">Directory containing directories full of yara rules</param>
        /// <returns>Paths to the sucessfully created rules files</returns>
        private string[] RecompileRules(string rulesDir)
        {
            List <string>      savedrules = new List <string>();
            EnumerationOptions opts       = new EnumerationOptions()
            {
                MatchCasing           = MatchCasing.CaseInsensitive,
                IgnoreInaccessible    = true,
                RecurseSubdirectories = true
            };


            List <string> ruleFiles = Directory.GetFiles(rulesDir, "*.yar*", opts).ToList();

            ruleFiles.AddRange(Directory.GetFiles(rulesDir, "*.txt", opts).ToList());


            // Compile list of yara rules
            var AllRulesCompiler = new Compiler();

            while (true)
            {
                bool failed = false;
                foreach (string rulespath in ruleFiles)
                {
                    string contents = File.ReadAllText(rulespath);
                    if (contents.Contains("rule", StringComparison.OrdinalIgnoreCase) && contents.Contains("condition", StringComparison.OrdinalIgnoreCase))
                    {
                        try
                        {
                            //if (GlobalConfig.SignatureScanLimits.TryGetValue())
                            AllRulesCompiler.AddRuleString(contents);
                        }
                        catch (Exception e)
                        {
                            //a bad rule causes an exeption in compilation and cant be removed, so we have to remove the whole file and recompile all from scratch
                            failed = true;
                            Logging.RecordException($"Failed to compile Yara rule in file {rulespath}: {e.Message}", e);
                            ruleFiles.Remove(rulespath);
                            if (!ruleFiles.Any())
                            {
                                Logging.RecordLogEvent($"No valid YARA rules found in directory {rulesDir}", Logging.LogFilterType.Error);
                                return(savedrules.ToArray());
                            }
                            AllRulesCompiler.Dispose();
                            AllRulesCompiler = new Compiler();
                            break;
                        }
                    }
                }
                if (!failed)
                {
                    break;
                }
            }



            //compilation will fail if the variable used by a rule isn't declared at compile time
            AllRulesCompiler.DeclareExternalStringVariable("filename");
            AllRulesCompiler.DeclareExternalStringVariable("extension");
            AllRulesCompiler.DeclareExternalStringVariable("filepath");
            AllRulesCompiler.DeclareExternalStringVariable("filetype");
            loadedRules = AllRulesCompiler.Compile();
            AllRulesCompiler.Dispose();

            //memoryScanRules = compiler.Compile();
            // fileScanRules = compiler.Compile();
            //compiler.Dispose();

            if (loadedRules.RuleCount > 0)
            {
                string diskpath = Path.Combine(rulesDir, "precompiled_rules.yarac");
                if (File.Exists(diskpath))
                {
                    File.Delete(diskpath);
                }

                if (loadedRules.Save(diskpath))
                {
                    savedrules.Add(diskpath);
                }
            }

            return(savedrules.ToArray());
        }
예제 #10
0
        public static List <BeaconMatch> YaraScanFile(string fileName, bool verbose)
        {
            List <BeaconMatch> beaconScanMatches = new List <BeaconMatch>();

            using (var ctx = new YaraContext())
            {
                Rules rules = null;

                try
                {
                    using (Compiler compiler = new Compiler())
                    {
                        // Retrieve YARA rules from YaraRules static class and compile them for scanning
                        foreach (string rule in YaraRules.meterpreterRules)
                        {
                            compiler.AddRuleString(rule);
                        }

                        compiler.AddRuleString(YaraRules.cobaltStrikeRule);

                        rules = compiler.GetRules();
                    }

                    // Scanner and ScanResults do not need to be disposed.
                    var scanner = new Scanner();

                    List <ScanResult> results = new List <ScanResult>();

                    // If file size > 2GB, stream the file and use ScanMemory() on file chunks rather than reading the whole file via
                    if (new FileInfo(fileName).Length < Int32.MaxValue)
                    {
                        results.AddRange(scanner.ScanFile(fileName, rules));
                    }
                    else
                    {
                        using (FileStream fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read))
                        {
                            // Parse the file in 200MB chunks
                            int    chunkSize   = 1024 * 1024 * 200;
                            byte[] chunk       = new byte[chunkSize];
                            int    bytesRead   = 0;
                            long   bytesToRead = fileStream.Length;

                            while (bytesToRead != 0)
                            {
                                int n = fileStream.Read(chunk, 0, chunkSize);

                                if (n == 0)
                                {
                                    break;
                                }

                                // Yara scan the file chunk and add any results to the list
                                var scanResults = scanner.ScanMemory(chunk, rules);

                                // Because the file is being scanned in chunks, match offsets are based on the start of the chunk. Need to add
                                // previous bytes read to the current match offsets
                                if (scanResults.Count > 0)
                                {
                                    foreach (ScanResult result in scanResults)
                                    {
                                        if (result.MatchingRule.Identifier.Contains("CobaltStrike"))
                                        {
                                            foreach (string key in result.Matches.Keys)
                                            {
                                                result.Matches[key][0].Offset += (ulong)bytesRead;
                                            }
                                            results.Add(result);
                                        }
                                    }
                                }

                                bytesRead   += n;
                                bytesToRead -= n;

                                // Shitty progress update
                                if (verbose && bytesRead > 0 && bytesRead <= fileStream.Length)
                                {
                                    Console.Write($"\r\tScanned {bytesRead} bytes of {fileStream.Length} byte file...");
                                }
                            }
                        }
                        if (verbose)
                        {
                            Console.WriteLine($"\r\tFinished scanning file: {fileName}\t\t\t");
                        }
                    }

                    beaconScanMatches = ParseScanResults(results);
                }
                finally
                {
                    // Rules and Compiler objects must be disposed.
                    if (rules != null)
                    {
                        rules.Dispose();
                    }
                }

                return(beaconScanMatches);
            }
        }