diff --git a/src/Client/Enums.cs b/src/Client/Enums.cs index 4943863..5dc2af2 100644 --- a/src/Client/Enums.cs +++ b/src/Client/Enums.cs @@ -26,6 +26,7 @@ public enum CollectionMethodOptions ComputerOnly, CARegistry, DCRegistry, + CertServices, All } } \ No newline at end of file diff --git a/src/Options.cs b/src/Options.cs index c7ae336..79e61ba 100644 --- a/src/Options.cs +++ b/src/Options.cs @@ -14,7 +14,7 @@ public class Options // Options that affect what is collected [Option('c', "collectionmethods", Default = new[] { "Default" }, HelpText = - "Collection Methods: Group, LocalGroup, LocalAdmin, RDP, DCOM, PSRemote, Session, Trusts, ACL, Container, ComputerOnly, GPOLocalGroup, LoggedOn, ObjectProps, SPNTargets, UserRights, Default, DCOnly, CARegistry, DCRegistry, All")] + "Collection Methods: Group, LocalGroup, LocalAdmin, RDP, DCOM, PSRemote, Session, Trusts, ACL, Container, ComputerOnly, GPOLocalGroup, LoggedOn, ObjectProps, SPNTargets, UserRights, Default, DCOnly, CARegistry, DCRegistry, CertServices, All")] public IEnumerable CollectionMethods { get; set; } [Option('d', "domain", Default = null, HelpText = "Specify domain to enumerate")] @@ -61,7 +61,7 @@ public class Options [Option(HelpText = "Don't zip files", Default = false)] public bool NoZip { get; set; } - + [Option(HelpText = "Password protects the zip with the specified password", Default = null)] public string ZipPassword { get; set; } @@ -87,7 +87,7 @@ public class Options [Option(HelpText = "Connect to LDAP SSL instead of regular LDAP", Default = false)] public bool SecureLDAP { get; set; } - + [Option(HelpText = "Disables certificate verification when using LDAPS", Default = false)] public bool DisableCertVerification { get; set; } @@ -97,10 +97,10 @@ public class Options //Options that affect how enumeration is performed [Option(HelpText = "Skip checking if 445 is open", Default = false)] public bool SkipPortCheck { get; set; } - + [Option(HelpText = "Timeout for port checks in milliseconds", Default = 500)] public int PortCheckTimeout { get; set; } - + [Option(HelpText = "Skip check for PwdLastSet when enumerating computers", Default = false)] public bool SkipPasswordCheck { get; set; } @@ -114,7 +114,7 @@ public class Options [Option(HelpText = "Add jitter to throttle (percent)")] public int Jitter { get; set; } - [Option('t',"threads", HelpText = "Number of threads to run enumeration with", Default = 50)] + [Option('t', "threads", HelpText = "Number of threads to run enumeration with", Default = 50)] public int Threads { get; set; } [Option(HelpText = "Skip registry session enumeration")] @@ -133,10 +133,10 @@ public class Options [Option('l', "Loop", HelpText = "Loop computer collection")] public bool Loop { get; set; } - [Option(HelpText="Loop duration (hh:mm:ss - 05:00:00 is 5 hours, default: 2 hrs)")] + [Option(HelpText = "Loop duration (hh:mm:ss - 05:00:00 is 5 hours, default: 2 hrs)")] public TimeSpan LoopDuration { get; set; } - [Option(HelpText="Add delay between loops (hh:mm:ss - 00:03:00 is 3 minutes)")] public TimeSpan LoopInterval { get; set; } + [Option(HelpText = "Add delay between loops (hh:mm:ss - 00:03:00 is 3 minutes)")] public TimeSpan LoopInterval { get; set; } //Misc Options [Option(HelpText = "Interval in which to display status in milliseconds", Default = 30000)] @@ -189,6 +189,7 @@ internal bool ResolveCollectionMethods(ILogger logger, out ResolvedCollectionMet CollectionMethodOptions.ComputerOnly => ResolvedCollectionMethod.ComputerOnly, CollectionMethodOptions.CARegistry => ResolvedCollectionMethod.CARegistry, CollectionMethodOptions.DCRegistry => ResolvedCollectionMethod.DCRegistry, + CollectionMethodOptions.CertServices => ResolvedCollectionMethod.CertServices, CollectionMethodOptions.All => ResolvedCollectionMethod.All, CollectionMethodOptions.None => ResolvedCollectionMethod.None, _ => throw new ArgumentOutOfRangeException() @@ -234,7 +235,7 @@ internal bool ResolveCollectionMethods(ILogger logger, out ResolvedCollectionMet resolved ^= ResolvedCollectionMethod.LocalAdmin; updates.Add("[-] Removed LocalAdmin Collection"); } - + if ((resolved & ResolvedCollectionMethod.CARegistry) != 0) { resolved ^= ResolvedCollectionMethod.CARegistry; diff --git a/src/Producers/BaseProducer.cs b/src/Producers/BaseProducer.cs index 0b6ef5f..a75f5c7 100644 --- a/src/Producers/BaseProducer.cs +++ b/src/Producers/BaseProducer.cs @@ -1,10 +1,17 @@ using System.Collections.Generic; + using System.Threading.Channels; + using System.Threading.Tasks; + using Sharphound.Client; + using SharpHoundCommonLib; + using SharpHoundCommonLib.Enums; + using SharpHoundCommonLib.LDAPQueries; + using SharpHoundCommonLib.OutputTypes; namespace Sharphound.Producers @@ -28,7 +35,7 @@ protected BaseProducer(IContext context, Channel channel, Ch public abstract Task Produce(); public abstract Task ProduceConfigNC(); - protected LDAPData CreateLDAPData() + protected LDAPData CreateDefaultNCData() { var query = new LDAPFilter(); var props = new List(); @@ -60,9 +67,9 @@ protected LDAPData CreateLDAPData() (methods & ResolvedCollectionMethod.RDP) != 0 || (methods & ResolvedCollectionMethod.LoggedOn) != 0 || (methods & ResolvedCollectionMethod.Session) != 0 || - (methods & ResolvedCollectionMethod.ObjectProps) != 0 || + (methods & ResolvedCollectionMethod.ObjectProps) != 0 || (methods & ResolvedCollectionMethod.UserRights) != 0) - + props.AddRange(CommonProperties.ComputerMethodProps); if ((methods & ResolvedCollectionMethod.Trusts) != 0) props.AddRange(CommonProperties.DomainTrustProps); @@ -96,7 +103,7 @@ protected LDAPData CreateLDAPData() (methods & ResolvedCollectionMethod.RDP) != 0 || (methods & ResolvedCollectionMethod.LoggedOn) != 0 || (methods & ResolvedCollectionMethod.Session) != 0 || - (methods & ResolvedCollectionMethod.ObjectProps) != 0 || + (methods & ResolvedCollectionMethod.ObjectProps) != 0 || (methods & ResolvedCollectionMethod.UserRights) != 0) { query = query.AddComputers(); @@ -144,34 +151,39 @@ protected LDAPData CreateConfigNCData() props.AddRange(CommonProperties.TypeResolutionProps); var methods = Context.ResolvedCollectionMethods; + var allObjectTypesQuery = query.AddContainers().AddConfiguration().AddCertificateTemplates().AddCertificateAuthorities().AddEnterpriseCertificationAuthorities(); - if ((methods & ResolvedCollectionMethod.ObjectProps) != 0 || (methods & ResolvedCollectionMethod.ACL) != 0) + if ((methods & ResolvedCollectionMethod.ObjectProps) != 0) { - query = query.AddContainers().AddConfiguration().AddCertificateTemplates().AddCertificateAuthorities().AddEnterpriseCertificationAuthorities(); + query = allObjectTypesQuery; props.AddRange(CommonProperties.ObjectPropsProps); - props.AddRange(CommonProperties.CertAbuseProps); + } - if ((methods & ResolvedCollectionMethod.Container) != 0) - props.AddRange(CommonProperties.ContainerProps); + if ((methods & ResolvedCollectionMethod.ACL) != 0) + { + query = allObjectTypesQuery; + props.AddRange(CommonProperties.ACLProps); + } - if ((methods & ResolvedCollectionMethod.ACL) != 0) - props.AddRange(CommonProperties.ACLProps); + if ((methods & ResolvedCollectionMethod.CertServices) != 0) + { + query = allObjectTypesQuery; + props.AddRange(CommonProperties.CertAbuseProps); } - else + + if ((methods & ResolvedCollectionMethod.Container) != 0) { - if ((methods & ResolvedCollectionMethod.Container) != 0) - { - query = query.AddContainers().AddConfiguration().AddCertificateTemplates().AddCertificateAuthorities().AddEnterpriseCertificationAuthorities(); - props.AddRange(CommonProperties.ContainerProps); - } + query = allObjectTypesQuery; + props.AddRange(CommonProperties.ContainerProps); + } - if ((methods & ResolvedCollectionMethod.CARegistry) != 0) - { - query = query.AddEnterpriseCertificationAuthorities(); - props.AddRange(CommonProperties.CertAbuseProps); - } + if ((methods & ResolvedCollectionMethod.CARegistry) != 0) + { + query = query.AddEnterpriseCertificationAuthorities(); + props.AddRange(CommonProperties.CertAbuseProps); } + if (Context.LdapFilter != null) query.AddFilter(Context.LdapFilter, true); data.Filter = query; diff --git a/src/Producers/ComputerFileProducer.cs b/src/Producers/ComputerFileProducer.cs index 02d981a..369525e 100644 --- a/src/Producers/ComputerFileProducer.cs +++ b/src/Producers/ComputerFileProducer.cs @@ -30,7 +30,7 @@ public override async Task Produce() var computerFile = Context.ComputerFile; var cancellationToken = Context.CancellationTokenSource.Token; - var ldapData = CreateLDAPData(); + var ldapData = CreateDefaultNCData(); try { diff --git a/src/Producers/LdapProducer.cs b/src/Producers/LdapProducer.cs index e978972..335d100 100644 --- a/src/Producers/LdapProducer.cs +++ b/src/Producers/LdapProducer.cs @@ -26,7 +26,7 @@ public override async Task Produce() { var cancellationToken = Context.CancellationTokenSource.Token; - var ldapData = CreateLDAPData(); + var ldapData = CreateDefaultNCData(); var log = Context.Logger; var utils = Context.LDAPUtils; @@ -67,7 +67,7 @@ await OutputChannel.Writer.WriteAsync(new Domain { "collected", true }, } }); - + foreach (var searchResult in Context.LDAPUtils.QueryLDAP(ldapData.Filter.GetFilter(), SearchScope.Subtree, ldapData.Props.Distinct().ToArray(), cancellationToken, domain.Name, adsPath: Context.SearchBase, @@ -83,7 +83,7 @@ await OutputChannel.Writer.WriteAsync(new Domain Context.Logger.LogTrace("Producer wrote {DistinguishedName} to channel", searchResult.DistinguishedName); } } - + } /// @@ -121,7 +121,7 @@ public override async Task ProduceConfigNC() Context.Logger.LogTrace("Skipping already collected config NC '{path}' for domain {Domain}", configAdsPath, domain.Name); } } - + } } diff --git a/src/Producers/StealthProducer.cs b/src/Producers/StealthProducer.cs index ac5e3f2..a88a30e 100644 --- a/src/Producers/StealthProducer.cs +++ b/src/Producers/StealthProducer.cs @@ -25,7 +25,7 @@ internal class StealthProducer : BaseProducer public StealthProducer(IContext context, Channel channel, Channel outputChannel) : base(context, channel, outputChannel) { - var ldapData = CreateLDAPData(); + var ldapData = CreateDefaultNCData(); _query = ldapData.Filter; _props = ldapData.Props; @@ -124,7 +124,7 @@ private async Task> FindPathTargetSids() } }); } - + // Loop over the paths we grabbed, and resolve them to sids.