/// <summary> /// Get Cobalt Strike Configurations from a file and output their contents to the console . /// </summary> /// <param name="fileName">Name of memory/dump file to be scanned for Cobalt Strike beacons</param> private static void GetBeaconsFromFile(string fileName) { OutputMessageToConsole(LogLevel.Info, $"Scanning file: {fileName}"); List <Beacon> beacons = new List <Beacon>(); if (File.Exists(fileName)) { // Check the size of the file. If > 500MB, and notify that scanning will take time var fileSize = new FileInfo(fileName).Length; if (fileSize > Int32.MaxValue) { OutputMessageToConsole(LogLevel.Warn, $"\tFile is large: {fileSize / (1024 * 1024)} MB. Scanning will be slow."); } // Yara scan the file and return any matches List <BeaconMatch> beaconMatches = CobaltStrikeScan.YaraScanFile(fileName, opts.Verbose); // Extract config bytes at each match offset and parse the beacon config from them if (beaconMatches.Count > 0) { if (opts.Verbose) { OutputMessageToConsole(LogLevel.Info, $"\t{beaconMatches.Count} Signature(s) detected in file. Attempting to extract and parse config...\n"); } foreach (BeaconMatch match in beaconMatches) { try { byte[] beaconConfigBytes = new byte[4096]; // Get a byte array from the offset of the file with beacon matches to avoid cases // where the file is too big to read in to a File object using (FileStream fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read)) { fileStream.Seek((long)match.Offset, SeekOrigin.Begin); fileStream.Read(beaconConfigBytes, 0, 4096); } match.Offset = 0; beacons.Add(GetBeaconFromYaraScan(match, beaconConfigBytes)); } catch (System.IO.IOException) { /* * if (opts.Verbose) * { * OutputMessageToConsole(LogLevel.Error, $"Error extracting signatured data from file at offset: {match.Offset}"); * } */ } } if (beacons.Count > 0) { foreach (Beacon beacon in beacons) { if (beacon.isValidBeacon()) { OutputMessageToConsole(LogLevel.Success, $"Cobalt Strike Beacon Configuration\n"); beacon.OutputToConsole(); } } } else { OutputBeaconNotFoundMessage(); } } else { OutputBeaconNotFoundMessage(); } } else { OutputMessageToConsole(LogLevel.Error, $"File doesn't exist: {fileName}\nExiting..."); System.Environment.Exit(1); } }
static void Main(string[] args) { //Parse command line arguments CommandLineOptions opts = new CommandLineOptions(); var result = Parser.Default.ParseArguments <CommandLineOptions>(args).WithParsed(parsed => opts = parsed); var title = new HeadingInfo("CobaltStrikeScan"); // Option Processes -p if (opts.Processes) { Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("Scanning processes for injected threads"); Console.ResetColor(); List <InjectedThread> injectedThreads = GetInjectedThreads.GetInjectedThreads.InjectedThreads(); foreach (InjectedThread injectedThread in injectedThreads) { // Output Thread details to console OutputInjectedThreadToConsole(injectedThread, opts.Verbose); // Check if option set for dumping process memory if (opts.Dump) { injectedThread.WriteBytesToFile(); } // Scan process memory for injected thread Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("Scanning injected thread for CobaltStrike beacon"); Console.ResetColor(); Dictionary <string, ulong> beaconMatchOffsets = CobaltStrikeScan.YaraScanBytes(injectedThread.ProcessBytes); if (beaconMatchOffsets.Count > 0) { Beacon beacon = GetBeaconFromYaraScan(beaconMatchOffsets, injectedThread.ProcessBytes); if (beacon != null) { beacon.OutputToConsole(); } } else { Console.WriteLine("Couldn't find CobaltStrike beacon in injected thread"); } } } // User supplied File option -f else if (!string.IsNullOrEmpty(opts.File)) { if (File.Exists(opts.File)) { Dictionary <string, ulong> beaconMatchOffsets = CobaltStrikeScan.YaraScanFile(opts.File); if (beaconMatchOffsets.Count > 0) { byte[] fileBytes = File.ReadAllBytes(opts.File); Beacon beacon = GetBeaconFromYaraScan(beaconMatchOffsets, fileBytes); if (beacon != null) { beacon.OutputToConsole(); } } else { Console.WriteLine("Couldn't find CobaltStrike beacon in file"); } } else { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine($"File doesn't exist: {opts.File}\nExiting..."); Console.ResetColor(); System.Environment.Exit(1); } } else if (opts.InjectedThreads) { Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("Scanning processes for injected threads\n"); Console.ResetColor(); List <InjectedThread> injectedThreads = GetInjectedThreads.GetInjectedThreads.InjectedThreads(); foreach (InjectedThread injectedThread in injectedThreads) { // Output Thread details to console OutputInjectedThreadToConsole(injectedThread, opts.Verbose); // Check if option set for dumping process memory if (opts.Dump) { injectedThread.WriteBytesToFile(); } } } else if (opts.Help) { Console.WriteLine(HelpText.AutoBuild(result, h => h, e => e)); } else { Console.WriteLine(HelpText.AutoBuild(result, h => h, e => e)); } }