Пример #1
0
        /// <summary>
        /// Grabs computers names from the text file specified in the options, and attempts to resolve them to LDAP objects.
        /// Pushes the corresponding LDAP objects to the queue.
        /// </summary>
        /// <param name="queue"></param>
        /// <returns></returns>
        protected override async Task ProduceLdap(ITargetBlock <SearchResultEntry> queue)
        {
            var computerFile = Options.Instance.ComputerFile;
            var token        = Helpers.GetCancellationToken();

            OutputTasks.StartOutputTimer();
            //Open the file for reading
            using (var fileStream = new StreamReader(new FileStream(computerFile, FileMode.Open, FileAccess.Read)))
            {
                string computer;
                // Loop over each line in the file
                while ((computer = fileStream.ReadLine()) != null)
                {
                    //If the cancellation token is set, cancel enumeration
                    if (token.IsCancellationRequested)
                    {
                        break;
                    }

                    string sid;
                    if (!computer.StartsWith("S-1-5-21"))
                    {
                        //The computer isn't a SID so try to convert it to one
                        sid = await ResolutionHelpers.ResolveHostToSid(computer, DomainName);
                    }
                    else
                    {
                        //The computer is already a sid, so just store it off
                        sid = computer;
                    }

                    try
                    {
                        //Convert the sid to a hex representation and find the entry in the domain
                        var hexSid = Helpers.ConvertSidToHexSid(sid);
                        var entry  = await Searcher.GetOne($"(objectsid={hexSid})", Props, SearchScope.Subtree);

                        if (entry == null)
                        {
                            //We couldn't find the entry for whatever reason
                            Console.WriteLine($"Failed to resolve {computer}");
                            continue;
                        }

                        //Success! Send the computer to be processed
                        await queue.SendAsync(entry);
                    }
                    catch
                    {
                        Console.WriteLine($"Failed to resolve {computer}");
                    }
                }
            }

            queue.Complete();
        }
Пример #2
0
        /// <summary>
        /// Produces stealth LDAP targets
        /// </summary>
        /// <param name="queue"></param>
        /// <returns></returns>
        protected override async Task ProduceLdap(ITargetBlock <SearchResultEntry> queue)
        {
            var token = Helpers.GetCancellationToken();

            //If we haven't generated our stealth targets, we'll build it now
            if (!_stealthTargetsBuilt)
            {
                Console.WriteLine("[+] Finding Stealth Targets from LDAP Properties");
                Console.WriteLine();
                var targetSids = await FindPathTargetSids();

                SetStealthTargetSids(targetSids);
                _stealthTargetsBuilt = true;

                OutputTasks.StartOutputTimer();
                //Output our stealth targets to the queue
                foreach (var searchResult in Searcher.QueryLdap(Query, Props, SearchScope.Subtree, Options.Instance.SearchBase))
                {
                    if (token.IsCancellationRequested)
                    {
                        Console.WriteLine("[-] Terminating Producer as cancellation was requested. Waiting for pipeline to finish");
                        break;
                    }

                    await queue.SendAsync(searchResult);
                }
                queue.Complete();
            }
            else
            {
                // We've already built our stealth targets, and we're doing a loop
                OutputTasks.StartOutputTimer();
                var targets = new List <SearchResultEntry>();
                targets.AddRange(_stealthTargetSids.Values);
                if (!Options.Instance.ExcludeDomainControllers)
                {
                    targets.AddRange(DomainControllerSids.Values);
                }

                foreach (var searchResult in targets)
                {
                    if (token.IsCancellationRequested)
                    {
                        break;
                    }
                    await queue.SendAsync(searchResult);
                }
                queue.Complete();
            }
        }
            public override bool Execute()
            {
                var executed = base.Execute();

                if (executed)
                {
                    XmlTasks = OutputTasks.Select(x => XElement.Parse(x.GetMetadata("Xml"))).ToArray();
                }

                test.tasksFile    = base.TasksFile;
                test.inlineTask   = base.InlineFile;
                test.compiledTask = base.InlineFile;

                return(executed);
            }
Пример #4
0
        protected override async Task ProduceLdap(ITargetBlock <SearchResultEntry> queue)
        {
            var token = Helpers.GetCancellationToken();

            OutputTasks.StartOutputTimer();
            foreach (var searchResult in Searcher.QueryLdap(Query, Props, SearchScope.Subtree))
            {
                if (token.IsCancellationRequested)
                {
                    Console.WriteLine("[-] Terminating Producer as cancellation was requested. Waiting for pipeline to finish");
                    break;
                }
                await queue.SendAsync(searchResult);
            }
            queue.Complete();
        }
