private static void Main(string[] args) { Utility.PrintBanner(); string sysvolPolDir = ""; JObject domainGpos = new JObject(); // Ask the DC for GPO details if (args.Length == 0) { Console.WriteLine("Trying to figure out what AD domain we're working with."); string currentDomainString = Domain.GetCurrentDomain().ToString(); Console.WriteLine("Current AD Domain is: " + currentDomainString); sysvolPolDir = @"\\" + currentDomainString + @"\sysvol\" + currentDomainString + @"\Policies\"; Utility.DebugWrite("SysvolPolDir is " + sysvolPolDir); GlobalVar.OnlineChecks = true; } // or if the user gives a path argument, just look for policies in there if (args.Length == 1) { Console.WriteLine("OK, I trust you know where you're aiming me."); sysvolPolDir = args[0]; } Console.WriteLine("We gonna look at the policies in: " + sysvolPolDir); if (GlobalVar.OnlineChecks) { domainGpos = LDAPstuff.GetDomainGpos(); } string[] gpoPaths = Directory.GetDirectories(sysvolPolDir); // create a dict to put all our output goodies in. Dictionary <string, JObject> grouper2OutputDict = new Dictionary <string, JObject>(); foreach (var gpoPath in gpoPaths) { // create a dict to put the stuff we find for this GPO into. Dictionary <string, JObject> gpoResultDict = new Dictionary <string, JObject>(); // // Get the UID of the GPO from the file path. string[] splitPath = gpoPath.Split(Path.DirectorySeparatorChar); string gpoUid = splitPath[splitPath.Length - 1]; // Make a JObject for GPO metadata JObject gpoPropsJson = new JObject(); // If we're online and talking to the domain, just use that data if (GlobalVar.OnlineChecks) { JToken domainGpo = domainGpos[gpoUid]; gpoPropsJson = (JObject)JToken.FromObject(domainGpo); } // otherwise do what we can with what we have else { Dictionary <string, string> gpoPropsDict = new Dictionary <string, string>(); gpoPropsDict.Add("GPO UID", gpoUid); gpoPropsDict.Add("GPO Path", gpoPath); gpoPropsJson = (JObject)JToken.FromObject(gpoPropsDict); } // TODO (and put in GPOProps) // get the policy owner // get whether it's linked and where // get whether it's enabled // Get the paths for the machine policy and user policy dirs string machinePolPath = Path.Combine(gpoPath, "Machine"); string userPolPath = Path.Combine(gpoPath, "User"); // Process Inf and Xml Policy data for machine and user JObject machinePolInfResults = ProcessInf(machinePolPath); JObject userPolInfResults = ProcessInf(userPolPath); JObject machinePolGppResults = ProcessGpXml(machinePolPath); JObject userPolGppResults = ProcessGpXml(userPolPath); // Add all this crap into a dict gpoResultDict.Add("GPOProps", gpoPropsJson); //gpoResultDict.Add("Machine Policy from GPP XML files", machinePolGppResults); //gpoResultDict.Add("User Policy from GPP XML files", userPolGppResults); gpoResultDict.Add("Machine Policy from Inf files", machinePolInfResults); gpoResultDict.Add("User Policy from Inf files", userPolInfResults); // turn dict of data for this gpo into jobj JObject gpoResultJson = (JObject)JToken.FromObject(gpoResultDict); // put into final jobj grouper2OutputDict.Add(gpoPath, gpoResultJson); // TODO // Parse other inf sections: // System Access // Kerberos Policy // Event Audit // Registry Values // Registry Keys // Group Membership // Service General Setting // Parse XML files // Parse ini files // Grep scripts for creds. // File permissions for referenced files. } // Final output is finally happening finally here: Utility.DebugWrite("Final Output:"); JObject grouper2OutputJson = (JObject)JToken.FromObject(grouper2OutputDict); Console.WriteLine(""); Console.WriteLine(grouper2OutputJson); Console.WriteLine(""); Console.WriteLine("This"); Console.WriteLine(Utility.CanIWrite("C:\\temp\\thing.txt").ToString()); // wait for 'anykey' Console.ReadKey(); }
private static void Main(string[] args) { Utility.PrintBanner(); CommandLineParser.CommandLineParser parser = new CommandLineParser.CommandLineParser(); SwitchArgument debugArg = new SwitchArgument('d', "debug", "Enables debug mode. Will also show you the names of any categories of policies that Grouper saw but didn't have any means of processing. I eagerly await your pull request.", false); SwitchArgument offlineArg = new SwitchArgument('o', "offline", "Disables checks that require LDAP comms with a DC or SMB comms with file shares found in policy settings. Requires that you define a value for --sysvol.", false); ValueArgument <string> sysvolArg = new ValueArgument <string>('s', "sysvol", "Set the path to a domain SYSVOL directory."); ValueArgument <int> intlevArg = new ValueArgument <int>('i', "interestlevel", "The minimum interest level to display. i.e. findings with an interest level lower than x will not be seen in output. Defaults to 1, i.e. show everything except some extremely dull defaults. If you want to see those too, do -i 0."); //ValueArgument<string> domainArg = new ValueArgument<string>('d', "domain", "The domain to connect to. If not specified, connects to current user context domain."); //ValueArgument<string> usernameArg = new ValueArgument<string>('u', "username", "Username to authenticate as. SMB permissions checks will be run from this user's perspective."); //ValueArgument<string> passwordArg = new ValueArgument<string>('p', "password", "Password to use for authentication."); //parser.Arguments.Add(domainArg); //parser.Arguments.Add(usernameArg); //parser.Arguments.Add(passwordArg); parser.Arguments.Add(debugArg); parser.Arguments.Add(intlevArg); parser.Arguments.Add(sysvolArg); parser.Arguments.Add(offlineArg); // set a couple of defaults string sysvolPolDir = ""; GlobalVar.OnlineChecks = true; try { parser.ParseCommandLine(args); //parser.ShowParsedArguments(); if (debugArg.Parsed && debugArg.Value) { GlobalVar.DebugMode = true; } if (offlineArg.Parsed && offlineArg.Value && sysvolArg.Parsed) { // args config for valid offline run. GlobalVar.OnlineChecks = false; sysvolPolDir = sysvolArg.Value; } if (offlineArg.Parsed && offlineArg.Value && !sysvolArg.Parsed) { // handle someone trying to run in offline mode without giving a value for sysvol Console.WriteLine("Offline mode requires you to provide a value for -s, the path where Grouper2 can find the domain SYSVOL share, or a copy of it at least."); Environment.Exit(1); } if (intlevArg.Parsed) { // handle interest level parsing Console.WriteLine("Roger. Everything with an Interest Level lower than " + intlevArg.Value.ToString() + " is getting thrown on the floor."); GlobalVar.IntLevelToShow = intlevArg.Value; } else { GlobalVar.IntLevelToShow = 1; } if (sysvolArg.Parsed) { sysvolPolDir = sysvolArg.Value; } //if (domainArg.Parsed || usernameArg.Parsed || passwordArg.Parsed) //{ // Console.WriteLine("I haven't set up anything to handle the domain/password stuff yet, so it won't work"); // Environment.Exit(1); //} } catch (CommandLineException e) { Console.WriteLine(e.Message); } JObject domainGpos = new JObject(); // Ask the DC for GPO details if (GlobalVar.OnlineChecks) { Console.WriteLine("Trying to figure out what AD domain we're working with."); string currentDomainString = Domain.GetCurrentDomain().ToString(); Console.WriteLine("Current AD Domain is: " + currentDomainString); if (sysvolPolDir == "") { sysvolPolDir = @"\\" + currentDomainString + @"\sysvol\" + currentDomainString + @"\Policies\"; } } Console.WriteLine("Targeting SYSVOL at: " + sysvolPolDir); // if we're online, get a bunch of metadata about the GPOs via LDAP if (GlobalVar.OnlineChecks) { domainGpos = LDAPstuff.GetDomainGpos(); } string[] gpoPaths = new string[0]; try { gpoPaths = Directory.GetDirectories(sysvolPolDir); } catch { Console.WriteLine("Sysvol path is broken. You should fix it."); Environment.Exit(1); } // create a JObject to put all our output goodies in. JObject grouper2Output = new JObject(); // so for each uid directory (including ones with that dumb broken domain replication condition) // we're going to gather up all our goodies and put them into that dict we just created. foreach (var gpoPath in gpoPaths) { // create a dict to put the stuff we find for this GPO into. JObject gpoResult = new JObject(); // Get the UID of the GPO from the file path. string[] splitPath = gpoPath.Split(Path.DirectorySeparatorChar); string gpoUid = splitPath[splitPath.Length - 1]; // Make a JObject for GPO metadata JObject gpoProps = new JObject(); // If we're online and talking to the domain, just use that data if (GlobalVar.OnlineChecks) { JToken domainGpo = domainGpos[gpoUid]; gpoProps = (JObject)JToken.FromObject(domainGpo); } // otherwise do what we can with what we have else { gpoProps = new JObject() { { "gpoUID", gpoUid }, { "gpoPath", gpoPath } }; } // TODO (and put in GPOProps) // get the policy owner // get whether it's linked and where // get whether it's enabled // Add all this crap into a dict, if we found anything of interest. gpoResult.Add("GPOProps", gpoProps); // turn dict of data for this gpo into jobj JObject gpoResultJson = (JObject)JToken.FromObject(gpoResult); // if I were smarter I would have done this shit with the machine and user dirs inside the Process methods instead of calling each one twice out here. // @liamosaur you reckon you can see how to clean it up after the fact? // Get the paths for the machine policy and user policy dirs string machinePolPath = Path.Combine(gpoPath, "Machine"); string userPolPath = Path.Combine(gpoPath, "User"); // Process Inf and Xml Policy data for machine and user JArray machinePolInfResults = ProcessInf(machinePolPath); JArray userPolInfResults = ProcessInf(userPolPath); JArray machinePolGppResults = ProcessGpXml(machinePolPath); JArray userPolGppResults = ProcessGpXml(userPolPath); JArray machinePolScriptResults = ProcessScriptsIni(machinePolPath); JArray userPolScriptResults = ProcessScriptsIni(userPolPath); // add all our findings to a JArray in what seems a very inefficient manner. JArray userFindings = new JArray(); JArray machineFindings = new JArray(); if (machinePolGppResults != null && machinePolGppResults.HasValues) { foreach (JObject finding in machinePolGppResults) { machineFindings.Add(finding); } } if (userPolGppResults != null && userPolGppResults.HasValues) { foreach (JObject finding in userPolGppResults) { userFindings.Add(finding); } } if (machinePolGppResults != null && machinePolInfResults.HasValues) { foreach (JObject finding in machinePolInfResults) { machineFindings.Add(finding); } } if (userPolInfResults != null && userPolInfResults.HasValues) { foreach (JObject finding in userPolInfResults) { userFindings.Add(finding); } } if (machinePolScriptResults != null && machinePolScriptResults.HasValues) { foreach (JObject finding in machinePolScriptResults) { machineFindings.Add(finding); } } if (userPolScriptResults != null && userPolScriptResults.HasValues) { foreach (JObject finding in userPolScriptResults) { userFindings.Add(finding); } } // if there are any Findings, add it to the final output. if (userFindings.HasValues) { JProperty userFindingsJProp = new JProperty("Findings in User Policy", userFindings); gpoResultJson.Add(userFindingsJProp); } if (machineFindings.HasValues) { JProperty machineFindingsJProp = new JProperty("Findings in Machine Policy", machineFindings); gpoResultJson.Add(machineFindingsJProp); } // put into final output if (userFindings.HasValues || machineFindings.HasValues) { grouper2Output.Add(gpoPath, gpoResultJson); } } // Final output is finally happening finally here: Console.WriteLine("RESULT!"); Console.WriteLine(""); Console.WriteLine(grouper2Output); Console.WriteLine(""); // wait for 'anykey' Console.ReadKey(); }