private static Options ParseImpl(string[] args) { BlockingMq Mq = BlockingMq.GetMq(); Mq.Info("Parsing args..."); Options parsedConfig = new Options(); // define args ValueArgument <string> configFileArg = new ValueArgument <string>('z', "config", "Path to a .toml config file. Run with \'generate\' to puke a sample config file into the working directory."); ValueArgument <string> outFileArg = new ValueArgument <string>('o', "outfile", "Path for output file. You probably want this if you're not using -s."); ValueArgument <string> verboseArg = new ValueArgument <string>('v', "verbosity", "Controls verbosity level, options are Trace (most verbose), Debug (less verbose), Info (less verbose still, default), and Data (results only). e.g '-v debug' "); SwitchArgument helpArg = new SwitchArgument('h', "help", "Displays this help.", false); SwitchArgument stdOutArg = new SwitchArgument('s', "stdout", "Enables outputting results to stdout as soon as they're found. You probably want this if you're not using -o.", false); ValueArgument <string> snaffleArg = new ValueArgument <string>('m', "snaffle", "Enables and assigns an output dir for Snaffler to automatically snaffle a copy of any found files."); ValueArgument <long> snaffleSizeArg = new ValueArgument <long>('l', "snafflesize", "Maximum size of file to snaffle, in bytes. Defaults to 10MB."); //var fileHuntArg = new SwitchArgument('f', "filehuntoff", // "Disables file discovery, will only perform computer and share discovery.", false); ValueArgument <string> dirTargetArg = new ValueArgument <string>('i', "dirtarget", "Disables computer and share discovery, requires a path to a directory in which to perform file discovery."); ValueArgument <string> domainArg = new ValueArgument <string>('d', "domain", "Domain to search for computers to search for shares on to search for files in. Easy."); ValueArgument <string> domainControllerArg = new ValueArgument <string>('c', "domaincontroller", "Domain controller to query for a list of domain computers."); ValueArgument <long> maxGrepSizeArg = new ValueArgument <long>('r', "maxgrepsize", "The maximum size file (in bytes) to search inside for interesting strings. Defaults to 500k."); ValueArgument <int> grepContextArg = new ValueArgument <int>('j', "grepcontext", "How many bytes of context either side of found strings in files to show, e.g. -j 200"); SwitchArgument domainUserArg = new SwitchArgument('u', "domainusers", "Makes Snaffler grab a list of interesting-looking accounts from the domain and uses them in searches.", false); // list of letters i haven't used yet: abefgknpqwxy CommandLineParser.CommandLineParser parser = new CommandLineParser.CommandLineParser(); parser.Arguments.Add(configFileArg); parser.Arguments.Add(outFileArg); parser.Arguments.Add(helpArg); parser.Arguments.Add(stdOutArg); parser.Arguments.Add(snaffleArg); parser.Arguments.Add(snaffleSizeArg); parser.Arguments.Add(dirTargetArg); parser.Arguments.Add(domainArg); parser.Arguments.Add(verboseArg); parser.Arguments.Add(domainControllerArg); parser.Arguments.Add(maxGrepSizeArg); parser.Arguments.Add(grepContextArg); parser.Arguments.Add(domainUserArg); // extra check to handle builtin behaviour from cmd line arg parser if ((args.Contains("--help") || args.Contains("/?") || args.Contains("help") || args.Contains("-h") || args.Length == 0)) { parser.ShowUsage(); Environment.Exit(0); } TomlSettings settings = TomlSettings.Create(cfg => cfg .ConfigureType <LogLevel>(tc => tc.WithConversionFor <TomlString>(conv => conv .FromToml(s => (LogLevel)Enum.Parse(typeof(LogLevel), s.Value, ignoreCase: true)) .ToToml(e => e.ToString())))); try { parser.ParseCommandLine(args); if (configFileArg.Parsed) { if (!configFileArg.Value.Equals("generate")) { string configFile = configFileArg.Value; parsedConfig = Toml.ReadFile <Options>(configFile, settings); parsedConfig.PrepareClassifiers(); Mq.Info("Read config file from " + configFile); return(parsedConfig); } } if (parsedConfig.ClassifierRules.Count <= 0) { parsedConfig.BuildDefaultClassifiers(); } // get the args into our config // output args if (outFileArg.Parsed && (!String.IsNullOrEmpty(outFileArg.Value))) { parsedConfig.LogToFile = true; parsedConfig.LogFilePath = outFileArg.Value; Mq.Degub("Logging to file at " + parsedConfig.LogFilePath); } // Set loglevel. if (verboseArg.Parsed) { parsedConfig.LogLevelString = verboseArg.Value; Mq.Degub("Requested verbosity level: " + parsedConfig.LogLevelString); } // if enabled, display findings to the console parsedConfig.LogToConsole = stdOutArg.Parsed; Mq.Degub("Enabled logging to stdout."); // args that tell us about targeting if ((domainArg.Parsed) && (!String.IsNullOrEmpty(domainArg.Value))) { parsedConfig.TargetDomain = domainArg.Value; Mq.Degub("Target domain is " + domainArg.Value); } if ((domainControllerArg.Parsed) && (!String.IsNullOrEmpty(domainControllerArg.Value))) { parsedConfig.TargetDc = domainControllerArg.Value; Mq.Degub("Target DC is " + domainControllerArg.Value); } if (domainUserArg.Parsed) { parsedConfig.DomainUserRules = true; Mq.Degub("Enabled use of domain user accounts in rules."); } if (dirTargetArg.Parsed) { parsedConfig.ShareFinderEnabled = false; parsedConfig.PathTargets = new string[] { dirTargetArg.Value }; Mq.Degub("Disabled finding shares."); Mq.Degub("Target path is " + dirTargetArg.Value); } if (maxGrepSizeArg.Parsed) { parsedConfig.MaxSizeToGrep = maxGrepSizeArg.Value; Mq.Degub("We won't bother looking inside files if they're bigger than " + parsedConfig.MaxSizeToGrep + " bytes"); } if (snaffleArg.Parsed) { parsedConfig.SnafflePath = snaffleArg.Value; } if (snaffleSizeArg.Parsed) { parsedConfig.MaxSizeToSnaffle = snaffleSizeArg.Value; } // how many bytes if (grepContextArg.Parsed) { parsedConfig.MatchContextBytes = grepContextArg.Value; Mq.Degub( "We'll show you " + grepContextArg.Value + " bytes of context around matches inside files."); } // if enabled, grab a copy of files that we like. if (snaffleArg.Parsed) { if (snaffleArg.Value.Length <= 0) { Mq.Error("-m or -mirror arg requires a path value."); throw new ArgumentException("Invalid argument combination."); } parsedConfig.Snaffle = true; parsedConfig.SnafflePath = snaffleArg.Value.TrimEnd('\\'); Mq.Degub("Mirroring matched files to path " + parsedConfig.SnafflePath); } if (!parsedConfig.LogToConsole && !parsedConfig.LogToFile) { Mq.Error( "\nYou didn't enable output to file or to the console so you won't see any results or debugs or anything. Your l0ss."); throw new ArgumentException("Pointless argument combination."); } if (configFileArg.Parsed) { if (configFileArg.Value.Equals("generate")) { Toml.WriteFile(parsedConfig, ".\\default.toml", settings); Mq.Info("Wrote default config values to .\\default.toml"); Mq.Terminate(); } } parsedConfig.PrepareClassifiers(); } catch (Exception e) { Mq.Error(e.ToString()); throw; } return(parsedConfig); }