private GPO ProcessGPOObject(ISearchResultEntry entry, ResolvedSearchResult resolvedSearchResult) { var ret = new GPO { ObjectIdentifier = resolvedSearchResult.ObjectId }; ret.Properties.Add("domain", resolvedSearchResult.Domain); ret.Properties.Add("name", resolvedSearchResult.DisplayName); ret.Properties.Add("distinguishedname", entry.DistinguishedName.ToUpper()); ret.Properties.Add("domainsid", resolvedSearchResult.DomainSid); ret.Properties.Add("highvalue", false); if ((_methods & ResolvedCollectionMethod.ACL) != 0) { ret.Aces = _aclProcessor.ProcessACL(resolvedSearchResult, entry).ToArray(); ret.IsACLProtected = _aclProcessor.IsACLProtected(entry); } if ((_methods & ResolvedCollectionMethod.ObjectProps) != 0) { ret.Properties = ContextUtils.Merge(ret.Properties, LDAPPropertyProcessor.ReadGPOProperties(entry)); if (_context.Flags.CollectAllProperties) { ret.Properties = ContextUtils.Merge(_ldapPropertyProcessor.ParseAllProperties(entry), ret.Properties); } } return(ret); }
static public JObject GetDomainGPOs() { DirectoryEntry rootDse = new DirectoryEntry("LDAP://rootDSE"); DirectoryEntry root = new DirectoryEntry("GC://" + rootDse.Properties["defaultNamingContext"].Value.ToString()); DirectorySearcher searcher = new DirectorySearcher(root) { Filter = "(objectClass=groupPolicyContainer)" }; SearchResultCollection GPOs = searcher.FindAll(); // new dictionary for data from each GPO to go into Dictionary <string, Dictionary <string, string> > GPOsData = new Dictionary <string, Dictionary <string, string> >(); foreach (SearchResult GPO in GPOs) { // new dictionary for data from this GPO Dictionary <string, string> GPOData = new Dictionary <string, string>(); DirectoryEntry GPODE = GPO.GetDirectoryEntry(); string GPODN = GPO.GetDirectoryEntry().Properties["distinguishedName"].Value.ToString(); string[] GPOUIDsp0 = GPODN.Split(','); string[] GPOUIDsp1 = GPOUIDsp0[0].Split('='); string GPOUID = GPOUIDsp1[1]; GPOData.Add("UID", GPOUID); GPOData.Add("DistinguishedName", GPODN); DirectoryEntry gpoObject = new DirectoryEntry($"LDAP://{GPODN}"); //GPOData.Add("SDDL", gpoObject.ObjectSecurity.ToString()); GPOData.Add("DisplayName", gpoObject.Properties["displayName"].Value.ToString()); GPOsData.Add(GPOUID, GPOData); } JObject DomainGPOsJson = (JObject)JToken.FromObject(GPOsData); //Console.WriteLine(DomainGPOsJson.ToString()); return(DomainGPOsJson); }
/// <summary> /// Converts a SaerchResultEntry into an LdapWrapper /// </summary> /// <param name="searchResultEntry"></param> /// <returns></returns> internal static LdapWrapper CreateLdapWrapper(SearchResultEntry searchResultEntry) { //Look for a null DN first. Not sure why this would happen. var distinguishedName = searchResultEntry.DistinguishedName; if (distinguishedName == null) { return(null); } var accountName = searchResultEntry.GetProperty("samaccountname"); var samAccountType = searchResultEntry.GetProperty("samaccounttype"); var accountDomain = Helpers.DistinguishedNameToDomain(distinguishedName); var objectSid = searchResultEntry.GetSid(); var objectId = searchResultEntry.GetObjectIdentifier(); //If objectsid/id is null, return if (objectSid == null && objectId == null) { return(null); } var objectType = LdapTypeEnum.Unknown; string objectIdentifier; LdapWrapper wrapper; //Lets see if its a "common" principal if (objectSid != null && CommonPrincipal.GetCommonSid(objectSid, out var commonPrincipal)) { accountName = commonPrincipal.Name; objectType = commonPrincipal.Type; objectIdentifier = Helpers.ConvertCommonSid(objectSid, accountDomain); } else { //Its not a common principal. Lets use properties to figure out what it actually is if (samAccountType != null) { if (samAccountType == "805306370") { return(null); } objectType = Helpers.SamAccountTypeToType(samAccountType); } else { var objectClasses = searchResultEntry.GetPropertyAsArray("objectClass"); if (objectClasses == null) { objectType = LdapTypeEnum.Unknown; } else if (objectClasses.Contains("groupPolicyContainer")) { objectType = LdapTypeEnum.GPO; } else if (objectClasses.Contains("organizationalUnit")) { objectType = LdapTypeEnum.OU; } else if (objectClasses.Contains("domain")) { objectType = LdapTypeEnum.Domain; } } objectIdentifier = objectId; } //Override GMSA object type if (searchResultEntry.GetPropertyAsBytes("msds-groupmsamembership") != null) { objectType = LdapTypeEnum.User; accountName = accountName?.TrimEnd('$'); } //Depending on the object type, create the appropriate wrapper object switch (objectType) { case LdapTypeEnum.Computer: accountName = accountName?.TrimEnd('$'); wrapper = new Computer(searchResultEntry) { DisplayName = $"{accountName}.{accountDomain}".ToUpper(), SamAccountName = accountName }; var hasLaps = searchResultEntry.GetProperty("ms-mcs-admpwdexpirationtime") != null; wrapper.Properties.Add("haslaps", hasLaps); wrapper.Properties.Add("highvalue", false); break; case LdapTypeEnum.User: wrapper = new User(searchResultEntry) { DisplayName = $"{accountName}@{accountDomain}".ToUpper() }; wrapper.Properties.Add("highvalue", false); break; case LdapTypeEnum.Group: wrapper = new Group(searchResultEntry) { DisplayName = $"{accountName}@{accountDomain}".ToUpper() }; if (objectIdentifier.EndsWith("-512") || objectIdentifier.EndsWith("-516") || objectIdentifier.EndsWith("-519") || objectIdentifier.EndsWith("-520") || objectIdentifier.EndsWith("S-1-5-32-544") || objectIdentifier.EndsWith("S-1-5-32-550") || objectIdentifier.EndsWith("S-1-5-32-549") || objectIdentifier.EndsWith("S-1-5-32-551") || objectIdentifier.EndsWith("S-1-5-32-548")) { wrapper.Properties.Add("highvalue", true); } else { wrapper.Properties.Add("highvalue", false); } break; case LdapTypeEnum.GPO: accountName = searchResultEntry.GetProperty("displayname"); wrapper = new GPO(searchResultEntry) { DisplayName = $"{accountName}@{accountDomain}".ToUpper() }; wrapper.Properties.Add("highvalue", false); break; case LdapTypeEnum.OU: accountName = searchResultEntry.GetProperty("name"); wrapper = new OU(searchResultEntry) { DisplayName = $"{accountName}@{accountDomain}".ToUpper() }; wrapper.Properties.Add("highvalue", false); break; case LdapTypeEnum.Domain: wrapper = new Domain(searchResultEntry) { DisplayName = accountDomain.ToUpper() }; wrapper.Properties.Add("highvalue", true); break; case LdapTypeEnum.Unknown: wrapper = null; break; default: throw new ArgumentOutOfRangeException(); } //Null wrappers happen when we cant resolve the object type. Shouldn't ever happen, but just in case, return null here if (wrapper == null) { Console.WriteLine($"Null Wrapper: {distinguishedName}"); return(null); } //Set the DN/SID for the wrapper going forward and a couple other properties wrapper.DistinguishedName = distinguishedName; wrapper.Properties.Add("name", wrapper.DisplayName); wrapper.Properties.Add("domain", wrapper.Domain); wrapper.Properties.Add("objectid", objectIdentifier.ToUpper()); wrapper.Properties.Add("distinguishedname", distinguishedName); wrapper.ObjectIdentifier = objectIdentifier; //Some post processing PostProcessWrapper(wrapper); //Cache the distinguished name from this object Cache.Instance.Add(wrapper.DistinguishedName, new ResolvedPrincipal { ObjectIdentifier = wrapper.ObjectIdentifier, ObjectType = objectType }); //If the objectidentifier is a SID, cache this mapping too if (objectIdentifier.StartsWith("S-1-5")) { Cache.Instance.Add(wrapper.ObjectIdentifier, objectType); } //Return our wrapper for the next step in the pipeline return(wrapper); }
/// <summary> /// Grab properties from GPO objects /// </summary> /// <param name="wrapper"></param> private static void ParseGPOProperties(GPO wrapper) { var result = wrapper.SearchResult; wrapper.Properties.Add("gpcpath", result.GetProperty("gpcfilesyspath")); }
internal static LdapWrapper FindLdapType(SearchResultEntry searchResultEntry) { //Look for a null DN first. Not sure why this would happen. var distinguishedName = searchResultEntry.DistinguishedName; if (distinguishedName == null) { return(null); } var accountName = searchResultEntry.GetProp("samaccountname"); var samAccountType = searchResultEntry.GetProp("samaccounttype"); var accountDomain = Helpers.DistinguishedNameToDomain(distinguishedName); var objectSid = searchResultEntry.GetSid(); var objectType = LdapTypeEnum.Unknown; LdapWrapper wrapper; //Lets see if its a "common" principal if (CommonPrincipal.GetCommonSid(objectSid, out var commonPrincipal)) { accountName = commonPrincipal.Name; objectType = commonPrincipal.Type; } else { //Its not a common principal. Lets use properties to figure out what it actually is if (samAccountType != null) { if (samAccountType == "805306370") { return(null); } objectType = Helpers.SamAccountTypeToType(samAccountType); } else { var objectClasses = searchResultEntry.GetPropArray("objectClass"); if (objectClasses == null) { objectType = LdapTypeEnum.Unknown; } else if (objectClasses.Contains("groupPolicyContainer")) { objectType = LdapTypeEnum.GPO; } else if (objectClasses.Contains("organizationalUnit")) { objectType = LdapTypeEnum.OU; } else if (objectClasses.Contains("domain")) { objectType = LdapTypeEnum.Domain; } } } //Depending on the object type, create the appropriate wrapper object switch (objectType) { case LdapTypeEnum.Computer: accountName = accountName?.TrimEnd('$'); wrapper = new Computer(searchResultEntry) { DisplayName = $"{accountName}.{accountDomain}" }; break; case LdapTypeEnum.User: wrapper = new User(searchResultEntry) { DisplayName = $"{accountName}@{accountDomain}" }; break; case LdapTypeEnum.Group: wrapper = new Group(searchResultEntry) { DisplayName = $"{accountName}@{accountDomain}" }; break; case LdapTypeEnum.GPO: accountName = searchResultEntry.GetProp("displayname"); wrapper = new GPO(searchResultEntry) { DisplayName = $"{accountName}@{accountDomain}" }; break; case LdapTypeEnum.OU: accountName = searchResultEntry.GetProp("name"); wrapper = new OU(searchResultEntry) { DisplayName = $"{accountName}@{accountDomain}" }; break; case LdapTypeEnum.Domain: wrapper = new Domain(searchResultEntry) { DisplayName = accountDomain }; break; case LdapTypeEnum.Unknown: wrapper = null; break; default: throw new ArgumentOutOfRangeException(); } //Set the DN/SID for the wrapper going forward if (wrapper == null) { return(wrapper); } wrapper.DistinguishedName = distinguishedName; wrapper.SecurityIdentifier = objectSid; //Return our wrapper for the next step in the pipeline return(wrapper); }
public static IEnumerable <object> Get_DomainGPO(Args_Get_DomainGPO args = null) { if (args == null) { args = new Args_Get_DomainGPO(); } var SearcherArguments = new Args_Get_DomainSearcher { Domain = args.Domain, Properties = args.Properties, SearchBase = args.SearchBase, Server = args.Server, SearchScope = args.SearchScope, ResultPageSize = args.ResultPageSize, ServerTimeLimit = args.ServerTimeLimit, SecurityMasks = args.SecurityMasks, Tombstone = args.Tombstone, Credential = args.Credential }; var GPOSearcher = GetDomainSearcher.Get_DomainSearcher(SearcherArguments); var GPOs = new List <object>(); if (GPOSearcher != null) { if (args.ComputerIdentity != null || args.UserIdentity != null) { var GPOAdsPaths = new List <string>(); string[] OldProperties = null; if (SearcherArguments.Properties != null) { OldProperties = SearcherArguments.Properties; } SearcherArguments.Properties = new[] { @"distinguishedname", @"dnshostname" }; string TargetComputerName = null; string ObjectDN = null; if (args.ComputerIdentity.IsNotNullOrEmpty()) { var Computer = GetDomainComputer.Get_DomainComputer(new Args_Get_DomainComputer(SearcherArguments) { Identity = new[] { args.ComputerIdentity }, FindOne = true }).First() as LDAPProperty; if (Computer == null) { Logger.Write_Verbose($@"[Get-DomainGPO] Computer '{args.ComputerIdentity}' not found!"); } ObjectDN = Computer.distinguishedname; TargetComputerName = Computer.dnshostname; } else { var User = GetDomainUser.Get_DomainUser(new Args_Get_DomainUser(SearcherArguments) { Identity = new[] { args.UserIdentity }, FindOne = true }) as LDAPProperty; if (User == null) { Logger.Write_Verbose($@"[Get-DomainGPO] User '{args.UserIdentity}' not found!"); } ObjectDN = User.distinguishedname; } // extract all OUs the target user/computer is a part of var ObjectOUs = new List <string>(); foreach (var item in ObjectDN.Split(',')) { if (item.StartsWith(@"OU=")) { ObjectOUs.Add(ObjectDN.Substring(ObjectDN.IndexOf($@"{item},"))); } } Logger.Write_Verbose($@"[Get-DomainGPO] object OUs: {ObjectOUs}"); if (ObjectOUs != null) { // find all the GPOs linked to the user/computer's OUs SearcherArguments.Properties = null; var InheritanceDisabled = false; foreach (var ObjectOU in ObjectOUs) { var ous = GetDomainOU.Get_DomainOU(new Args_Get_DomainOU(SearcherArguments) { Identity = new[] { ObjectOU } }); foreach (LDAPProperty ou in ous) { // extract any GPO links for this particular OU the computer is a part of if (ou.gplink.IsNotNullOrEmpty()) { foreach (var item in ou.gplink.Split(new[] { @"][" }, StringSplitOptions.None)) { if (item.StartsWith(@"LDAP")) { var Parts = item.Split(';'); var GpoDN = Parts[0]; var Enforced = Parts[1]; if (InheritanceDisabled) { // if inheritance has already been disabled and this GPO is set as "enforced" // then add it, otherwise ignore it if (Enforced == @"2") { GPOAdsPaths.Add(GpoDN); } } else { // inheritance not marked as disabled yet GPOAdsPaths.Add(GpoDN); } } } } //if this OU has GPO inheritence disabled, break so additional OUs aren't processed if (ou.gpoptions == 1) { InheritanceDisabled = true; } } } } if (TargetComputerName.IsNotNullOrEmpty()) { // find all the GPOs linked to the computer's site var ComputerSite = GetNetComputerSiteName.Get_NetComputerSiteName(new Args_Get_NetComputerSiteName { ComputerName = new[] { TargetComputerName } }).First().SiteName; if (ComputerSite.IsNotNullOrEmpty() && !ComputerSite.IsLikeMatch(@"Error*")) { var sites = GetDomainSite.Get_DomainSite(new Args_Get_DomainSite(SearcherArguments) { Identity = new[] { ComputerSite } }); foreach (LDAPProperty site in sites) { if (site.gplink.IsNotNullOrEmpty()) { // extract any GPO links for this particular site the computer is a part of foreach (var item in site.gplink.Split(new[] { @"][" }, StringSplitOptions.None)) { if (item.StartsWith(@"LDAP")) { GPOAdsPaths.Add(item.Split(';')[0]); } } } } } } // find any GPOs linked to the user/computer's domain var ObjectDomainDN = ObjectDN.Substring(ObjectDN.IndexOf(@"DC=")); SearcherArguments.Properties = null; SearcherArguments.LDAPFilter = $@"(objectclass=domain)(distinguishedname={ObjectDomainDN})"; var objs = GetDomainObject.Get_DomainObject(new Args_Get_DomainObject(SearcherArguments)); foreach (LDAPProperty obj in objs) { if (obj.gplink.IsNotNullOrEmpty()) { // extract any GPO links for this particular domain the computer is a part of foreach (var item in obj.gplink.Split(new[] { @"][" }, StringSplitOptions.None)) { if (item.StartsWith(@"LDAP")) { GPOAdsPaths.Add(item.Split(';')[0]); } } } } Logger.Write_Verbose($@"[Get-DomainGPO] GPOAdsPaths: {GPOAdsPaths}"); // restore the old properites to return, if set if (OldProperties != null) { SearcherArguments.Properties = OldProperties; } else { SearcherArguments.Properties = null; } foreach (var path in GPOAdsPaths.Where(x => x != null && x != "")) { // use the gplink as an ADS path to enumerate all GPOs for the computer SearcherArguments.SearchBase = path; SearcherArguments.LDAPFilter = @"(objectCategory=groupPolicyContainer)"; objs = GetDomainObject.Get_DomainObject(new Args_Get_DomainObject(SearcherArguments)); foreach (LDAPProperty obj in objs) { GPOs.Add(new GPO(obj)); } } } else { var IdentityFilter = @""; var Filter = @""; if (args.Identity != null) { foreach (var item in args.Identity) { var IdentityInstance = item.Replace(@"(", @"\28").Replace(@")", @"\29"); if (IdentityInstance.IsRegexMatch(@"LDAP://|^CN=.*")) { IdentityFilter += $@"(distinguishedname={IdentityInstance})"; if (args.Domain.IsNullOrEmpty() && args.SearchBase.IsNullOrEmpty()) { // if a -Domain isn't explicitly set, extract the object domain out of the distinguishedname // and rebuild the domain searcher var IdentityDomain = IdentityInstance.Substring(IdentityInstance.IndexOf(@"DC=")).Replace(@"DC=", @"").Replace(@",", @"."); Logger.Write_Verbose($@"[Get-DomainGPO] Extracted domain '{IdentityDomain}' from '{IdentityInstance}'"); SearcherArguments.Domain = IdentityDomain; GPOSearcher = GetDomainSearcher.Get_DomainSearcher(SearcherArguments); if (GPOSearcher == null) { Logger.Write_Warning($@"[Get-DomainGPO] Unable to retrieve domain searcher for '{IdentityDomain}'"); } } } else if (IdentityInstance.IsRegexMatch(@"{.*}")) { IdentityFilter += $@"(name={IdentityInstance})"; } else { try { var GuidByteString = string.Join(string.Empty, Guid.Parse(IdentityInstance).ToByteArray().Select(x => x.ToString(@"\X2"))); IdentityFilter += $@"(objectguid={GuidByteString})"; } catch { IdentityFilter += $@"(displayname={IdentityInstance})"; } } } } if (IdentityFilter != null && IdentityFilter.Trim() != @"") { Filter += $@"(|{IdentityFilter})"; } if (args.LDAPFilter.IsNotNullOrEmpty()) { Logger.Write_Verbose($@"[Get-DomainGPO] Using additional LDAP filter: {args.LDAPFilter}"); Filter += $@"{args.LDAPFilter}"; } GPOSearcher.Filter = $@"(&(objectCategory=groupPolicyContainer){Filter})"; Logger.Write_Verbose($@"[Get-DomainGPO] filter string: {GPOSearcher.Filter}"); SearchResult[] Results = null; if (args.FindOne) { Results = new SearchResult[] { GPOSearcher.FindOne() }; } else { var items = GPOSearcher.FindAll(); if (items != null) { Results = new SearchResult[items.Count]; items.CopyTo(Results, 0); } } if (Results != null) { foreach (var result in Results) { if (args.Raw) { // return raw result objects GPOs.Add(result); } else { GPO GPO; if (args.SearchBase.IsNotNullOrEmpty() && args.SearchBase.IsRegexMatch(@"^GC://")) { GPO = new GPO(ConvertLDAPProperty.Convert_LDAPProperty(result.Properties)); try { var GPODN = GPO.distinguishedname; var GPODomain = GPODN.Substring(GPODN.IndexOf(@"DC=")).Replace(@"DC=", @"").Replace(@",", @"."); var gpcfilesyspath = $@"\\{GPODomain}\SysVol\{GPODomain}\Policies\{GPO.cn}"; GPO.gpcfilesyspath = gpcfilesyspath; } catch { Logger.Write_Verbose($@"[Get-DomainGPO] Error calculating gpcfilesyspath for: {GPO.distinguishedname}"); } } else { GPO = new GPO(ConvertLDAPProperty.Convert_LDAPProperty(result.Properties)); } GPOs.Add(GPO); } } } } GPOSearcher.Dispose(); } return(GPOs); }