Пример #5
0
        /// <summary>
        /// Uses the LDAP filter and properties specified to grab data from LDAP, and push it to the queue.
        /// </summary>
        /// <param name="queue"></param>
        /// <returns></returns>
        protected override async Task ProduceLdap(ITargetBlock <SearchResultEntry> queue)
        {
            var token = Helpers.GetCancellationToken();

            OutputTasks.StartOutputTimer();
            //Do a basic  LDAP search and grab results
            foreach (var searchResult in Searcher.QueryLdap(Query, Props, SearchScope.Subtree, Options.Instance.SearchBase))
            {
                //If our cancellation token is set, cancel out of our loop
                if (token.IsCancellationRequested)
                {
                    Console.WriteLine("[-] Terminating Producer as cancellation was requested. Waiting for pipeline to finish");
                    break;
                }
                await queue.SendAsync(searchResult);
            }
            queue.Complete();
        }
Пример #6
0
        /// <summary>
        /// Entry point for SharpHound.
        /// </summary>
        /// <param name="args"></param>
        /// <returns></returns>
        private static async Task Main(string[] args)
        {
            // Use the wonderful commandlineparser library to build our options.
            var parser = new Parser(with =>
            {
                with.CaseInsensitiveEnumValues = true;
                with.CaseSensitive             = false;
                with.HelpWriter = Console.Error;
            });

            parser.ParseArguments <Options>(args).WithParsed(o =>
            {
                //We've successfully parsed arguments, lets do some options post-processing.
                var currentTime = DateTime.Now;
                var initString  =
                    $"Initializing SharpHound at {currentTime.ToShortTimeString()} on {currentTime.ToShortDateString()}";
                Console.WriteLine(new string('-', initString.Length));
                Console.WriteLine(initString);
                Console.WriteLine(new string('-', initString.Length));
                Console.WriteLine();

                // Set the current user name for session collection.
                if (o.OverrideUserName != null)
                {
                    o.CurrentUserName = o.OverrideUserName;
                }
                else
                {
                    o.CurrentUserName = WindowsIdentity.GetCurrent().Name.Split('\\')[1];
                }

                //Check some loop options
                if (o.Loop)
                {
                    //If loop is set, ensure we actually set options properly
                    if (o.LoopDuration == TimeSpan.Zero)
                    {
                        Console.WriteLine("Loop specified without a duration. Defaulting to 2 hours!");
                        o.LoopDuration = TimeSpan.FromHours(2);
                    }

                    if (o.LoopInterval == TimeSpan.Zero)
                    {
                        o.LoopInterval = TimeSpan.FromSeconds(30);
                    }
                }

                Options.Instance = o;
            }).WithNotParsed(error =>
            {
            });

            parser.Dispose();

            var options = Options.Instance;

            if (options == null)
            {
                return;
            }

            // Check to make sure we actually have valid collection methods set
            if (!options.ResolveCollectionMethods())
            {
                return;
            }

            //If the user didn't specify a domain, pull the domain from DirectoryServices
            if (options.Domain == null)
            {
                try
                {
                    options.Domain = System.DirectoryServices.ActiveDirectory.Domain.GetCurrentDomain().Name.ToUpper();
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);
                    Console.WriteLine("Unable to determine user's domain. Please manually specify it with the --domain flag");
                    return;
                }
            }


            //Check to make sure both LDAP options are set if either is set
            if ((options.LdapPassword != null && options.LdapUsername == null) ||
                (options.LdapUsername != null && options.LdapPassword == null))
            {
                Console.WriteLine("You must specify both LdapUsername and LdapPassword if using these options!");
                return;
            }

            //Initial LDAP connection test. Search for the well known administrator SID to make sure we can connect successfully.
            var searcher = Helpers.GetDirectorySearcher(options.Domain);
            var result   = await searcher.GetOne("(objectclass=domain)", new[] { "objectsid" },
                                                 SearchScope.Subtree);

            //If we get nothing back from LDAP, something is wrong
            if (result == null)
            {
                Console.WriteLine("LDAP Connection Test Failed. Check if you're in a domain context!");
                return;
            }

            var   initialCompleted  = false;
            var   needsCancellation = false;
            Timer timer             = null;
            var   loopEnd           = DateTime.Now;

            //If loop is set, set up our timer for the loop now
            if (options.Loop)
            {
                loopEnd        = loopEnd.AddMilliseconds(options.LoopDuration.TotalMilliseconds);
                timer          = new Timer();
                timer.Elapsed += (sender, eventArgs) =>
                {
                    if (initialCompleted)
                    {
                        Helpers.InvokeCancellation();
                    }
                    else
                    {
                        needsCancellation = true;
                    }
                };
                timer.Interval  = options.LoopDuration.TotalMilliseconds;
                timer.AutoReset = false;
                timer.Start();
            }

            //Create our Cache
            Cache.CreateInstance();

            //Start the computer error task (if specified)
            OutputTasks.StartComputerStatusTask();

            //Build our pipeline, and get the initial block to wait for completion.
            var pipelineCompletionTask = PipelineBuilder.GetBasePipelineForDomain(options.Domain);

            //Wait for output to complete
            await pipelineCompletionTask;

            //Wait for our output tasks to finish.
            await OutputTasks.CompleteOutput();

            //Mark our initial run as complete, signalling that we're now in the looping phase
            initialCompleted = true;

            if (needsCancellation)
            {
                Helpers.InvokeCancellation();
            }

            //Start looping if specified
            if (Options.Instance.Loop)
            {
                if (Helpers.GetCancellationToken().IsCancellationRequested)
                {
                    Console.WriteLine("Skipping looping because loop duration has already passed");
                }
                else
                {
                    Console.WriteLine();
                    Console.WriteLine("Waiting 30 seconds before starting loops");
                    try
                    {
                        await Task.Delay(TimeSpan.FromSeconds(30), Helpers.GetCancellationToken());
                    }
                    catch (TaskCanceledException)
                    {
                        Console.WriteLine("Skipped wait because loop duration has completed!");
                    }

                    if (!Helpers.GetCancellationToken().IsCancellationRequested)
                    {
                        Console.WriteLine();
                        Console.WriteLine($"Loop Enumeration Methods: {options.GetLoopCollectionMethods()}");
                        Console.WriteLine($"Looping scheduled to stop at {loopEnd.ToLongTimeString()} on {loopEnd.ToShortDateString()}");
                        Console.WriteLine();
                    }

                    var count = 0;
                    while (!Helpers.GetCancellationToken().IsCancellationRequested)
                    {
                        count++;
                        var currentTime = DateTime.Now;
                        Console.WriteLine($"Starting loop #{count} at {currentTime.ToShortTimeString()} on {currentTime.ToShortDateString()}");
                        Helpers.StartNewRun();
                        pipelineCompletionTask = PipelineBuilder.GetLoopPipelineForDomain(Options.Instance.Domain);
                        await pipelineCompletionTask;
                        await OutputTasks.CompleteOutput();

                        if (!Helpers.GetCancellationToken().IsCancellationRequested)
                        {
                            Console.WriteLine();
                            Console.WriteLine($"Waiting {options.LoopInterval.TotalSeconds} seconds for next loop");
                            Console.WriteLine();
                            try
                            {
                                await Task.Delay(options.LoopInterval, Helpers.GetCancellationToken());
                            }
                            catch (TaskCanceledException)
                            {
                                Console.WriteLine("Skipping wait as loop duration has expired");
                            }
                        }
                    }

                    if (count > 0)
                    {
                        Console.WriteLine($"Looping finished! Looped a total of {count} times");
                    }

                    //Special function to grab all the zip files created by looping and collapse them into a single file
                    await OutputTasks.CollapseLoopZipFiles();
                }
            }
            timer?.Dispose();

            //Program exit started. Save the cache file
            Cache.Instance.SaveCache();

            //And we're done!
            var currTime = DateTime.Now;

            Console.WriteLine();
            Console.WriteLine($"SharpHound Enumeration Completed at {currTime.ToShortTimeString()} on {currTime.ToShortDateString()}! Happy Graphing!");
            Console.WriteLine();
        }
