Exemplo n.º 1
0
        public static void Main(string[] args)
        {
            if (args == null)
            {
                throw new ArgumentNullException(nameof(args));
            }

            var options = new Options();

            if (!Parser.Default.ParseArguments(args, options))
            {
                return;
            }

            if (options.Debug)
            {
                Console.WriteLine("Debug Mode activated!");
                options.Threads = 1;
            }

            if (options.MaxLoopTime != null && options.CollectMethod.Equals(SessionLoop))
            {
                var regex     = new Regex("[0-9]+[smdh]");
                var matches   = regex.Matches(options.MaxLoopTime);
                var numregex  = new Regex("[0-9]+");
                var timeregex = new Regex("[smdh]");
                if (matches.Count == 0)
                {
                    Console.WriteLine("LoopEndTime does not match required format");
                    return;
                }

                var now   = DateTime.Now;
                var drift = 0;
                foreach (var match in matches)
                {
                    var num  = int.Parse(numregex.Match(match.ToString()).Value);
                    var spec = timeregex.Match(match.ToString());

                    switch (spec.Value)
                    {
                    case "s":
                        now    = now.AddSeconds(num);
                        drift += num;
                        break;

                    case "m":
                        now    = now.AddMinutes(num);
                        drift += num * 60;
                        break;

                    case "h":
                        now    = now.AddHours(num);
                        drift += num * 60 * 60;
                        break;

                    case "d":
                        now    = now.AddDays(num);
                        drift += num * 60 * 60 * 24;
                        break;
                    }
                }

                options.LoopEnd = now;

                if (drift == 0)
                {
                    Console.WriteLine("LoopEndTime is zero! Specify a real value");
                    return;
                }
            }



            options.CurrentUser = WindowsIdentity.GetCurrent().Name.Split('\\')[1];
            var nowtime = DateTime.Now;

            Console.WriteLine($"Initializing BloodHound at {nowtime.ToShortTimeString()} on {nowtime.ToShortDateString()}");
            Cache.CreateInstance(options);
            Utils.CreateInstance(options);

            if (!Utils.CheckWritePrivs())
            {
                Console.WriteLine("Unable to write in chosen directory. Please check privs");
                return;
            }

            SessionHelpers.Init(options);
            LocalAdminHelpers.Init();
            GroupHelpers.Init();
            AclHelpers.Init();
            DomainTrustEnumeration.Init();
            ContainerHelpers.Init();

            if (options.Test != null)
            {
                Test.DoStuff(options.Test);
                return;
            }

            if (options.ComputerFile != null)
            {
                if (!File.Exists(options.ComputerFile))
                {
                    Console.WriteLine("Specified ComputerFile does not exist!");
                    return;
                }

                if (options.CollectMethod.Equals(Default))
                {
                    options.CollectMethod = ComputerOnly;
                    Console.WriteLine("ComputerFile detected with default enumeration. Switching to ComputerOnly collection method");
                }

                if (!(options.CollectMethod.Equals(Session) || options.CollectMethod.Equals(SessionLoop) ||
                      options.CollectMethod.Equals(LoggedOn) || options.CollectMethod.Equals(LocalGroup) ||
                      options.CollectMethod.Equals(ComputerOnly)))
                {
                    Console.WriteLine("ComputerFile can only be used with the following collection methods: ComputerOnly, Session, SessionLoop, LocalGroup, LoggedOn");
                    return;
                }
            }

            //Lets test our connection to LDAP before we do anything else
            try
            {
                using (var conn = Utils.Instance.GetLdapConnection(options.Domain))
                {
                    if (conn == null)
                    {
                        Console.WriteLine("LDAP connection test failed, probably can't contact domain");
                        return;
                    }
                    conn.Bind();
                }
            }
            catch (LdapException)
            {
                Console.WriteLine("Ldap Connection Failure.");
                Console.WriteLine("Try again with the IgnoreLdapCert option if using SecureLDAP or check your DomainController option");
                return;
            }

            if (options.Uri != null)
            {
                using (var client = new WebClient())
                {
                    client.Headers.Add("content-type", "application/json");
                    client.Headers.Add("Accept", "application/json; charset=UTF-8");

                    if (options.UserPass != null)
                    {
                        client.Headers.Add("Authorization", options.GetEncodedUserPass());
                    }

                    try
                    {
                        client.DownloadData(options.GetCheckURI());
                        Console.WriteLine("Successfully connected to the Neo4j REST endpoint.");
                    }
                    catch
                    {
                        Console.WriteLine("Unable to connect to the Neo4j REST endpoint. Check your URI and username/password");
                        return;
                    }
                }
            }

            if (options.Stealth)
            {
                Console.WriteLine("Note: All stealth options are single threaded");
            }

            if (options.CollectMethod.Equals(LocalGroup) && options.Stealth)
            {
                Console.WriteLine("Note: You specified Stealth and LocalGroup which is equivalent to GPOLocalGroup");
                options.CollectMethod = GPOLocalGroup;
            }

            var runner = new EnumerationRunner(options);

            if (options.CollectMethod.Equals(SessionLoop))
            {
                if (options.MaxLoopTime == null)
                {
                    Console.WriteLine("Session Loop mode specified without MaxLoopTime, will loop indefinitely");
                }
                else
                {
                    Console.WriteLine($"Session Loop mode specified. Looping will end on {options.LoopEnd.ToShortDateString()} at {options.LoopEnd.ToShortTimeString()}");
                }
            }

            if (options.Stealth)
            {
                runner.StartStealthEnumeration();
            }
            else
            {
                runner.StartEnumeration();
            }
            Cache.Instance.SaveCache();

            Utils.DeduplicateFiles();

            if (options.CompressData)
            {
                Utils.CompressFiles();
            }
        }