Пример #7
0
        private static async Task Main(string[] args)
        {
            //TODO: Trusts
            var parser = new Parser(with =>
            {
                with.CaseInsensitiveEnumValues = true;
                with.CaseSensitive             = false;
                with.HelpWriter = Console.Error;
            });

            parser.ParseArguments <Options>(args).WithParsed(o =>
            {
                var currentTime = DateTime.Now;
                var initString  =
                    $"Initializing SharpHound at {currentTime.ToShortTimeString()} on {currentTime.ToShortDateString()}";
                Console.WriteLine(new string('-', initString.Length));
                Console.WriteLine(initString);
                Console.WriteLine(new string('-', initString.Length));
                Console.WriteLine();

                if (o.OverrideUserName != null)
                {
                    o.CurrentUserName = o.OverrideUserName;
                }
                else
                {
                    o.CurrentUserName = WindowsIdentity.GetCurrent().Name.Split('\\')[1];
                }

                if (o.Loop)
                {
                    if (o.LoopDuration == TimeSpan.Zero)
                    {
                        Console.WriteLine("Loop specified without a duration. Defaulting to 2 hours!");
                        o.LoopDuration = TimeSpan.FromHours(2);
                    }

                    if (o.LoopInterval == TimeSpan.Zero)
                    {
                        o.LoopInterval = TimeSpan.FromSeconds(30);
                    }
                }

                Options.Instance = o;
            }).WithNotParsed(error => {
            });

            parser.Dispose();

            var options = Options.Instance;

            if (options == null)
            {
                return;
            }

            if (!options.ResolveCollectionMethods())
            {
                return;
            }

            var searcher = Helpers.GetDirectorySearcher(options.Domain);
            var result   = await searcher.GetOne($"(objectsid={Helpers.ConvertSidToHexSid("S-1-5-32-544")})", new[] { "objectsid" },
                                                 SearchScope.Subtree);

            if (result == null)
            {
                Console.WriteLine("LDAP Connection Test Failed. Check if you're in a domain context!");
                return;
            }

            var   initialCompleted  = false;
            var   needsCancellation = false;
            Timer timer             = null;
            var   loopEnd           = DateTime.Now;

            if (options.Loop)
            {
                loopEnd        = loopEnd.AddMilliseconds(options.LoopDuration.TotalMilliseconds);
                timer          = new Timer();
                timer.Elapsed += (sender, eventArgs) =>
                {
                    if (initialCompleted)
                    {
                        Helpers.InvokeCancellation();
                    }
                    else
                    {
                        needsCancellation = true;
                    }
                };
                timer.Interval  = options.LoopDuration.TotalMilliseconds;
                timer.AutoReset = false;
                timer.Start();
            }

            Cache.CreateInstance();

            OutputTasks.StartComputerStatusTask();
            var   pipelineCompletionTask = PipelineBuilder.GetBasePipelineForDomain(options.Domain);
            await pipelineCompletionTask;
            await OutputTasks.CompleteOutput();

            initialCompleted = true;

            if (needsCancellation)
            {
                Helpers.InvokeCancellation();
            }

            if (Options.Instance.Loop)
            {
                if (Helpers.GetCancellationToken().IsCancellationRequested)
                {
                    Console.WriteLine("Skipping looping because loop duration has already passed");
                }
                else
                {
                    Console.WriteLine();
                    Console.WriteLine("Waiting 30 seconds before starting loops");
                    try
                    {
                        await Task.Delay(TimeSpan.FromSeconds(30), Helpers.GetCancellationToken());
                    }
                    catch (TaskCanceledException)
                    {
                        Console.WriteLine("Skipped wait because loop duration has completed!");
                    }

                    if (!Helpers.GetCancellationToken().IsCancellationRequested)
                    {
                        Console.WriteLine();
                        Console.WriteLine($"Loop Enumeration Methods: {options.GetLoopCollectionMethods()}");
                        Console.WriteLine($"Looping scheduled to stop at {loopEnd.ToLongTimeString()} on {loopEnd.ToShortDateString()}");
                        Console.WriteLine();
                    }

                    var count = 0;
                    while (!Helpers.GetCancellationToken().IsCancellationRequested)
                    {
                        count++;
                        var currentTime = DateTime.Now;
                        Console.WriteLine($"Starting loop #{count} at {currentTime.ToShortTimeString()} on {currentTime.ToShortDateString()}");
                        Helpers.StartNewRun();
                        pipelineCompletionTask = PipelineBuilder.GetLoopPipelineForDomain(Options.Instance.Domain);
                        await pipelineCompletionTask;
                        await OutputTasks.CompleteOutput();

                        if (!Helpers.GetCancellationToken().IsCancellationRequested)
                        {
                            Console.WriteLine();
                            Console.WriteLine($"Waiting {options.LoopInterval.TotalSeconds} seconds for next loop");
                            Console.WriteLine();
                            try
                            {
                                await Task.Delay(options.LoopInterval, Helpers.GetCancellationToken());
                            }
                            catch (TaskCanceledException)
                            {
                                Console.WriteLine("Skipping wait as loop duration has expired");
                            }
                        }
                    }

                    if (count > 0)
                    {
                        Console.WriteLine($"Looping finished! Looped a total of {count} times");
                    }

                    await OutputTasks.CollapseLoopZipFiles();
                }
            }
            timer?.Dispose();

            Cache.Instance.SaveCache();

            Console.WriteLine();
            Console.WriteLine("SharpHound Enumeration Completed! Happy Graphing!");
            Console.WriteLine();
        }