Exemplo n.º 2
0
        public static void Main(string[] args)
        {
            if (args == null)
            {
                throw new ArgumentNullException(nameof(args));
            }

            var options = new Options();

            if (!Parser.Default.ParseArguments(args, options))
            {
                return;
            }

            try
            {
                // ReSharper disable once ReturnValueOfPureMethodIsNotUsed
                Path.Combine(options.CSVFolder, options.CacheFile);
            }
            catch (ArgumentException)
            {
                Console.WriteLine("Invalid characters in output path. Check for trailing backslashes!");
                return;
            }

            var collectionMethods = new List <CollectionMethod>();

            if (options.CollectionMethod.Length == 1)
            {
                options.CollectionMethod = options.CollectionMethod[0].Split(',');
            }

            if (options.Jitter > 100 || options.Jitter < 0)
            {
                Console.WriteLine("Jitter must be a value between 0 and 100!");
                return;
            }

            if (options.Throttle < 0)
            {
                Console.WriteLine("Throttle must be 0 or greater!");
                return;
            }

            foreach (var unparsed in options.CollectionMethod)
            {
                try
                {
                    var e = (CollectionMethod)Enum.Parse(typeof(CollectionMethod), unparsed, true);
                    collectionMethods.Add(e);
                }
                catch
                {
                    Console.WriteLine($"Failed to parse value {unparsed}. Check your values for CollectionMethods!");
                    return;
                }
            }

            if (options.Debug)
            {
                Console.WriteLine("Debug Mode activated!");
                options.Threads = 1;
            }

            if (options.MaxLoopTime != null && collectionMethods.Contains(SessionLoop))
            {
                var regex     = new Regex("[0-9]+[smdh]");
                var matches   = regex.Matches(options.MaxLoopTime);
                var numregex  = new Regex("[0-9]+");
                var timeregex = new Regex("[smdh]");
                if (matches.Count == 0)
                {
                    Console.WriteLine("LoopEndTime does not match required format");
                    return;
                }

                var now   = DateTime.Now;
                var drift = 0;
                foreach (var match in matches)
                {
                    var num  = int.Parse(numregex.Match(match.ToString()).Value);
                    var spec = timeregex.Match(match.ToString());

                    switch (spec.Value)
                    {
                    case "s":
                        now    = now.AddSeconds(num);
                        drift += num;
                        break;

                    case "m":
                        now    = now.AddMinutes(num);
                        drift += num * 60;
                        break;

                    case "h":
                        now    = now.AddHours(num);
                        drift += num * 60 * 60;
                        break;

                    case "d":
                        now    = now.AddDays(num);
                        drift += num * 60 * 60 * 24;
                        break;
                    }
                }

                options.LoopEnd = now;

                if (drift == 0)
                {
                    Console.WriteLine("LoopEndTime is zero! Specify a real value");
                    return;
                }
            }

            options.CurrentUser = WindowsIdentity.GetCurrent().Name.Split('\\')[1];
            var nowtime = DateTime.Now;

            Console.WriteLine($"Initializing BloodHound at {nowtime.ToShortTimeString()} on {nowtime.ToShortDateString()}");

            if (options.ComputerFile != null)
            {
                if (options.PingTimeout < 1000)
                {
                    Console.WriteLine("Increasing ping timeout to 1 second for ComputerFile mode");
                    options.PingTimeout = 1000;
                }
            }

            Cache.CreateInstance(options);
            Utils.CreateInstance(options);

            if (!Utils.CheckWritePrivs())
            {
                Console.WriteLine("Unable to write in chosen directory. Please check privs");
                return;
            }

            if (Utils.Instance.GetDomainList().Count == 0)
            {
                Console.WriteLine("Unable to contact domain. Try from a domain context!");
                return;
            }

            SessionHelpers.Init(options);
            LocalAdminHelpers.Init();
            GroupHelpers.Init();
            AclHelpers.Init();
            DomainTrustEnumeration.Init();
            ContainerHelpers.Init();

            if (options.Test != null)
            {
                Test.DoStuff(options.Test);
                return;
            }

            //Lets test our connection to LDAP before we do anything else
            try
            {
                using (var conn = Utils.Instance.GetLdapConnection(options.Domain))
                {
                    if (conn == null)
                    {
                        Console.WriteLine("LDAP connection test failed, probably can't contact domain");
                        return;
                    }
                    conn.Bind();
                }
            }
            catch (LdapException)
            {
                Console.WriteLine("Ldap Connection Failure.");
                Console.WriteLine("Try again with the IgnoreLdapCert option if using SecureLDAP or check your DomainController/LdapPort option");
                return;
            }

            if (options.Uri != null)
            {
                if (!options.Uri.StartsWith("http", StringComparison.OrdinalIgnoreCase))
                {
                    Console.WriteLine("URI must start with http:// or https://");
                    return;
                }

                using (var client = new WebClient())
                {
                    client.Headers.Add("content-type", "application/json");
                    client.Headers.Add("Accept", "application/json; charset=UTF-8");

                    if (options.UserPass != null)
                    {
                        client.Headers.Add("Authorization", options.GetEncodedUserPass());
                    }

                    try
                    {
                        client.DownloadData(options.GetCheckURI());
                        Console.WriteLine("Successfully connected to the Neo4j REST endpoint.");
                    }
                    catch
                    {
                        Console.WriteLine("Unable to connect to the Neo4j REST endpoint. Check your URI and username/password");
                        return;
                    }
                }
            }

            if (options.RemoveCSV && !options.CompressData)
            {
                Console.WriteLine("Ignoring RemoveCSV as CompressData is not set");
                options.RemoveCSV = false;
            }

            if (options.Stealth)
            {
                Console.WriteLine("Note: All stealth options are single threaded");
            }

            if (options.Throttle > 0)
            {
                Console.WriteLine(
                    $"Adding a delay of {options.Throttle} milliseconds to computer requests with a jitter of {options.Jitter}%");
            }

            foreach (var cmethod in collectionMethods)
            {
                options.CurrentCollectionMethod = cmethod;
                if (options.ComputerFile != null)
                {
                    if (!File.Exists(options.ComputerFile))
                    {
                        Console.WriteLine("Specified ComputerFile does not exist!");
                        return;
                    }

                    if (options.CurrentCollectionMethod.Equals(Default))
                    {
                        options.CurrentCollectionMethod = ComputerOnly;
                        Console.WriteLine("ComputerFile detected with default enumeration. Switching to ComputerOnly collection method");
                    }

                    if (!(options.CurrentCollectionMethod.Equals(Session) || options.CurrentCollectionMethod.Equals(SessionLoop) ||
                          options.CurrentCollectionMethod.Equals(LoggedOn) || options.CurrentCollectionMethod.Equals(LocalGroup) ||
                          options.CurrentCollectionMethod.Equals(ComputerOnly)))
                    {
                        Console.WriteLine("ComputerFile can only be used with the following collection methods: ComputerOnly, Session, SessionLoop, LocalGroup, LoggedOn");
                        continue;
                    }
                }

                if (options.CurrentCollectionMethod.Equals(LocalGroup) && options.Stealth)
                {
                    Console.WriteLine("Note: You specified Stealth and LocalGroup which is equivalent to GPOLocalGroup");
                    options.CurrentCollectionMethod = GPOLocalGroup;
                }

                var runner = new EnumerationRunner(options);

                if (options.CurrentCollectionMethod.Equals(SessionLoop))
                {
                    Console.WriteLine(options.MaxLoopTime == null
                        ? "Session Loop mode specified without MaxLoopTime, will loop indefinitely"
                        : $"Session Loop mode specified. Looping will end on {options.LoopEnd.ToShortDateString()} at {options.LoopEnd.ToShortTimeString()}");
                }

                if (options.Stealth)
                {
                    runner.StartStealthEnumeration();
                }
                else
                {
                    runner.StartEnumeration();
                }
                Console.WriteLine();
            }

            Cache.Instance.SaveCache();

            Utils.DeduplicateFiles();

            if (options.CompressData)
            {
                Utils.CompressFiles();
            }
        }