public static IEnumerable <object> Find_DomainUserEvent(Args_Find_DomainUserEvent args = null) { if (args == null) { args = new Args_Find_DomainUserEvent(); } var UserSearcherArguments = new Args_Get_DomainUser { Properties = new[] { "samaccountname" }, Identity = args.UserIdentity, Domain = args.UserDomain, LDAPFilter = args.UserLDAPFilter, SearchBase = args.UserSearchBase, AdminCount = args.UserAdminCount, Server = args.Server, SearchScope = args.SearchScope, ResultPageSize = args.ResultPageSize, ServerTimeLimit = args.ServerTimeLimit, Tombstone = args.Tombstone, Credential = args.Credential }; string[] TargetUsers = null; if (args.UserIdentity != null || !string.IsNullOrEmpty(args.UserLDAPFilter) || !string.IsNullOrEmpty(args.UserSearchBase) || args.UserAdminCount) { TargetUsers = GetDomainUser.Get_DomainUser(UserSearcherArguments).Select(x => (x as LDAPProperty).samaccountname).ToArray(); } else if (args.UserGroupIdentity != null || (args.Filter == null)) { // otherwise we're querying a specific group var GroupSearcherArguments = new Args_Get_DomainGroupMember { Identity = args.UserGroupIdentity, Recurse = true, Domain = args.UserDomain, SearchBase = args.UserSearchBase, Server = args.Server, SearchScope = args.SearchScope, ResultPageSize = args.ResultPageSize, ServerTimeLimit = args.ServerTimeLimit, Tombstone = args.Tombstone, Credential = args.Credential }; Logger.Write_Verbose($@"UserGroupIdentity: {args.UserGroupIdentity.ToJoinedString()}"); TargetUsers = GetDomainGroupMember.Get_DomainGroupMember(GroupSearcherArguments).Select(x => x.MemberName).ToArray(); } // build the set of computers to enumerate string[] TargetComputers = null; if (args.ComputerName != null) { TargetComputers = args.ComputerName; } else { // if not -ComputerName is passed, query the current (or target) domain for domain controllers var DCSearcherArguments = new Args_Get_DomainController { LDAP = true, Domain = args.Domain, Server = args.Server, Credential = args.Credential }; Logger.Write_Verbose($@"[Find-DomainUserEvent] Querying for domain controllers in domain: {args.Domain}"); TargetComputers = GetDomainController.Get_DomainController(DCSearcherArguments).Select(x => (x as LDAPProperty).dnshostname).ToArray(); } Logger.Write_Verbose($@"[Find-DomainUserEvent] TargetComputers length: {TargetComputers.Count()}"); Logger.Write_Verbose($@"[Find-DomainUserEvent] TargetComputers {TargetComputers.ToJoinedString()}"); if (TargetComputers == null || TargetComputers.Length == 0) { throw new Exception("[Find-DomainUserEvent] No hosts found to enumerate"); } var rets = new List <IWinEvent>(); // only ignore threading if -Delay is passed if (args.Delay != 0 || args.StopOnSuccess) { Logger.Write_Verbose($@"[Find-DomainUserEvent] TargetComputers length: {TargetComputers.Length}"); Logger.Write_Verbose($@"[Find-DomainUserEvent] Delay: {args.Delay}, Jitter: {args.Jitter}"); var Counter = 0; var RandNo = new System.Random(); foreach (var TargetComputer in TargetComputers) { Counter = Counter + 1; // sleep for our semi-randomized interval System.Threading.Thread.Sleep(RandNo.Next((int)((1 - args.Jitter) * args.Delay), (int)((1 + args.Jitter) * args.Delay)) * 1000); Logger.Write_Verbose($@"[Find-DomainUserEvent] Enumerating server {TargetComputer} ({Counter} of {TargetComputers.Count()})"); var Result = _Find_DomainUserEvent(new[] { TargetComputer }, args.StartTime, args.EndTime, args.MaxEvents, TargetUsers, args.Filter, args.Credential); if (Result != null) { rets.AddRange(Result); } if (Result != null && args.StopOnSuccess) { Logger.Write_Verbose("[Find-DomainUserEvent] Target user found, returning early"); return(rets); } } } else { Logger.Write_Verbose($@"[Find-DomainUserEvent] Using threading with threads: {args.Threads}"); // if we're using threading, kick off the script block with New-ThreadedFunction // if we're using threading, kick off the script block with New-ThreadedFunction using the $HostEnumBlock + params System.Threading.Tasks.Parallel.ForEach( TargetComputers, TargetComputer => { var Result = _Find_DomainUserEvent(new[] { TargetComputer }, args.StartTime, args.EndTime, args.MaxEvents, TargetUsers, args.Filter, args.Credential); lock (rets) { if (Result != null) { rets.AddRange(Result); } } }); } return(rets); }
public static IEnumerable <UserProcess> Find_DomainProcess(Args_Find_DomainProcess args = null) { if (args == null) { args = new Args_Find_DomainProcess(); } var ComputerSearcherArguments = new Args_Get_DomainComputer { Properties = new[] { "dnshostname" }, Domain = args.Domain, LDAPFilter = args.ComputerLDAPFilter, SearchBase = args.ComputerSearchBase, Unconstrained = args.Unconstrained, OperatingSystem = args.OperatingSystem, ServicePack = args.ServicePack, SiteName = args.SiteName, Server = args.Server, SearchScope = args.SearchScope, ResultPageSize = args.ResultPageSize, ServerTimeLimit = args.ServerTimeLimit, Tombstone = args.Tombstone, Credential = args.Credential }; if (!string.IsNullOrEmpty(args.ComputerDomain)) { ComputerSearcherArguments.Domain = args.ComputerDomain; } var UserSearcherArguments = new Args_Get_DomainUser { Properties = new[] { "samaccountname" }, Identity = args.UserIdentity, Domain = args.Domain, LDAPFilter = args.UserLDAPFilter, SearchBase = args.UserSearchBase, AdminCount = args.UserAdminCount, Server = args.Server, SearchScope = args.SearchScope, ResultPageSize = args.ResultPageSize, ServerTimeLimit = args.ServerTimeLimit, Tombstone = args.Tombstone, Credential = args.Credential }; if (!string.IsNullOrEmpty(args.UserDomain)) { UserSearcherArguments.Domain = args.UserDomain; } // first, build the set of computers to enumerate string[] TargetComputers = null; if (args.ComputerName != null) { TargetComputers = args.ComputerName; } else { Logger.Write_Verbose(@"[Find-DomainProcess] Querying computers in the domain"); TargetComputers = GetDomainComputer.Get_DomainComputer(ComputerSearcherArguments).Select(x => (x as LDAPProperty).dnshostname).ToArray(); } if (TargetComputers == null || TargetComputers.Length == 0) { throw new Exception("[Find-DomainProcess] No hosts found to enumerate"); } Logger.Write_Verbose($@"[Find-DomainProcess] TargetComputers length: {TargetComputers.Length}"); // now build the user target set List <string> TargetProcessName = null; string[] TargetUsers = null; if (args.ProcessName != null) { TargetProcessName = new List <string>(); foreach (var T in args.ProcessName) { TargetProcessName.AddRange(T.Split(',')); } } else if (args.UserIdentity != null || args.UserLDAPFilter != null || args.UserSearchBase != null || args.UserAdminCount /* || args.UserAllowDelegation*/) { TargetUsers = GetDomainUser.Get_DomainUser(UserSearcherArguments).Select(x => (x as LDAPProperty).samaccountname).ToArray(); } else { var GroupSearcherArguments = new Args_Get_DomainGroupMember { Identity = args.UserGroupIdentity, Recurse = true, Domain = args.UserDomain, SearchBase = args.UserSearchBase, Server = args.Server, SearchScope = args.SearchScope, ResultPageSize = args.ResultPageSize, ServerTimeLimit = args.ServerTimeLimit, Tombstone = args.Tombstone, Credential = args.Credential }; TargetUsers = GetDomainGroupMember.Get_DomainGroupMember(GroupSearcherArguments).Select(x => x.MemberName).ToArray(); } var rets = new List <UserProcess>(); // only ignore threading if -Delay is passed if (args.Delay != 0 || args.StopOnSuccess) { Logger.Write_Verbose($@"[Find-DomainProcess] Total number of hosts: {TargetComputers.Count()}"); Logger.Write_Verbose($@"[Find-DomainProcess] Delay: {args.Delay}, Jitter: {args.Jitter}"); var Counter = 0; var RandNo = new System.Random(); foreach (var TargetComputer in TargetComputers) { Counter = Counter + 1; // sleep for our semi-randomized interval System.Threading.Thread.Sleep(RandNo.Next((int)((1 - args.Jitter) * args.Delay), (int)((1 + args.Jitter) * args.Delay)) * 1000); Logger.Write_Verbose($@"[Find-DomainProcess] Enumerating server {TargetComputer} ({Counter} of {TargetComputers.Count()})"); var Result = _Find_DomainProcess(new[] { TargetComputer }, TargetProcessName?.ToArray(), TargetUsers, args.Credential); if (Result != null) { rets.AddRange(Result); } if (Result != null && args.StopOnSuccess) { Logger.Write_Verbose("[Find-DomainProcess] Target user found, returning early"); return(rets); } } } else { Logger.Write_Verbose($@"[Find-DomainProcess] Using threading with threads: {args.Threads}"); // if we're using threading, kick off the script block with New-ThreadedFunction // if we're using threading, kick off the script block with New-ThreadedFunction using the $HostEnumBlock + params System.Threading.Tasks.Parallel.ForEach( TargetComputers, TargetComputer => { var Result = _Find_DomainProcess(new[] { TargetComputer }, TargetProcessName?.ToArray(), TargetUsers, args.Credential); lock (rets) { if (Result != null) { rets.AddRange(Result); } } }); } return(rets); }
public static IEnumerable <GroupMember> Get_NetGroupMember(Args_Get_DomainGroupMember args = null) { return(GetDomainGroupMember.Get_DomainGroupMember(args)); }
public static IEnumerable <UserLocation> Find_DomainUserLocation(Args_Find_DomainUserLocation args = null) { if (args == null) { args = new Args_Find_DomainUserLocation(); } var ComputerSearcherArguments = new Args_Get_DomainComputer { Properties = new[] { "dnshostname" }, Domain = args.Domain, LDAPFilter = args.ComputerLDAPFilter, SearchBase = args.ComputerSearchBase, Unconstrained = args.Unconstrained, OperatingSystem = args.OperatingSystem, ServicePack = args.ServicePack, SiteName = args.SiteName, Server = args.Server, SearchScope = args.SearchScope, ResultPageSize = args.ResultPageSize, ServerTimeLimit = args.ServerTimeLimit, Tombstone = args.Tombstone, Credential = args.Credential }; if (!string.IsNullOrEmpty(args.ComputerDomain)) { ComputerSearcherArguments.Domain = args.ComputerDomain; } var UserSearcherArguments = new Args_Get_DomainUser { Properties = new[] { "samaccountname" }, Identity = args.UserIdentity, Domain = args.Domain, LDAPFilter = args.UserLDAPFilter, SearchBase = args.UserSearchBase, AdminCount = args.UserAdminCount, AllowDelegation = args.AllowDelegation, Server = args.Server, SearchScope = args.SearchScope, ResultPageSize = args.ResultPageSize, ServerTimeLimit = args.ServerTimeLimit, Tombstone = args.Tombstone, Credential = args.Credential }; if (!string.IsNullOrEmpty(args.UserDomain)) { UserSearcherArguments.Domain = args.UserDomain; } string[] TargetComputers = null; // first, build the set of computers to enumerate if (args.ComputerName != null) { TargetComputers = args.ComputerName; } else { if (args.Stealth) { Logger.Write_Verbose($@"[Find-DomainUserLocation] Stealth enumeration using source: {args.StealthSource}"); var TargetComputerArrayList = new System.Collections.ArrayList(); if (args.StealthSource.ToString().IsRegexMatch("File|All")) { Logger.Write_Verbose("[Find-DomainUserLocation] Querying for file servers"); var FileServerSearcherArguments = new Args_Get_DomainFileServer { Domain = new[] { args.Domain }, SearchBase = args.ComputerSearchBase, Server = args.Server, SearchScope = args.SearchScope, ResultPageSize = args.ResultPageSize, ServerTimeLimit = args.ServerTimeLimit, Tombstone = args.Tombstone, Credential = args.Credential }; if (!string.IsNullOrEmpty(args.ComputerDomain)) { FileServerSearcherArguments.Domain = new[] { args.ComputerDomain } } ; var FileServers = GetDomainFileServer.Get_DomainFileServer(FileServerSearcherArguments); TargetComputerArrayList.AddRange(FileServers); } if (args.StealthSource.ToString().IsRegexMatch("DFS|All")) { Logger.Write_Verbose(@"[Find-DomainUserLocation] Querying for DFS servers"); // { TODO: fix the passed parameters to Get-DomainDFSShare // $ComputerName += Get-DomainDFSShare -Domain $Domain -Server $DomainController | ForEach-Object {$_.RemoteServerName} } if (args.StealthSource.ToString().IsRegexMatch("DC|All")) { Logger.Write_Verbose(@"[Find-DomainUserLocation] Querying for domain controllers"); var DCSearcherArguments = new Args_Get_DomainController { LDAP = true, Domain = args.Domain, Server = args.Server, Credential = args.Credential }; if (!string.IsNullOrEmpty(args.ComputerDomain)) { DCSearcherArguments.Domain = args.ComputerDomain; } var DomainControllers = GetDomainController.Get_DomainController(DCSearcherArguments).Select(x => (x as LDAPProperty).dnshostname).ToArray(); TargetComputerArrayList.AddRange(DomainControllers); } TargetComputers = TargetComputerArrayList.ToArray() as string[]; } } if (args.ComputerName != null) { TargetComputers = args.ComputerName; } else { if (args.Stealth) { Logger.Write_Verbose($@"[Find-DomainUserLocation] Stealth enumeration using source: {args.StealthSource}"); var TargetComputerArrayList = new System.Collections.ArrayList(); if (args.StealthSource.ToString().IsRegexMatch("File|All")) { Logger.Write_Verbose("[Find-DomainUserLocation] Querying for file servers"); var FileServerSearcherArguments = new Args_Get_DomainFileServer { Domain = new[] { args.Domain }, SearchBase = args.ComputerSearchBase, Server = args.Server, SearchScope = args.SearchScope, ResultPageSize = args.ResultPageSize, ServerTimeLimit = args.ServerTimeLimit, Tombstone = args.Tombstone, Credential = args.Credential }; if (!string.IsNullOrEmpty(args.ComputerDomain)) { FileServerSearcherArguments.Domain = new[] { args.ComputerDomain } } ; var FileServers = GetDomainFileServer.Get_DomainFileServer(FileServerSearcherArguments); TargetComputerArrayList.AddRange(FileServers); } if (args.StealthSource.ToString().IsRegexMatch("DFS|All")) { Logger.Write_Verbose(@"[Find-DomainUserLocation] Querying for DFS servers"); // { TODO: fix the passed parameters to Get-DomainDFSShare // $ComputerName += Get-DomainDFSShare -Domain $Domain -Server $DomainController | ForEach-Object {$_.RemoteServerName} } if (args.StealthSource.ToString().IsRegexMatch("DC|All")) { Logger.Write_Verbose(@"[Find-DomainUserLocation] Querying for domain controllers"); var DCSearcherArguments = new Args_Get_DomainController { LDAP = true, Domain = args.Domain, Server = args.Server, Credential = args.Credential }; if (!string.IsNullOrEmpty(args.ComputerDomain)) { DCSearcherArguments.Domain = args.ComputerDomain; } var DomainControllers = GetDomainController.Get_DomainController(DCSearcherArguments).Select(x => (x as LDAPProperty).dnshostname).ToArray(); TargetComputerArrayList.AddRange(DomainControllers); } TargetComputers = TargetComputerArrayList.ToArray() as string[]; } else { Logger.Write_Verbose("[Find-DomainUserLocation] Querying for all computers in the domain"); TargetComputers = GetDomainComputer.Get_DomainComputer(ComputerSearcherArguments).Select(x => (x as LDAPProperty).dnshostname).ToArray(); } } Logger.Write_Verbose($@"[Find-DomainUserLocation] TargetComputers length: {TargetComputers.Length}"); if (TargetComputers.Length == 0) { throw new Exception("[Find-DomainUserLocation] No hosts found to enumerate"); } // get the current user so we can ignore it in the results string CurrentUser; if (args.Credential != null) { CurrentUser = args.Credential.UserName; } else { CurrentUser = Environment.UserName.ToLower(); } // now build the user target set string[] TargetUsers = null; if (args.ShowAll) { TargetUsers = new string[] { }; } else if (args.UserIdentity != null || args.UserLDAPFilter != null || args.UserSearchBase != null || args.UserAdminCount || args.UserAllowDelegation) { TargetUsers = GetDomainUser.Get_DomainUser(UserSearcherArguments).Select(x => (x as LDAPProperty).samaccountname).ToArray(); } else { var GroupSearcherArguments = new Args_Get_DomainGroupMember { Identity = args.UserGroupIdentity, Recurse = true, Domain = args.UserDomain, SearchBase = args.UserSearchBase, Server = args.Server, SearchScope = args.SearchScope, ResultPageSize = args.ResultPageSize, ServerTimeLimit = args.ServerTimeLimit, Tombstone = args.Tombstone, Credential = args.Credential }; TargetUsers = GetDomainGroupMember.Get_DomainGroupMember(GroupSearcherArguments).Select(x => x.MemberName).ToArray(); } Logger.Write_Verbose($@"[Find-DomainUserLocation] TargetUsers length: {TargetUsers.Length}"); if ((!args.ShowAll) && (TargetUsers.Length == 0)) { throw new Exception("[Find-DomainUserLocation] No users found to target"); } var LogonToken = IntPtr.Zero; if (args.Credential != null) { if (args.Delay != 0 || args.StopOnSuccess) { LogonToken = InvokeUserImpersonation.Invoke_UserImpersonation(new Args_Invoke_UserImpersonation { Credential = args.Credential }); } else { LogonToken = InvokeUserImpersonation.Invoke_UserImpersonation(new Args_Invoke_UserImpersonation { Credential = args.Credential, Quiet = true }); } } var rets = new List <UserLocation>(); // only ignore threading if -Delay is passed if (args.Delay != 0 /* || args.StopOnSuccess*/) { Logger.Write_Verbose($@"[Find-DomainUserLocation] Total number of hosts: {TargetComputers.Count()}"); Logger.Write_Verbose($@"[Find-DomainUserLocation] Delay: {args.Delay}, Jitter: {args.Jitter}"); var Counter = 0; var RandNo = new System.Random(); foreach (var TargetComputer in TargetComputers) { Counter = Counter + 1; // sleep for our semi-randomized interval System.Threading.Thread.Sleep(RandNo.Next((int)((1 - args.Jitter) * args.Delay), (int)((1 + args.Jitter) * args.Delay)) * 1000); Logger.Write_Verbose($@"[Find-DomainUserLocation] Enumerating server {TargetComputer} ({Counter} of {TargetComputers.Count()})"); var Result = _Find_DomainUserLocation(new[] { TargetComputer }, TargetUsers, CurrentUser, args.Stealth, args.CheckAccess, LogonToken); if (Result != null) { rets.AddRange(Result); } if (Result != null && args.StopOnSuccess) { Logger.Write_Verbose("[Find-DomainUserLocation] Target user found, returning early"); return(rets); } } } else { Logger.Write_Verbose($@"[Find-DomainUserLocation] Using threading with threads: {args.Threads}"); Logger.Write_Verbose($@"[Find-DomainUserLocation] TargetComputers length: {TargetComputers.Length}"); // if we're using threading, kick off the script block with New-ThreadedFunction // if we're using threading, kick off the script block with New-ThreadedFunction using the $HostEnumBlock + params System.Threading.Tasks.Parallel.ForEach( TargetComputers, TargetComputer => { var Result = _Find_DomainUserLocation(new[] { TargetComputer }, TargetUsers, CurrentUser, args.Stealth, args.CheckAccess, LogonToken); lock (rets) { if (Result != null) { rets.AddRange(Result); } } }); } if (LogonToken != IntPtr.Zero) { InvokeRevertToSelf.Invoke_RevertToSelf(LogonToken); } return(rets); }
public static IEnumerable <GroupMember> Get_DomainGroupMember(Args_Get_DomainGroupMember args = null) { if (args == null) { args = new Args_Get_DomainGroupMember(); } var SearcherArguments = new Args_Get_DomainSearcher() { Properties = new string[] { @"member", @"samaccountname", @"distinguishedname" }, Domain = args.Domain, LDAPFilter = args.LDAPFilter, SearchBase = args.SearchBase, Server = args.Server, SearchScope = args.SearchScope, ResultPageSize = args.ResultPageSize, ServerTimeLimit = args.ServerTimeLimit, Tombstone = args.Tombstone, Credential = args.Credential }; var ADNameArguments = new Args_Convert_ADName { Domain = args.Domain, Server = args.Server, Credential = args.Credential }; var GroupMembers = new List <GroupMember>(); var GroupSearcher = GetDomainSearcher.Get_DomainSearcher(SearcherArguments); if (GroupSearcher != null) { string GroupFoundDomain = null; string GroupFoundName = null; string GroupFoundDN = null; List <string> Members = null; if (args.RecurseUsingMatchingRule) { var GroupArguments = new Args_Get_DomainGroup() { Properties = SearcherArguments.Properties, Domain = SearcherArguments.Domain, LDAPFilter = SearcherArguments.LDAPFilter, SearchBase = SearcherArguments.SearchBase, Server = SearcherArguments.Server, SearchScope = SearcherArguments.SearchScope, ResultPageSize = SearcherArguments.ResultPageSize, ServerTimeLimit = SearcherArguments.ServerTimeLimit, Tombstone = SearcherArguments.Tombstone, Credential = SearcherArguments.Credential, Identity = args.Identity, Raw = true }; var Groups = GetDomainGroup.Get_DomainGroup(GroupArguments); if (Groups == null) { Logger.Write_Warning($@"[Get-DomainGroupMember] Error searching for group with identity: {args.Identity}"); } else { var Group = Groups.First() as SearchResult; GroupFoundName = Group.Properties[@"samaccountname"][0] as string; GroupFoundDN = Group.Properties[@"distinguishedname"][0] as string; if (args.Domain.IsNotNullOrEmpty()) { GroupFoundDomain = args.Domain; } else { // if a domain isn't passed, try to extract it from the found group distinguished name if (GroupFoundDN.IsNotNullOrEmpty()) { GroupFoundDomain = GroupFoundDN.Substring(GroupFoundDN.IndexOf(@"DC=")).Replace(@"DC=", @"").Replace(@",", @"."); } } Logger.Write_Verbose($@"[Get-DomainGroupMember] Using LDAP matching rule to recurse on '{GroupFoundDN}', only user accounts will be returned."); GroupSearcher.Filter = $@"(&(samAccountType=805306368)(memberof:1.2.840.113556.1.4.1941:={GroupFoundDN}))"; GroupSearcher.PropertiesToLoad.AddRange(new string[] { @"distinguishedName" }); var Results = GroupSearcher.FindAll(); if (Results != null) { Members = new List <string>(); foreach (SearchResult result in Results) { Members.Add(result.Properties[@"distinguishedname"][0] as string); } } } } else { var IdentityFilter = @""; var Filter = @""; if (args.Identity != null) { foreach (var item in args.Identity) { var IdentityInstance = item.Replace(@"(", @"\28").Replace(@")", @"\29"); if (new Regex(@"^S-1-").Match(IdentityInstance).Success) { IdentityFilter += $@"(objectsid={IdentityInstance})"; } else if (new Regex(@"^CN=").Match(IdentityInstance).Success) { 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-DomainGroupMember] Extracted domain '{IdentityDomain}' from '{IdentityInstance}'"); SearcherArguments.Domain = IdentityDomain; GroupSearcher = GetDomainSearcher.Get_DomainSearcher(SearcherArguments); if (GroupSearcher == null) { Logger.Write_Warning($@"[Get-DomainGroupMember] Unable to retrieve domain searcher for '{IdentityDomain}'"); } } } else if (new Regex(@"^[0-9A-F]{8}-([0-9A-F]{4}-){3}[0-9A-F]{12}$").Match(IdentityInstance).Success) { var GuidByteString = string.Join(string.Empty, Guid.Parse(IdentityInstance).ToByteArray().Select(x => x.ToString(@"\X2"))); IdentityFilter += $@"(objectguid={GuidByteString})"; } else if (IdentityInstance.Contains(@"\")) { var ConvertedIdentityInstance = ConvertADName.Convert_ADName(new Args_Convert_ADName { OutputType = ADSNameType.Canonical, Identity = new string[] { IdentityInstance.Replace(@"\28", @"(").Replace(@"\29", @")") } }); if (ConvertedIdentityInstance != null && ConvertedIdentityInstance.Any()) { var GroupDomain = ConvertedIdentityInstance.First().Substring(0, ConvertedIdentityInstance.First().IndexOf('/')); var GroupName = IdentityInstance.Split(new char[] { '\\' })[1]; IdentityFilter += $@"(samAccountName={GroupName})"; SearcherArguments.Domain = GroupDomain; Logger.Write_Verbose($@"[Get-DomainGroupMember] Extracted domain '{GroupDomain}' from '{IdentityInstance}'"); GroupSearcher = GetDomainSearcher.Get_DomainSearcher(SearcherArguments); } } else { IdentityFilter += $@"(samAccountName={IdentityInstance})"; } } } if (IdentityFilter != null && IdentityFilter.Trim() != @"") { Filter += $@"(|{IdentityFilter})"; } if (args.LDAPFilter.IsNotNullOrEmpty()) { Logger.Write_Verbose($@"[Get-DomainGroupMember] Using additional LDAP filter: {args.LDAPFilter}"); Filter += $@"{args.LDAPFilter}"; } GroupSearcher.Filter = $@"(&(objectCategory=group){Filter})"; Logger.Write_Verbose($@"[Get-DomainGroupMember] Get-DomainGroupMember filter string: {GroupSearcher.Filter}"); SearchResult Result = null; try { Result = GroupSearcher.FindOne(); } catch (Exception e) { Logger.Write_Warning($@"[Get-DomainGroupMember] Error searching for group with identity '{args.Identity}': {e}"); Members = new List <string>(); } GroupFoundName = @""; GroupFoundDN = @""; if (Result != null) { var tmpProperty = Result.Properties[@"member"]; var tmpValues = new string[tmpProperty.Count]; tmpProperty.CopyTo(tmpValues, 0); Members = tmpValues.ToList(); string RangedProperty = ""; if (Members.Count == 0) { // ranged searching, thanks @meatballs__ ! var Finished = false; var Bottom = 0; var Top = 0; while (!Finished) { Top = Bottom + 1499; var MemberRange = $@"member;range={Bottom}-{Top}"; Bottom += 1500; GroupSearcher.PropertiesToLoad.Clear(); GroupSearcher.PropertiesToLoad.Add($@"{MemberRange}"); GroupSearcher.PropertiesToLoad.Add(@"samaccountname"); GroupSearcher.PropertiesToLoad.Add(@"distinguishedname"); try { Result = GroupSearcher.FindOne(); RangedProperty = Result.Properties.PropertyNames.GetFirstMatch(@"member;range=*"); tmpProperty = Result.Properties[RangedProperty]; tmpValues = new string[tmpProperty.Count]; tmpProperty.CopyTo(tmpValues, 0); Members.AddRange(tmpValues.ToList()); GroupFoundName = Result.Properties[@"samaccountname"][0] as string; GroupFoundDN = Result.Properties[@"distinguishedname"][0] as string; if (Members.Count == 0) { Finished = true; } } catch { Finished = true; } } } else { GroupFoundName = Result.Properties[@"samaccountname"][0] as string; GroupFoundDN = Result.Properties[@"distinguishedname"][0] as string; tmpProperty = Result.Properties[RangedProperty]; tmpValues = new string[tmpProperty.Count]; tmpProperty.CopyTo(tmpValues, 0); Members.AddRange(tmpValues.ToList()); } if (args.Domain.IsNotNullOrEmpty()) { GroupFoundDomain = args.Domain; } else { // if a domain isn't passed, try to extract it from the found group distinguished name if (GroupFoundDN.IsNotNullOrEmpty()) { GroupFoundDomain = GroupFoundDN.Substring(GroupFoundDN.IndexOf(@"DC=")).Replace(@"DC=", @"".Replace(@",", @".")); } } } var UseMatchingRule = false; string MemberDomain = null; foreach (var Member in Members) { ResultPropertyCollection Properties = null; if (args.Recurse && UseMatchingRule) { //$Properties = $_.Properties } else { var ObjectSearcherArguments = new Args_Get_DomainObject { ADSPath = SearcherArguments.ADSPath, Credential = SearcherArguments.Credential, Domain = SearcherArguments.Domain, DomainController = SearcherArguments.DomainController, Filter = SearcherArguments.Filter, LDAPFilter = SearcherArguments.LDAPFilter, Properties = SearcherArguments.Properties, ResultPageSize = SearcherArguments.ResultPageSize, SearchBase = SearcherArguments.SearchBase, SearchScope = SearcherArguments.SearchScope, SecurityMasks = SearcherArguments.SecurityMasks, Server = SearcherArguments.Server, ServerTimeLimit = SearcherArguments.ServerTimeLimit, Tombstone = SearcherArguments.Tombstone }; ObjectSearcherArguments.Identity = new string[] { Member }; ObjectSearcherArguments.Raw = true; ObjectSearcherArguments.Properties = new string[] { @"distinguishedname", @"cn", @"samaccountname", @"objectsid", @"objectclass" }; var Object = GetDomainObject.Get_DomainObject(ObjectSearcherArguments)?.FirstOrDefault() as SearchResult; Properties = Object.Properties; } if (Properties != null) { var GroupMember = new GroupMember { GroupDomain = GroupFoundDomain, GroupName = GroupFoundName, GroupDistinguishedName = GroupFoundDN }; string MemberSID = null; if (Properties["objectsid"] != null) { MemberSID = new System.Security.Principal.SecurityIdentifier(Properties["objectsid"][0] as byte[], 0).Value; } else { MemberSID = null; } string MemberDN = null; try { MemberDN = Properties["distinguishedname"][0].ToString(); if (MemberDN.IsRegexMatch(@"ForeignSecurityPrincipals|S-1-5-21")) { try { if (MemberSID.IsNullOrEmpty()) { MemberSID = Properties["cn"][0].ToString(); } ADNameArguments.Identity = new string[] { MemberSID }; ADNameArguments.OutputType = ADSNameType.DomainSimple; var MemberSimpleName = ConvertADName.Convert_ADName(ADNameArguments); if (MemberSimpleName != null && MemberSimpleName.Any()) { MemberDomain = MemberSimpleName.First().Split('@')[1]; } else { Logger.Write_Warning($@"[Get-DomainGroupMember] Error converting {MemberDN}"); MemberDomain = null; } } catch { Logger.Write_Warning($@"[Get-DomainGroupMember] Error converting {MemberDN}"); MemberDomain = null; } } else { // extract the FQDN from the Distinguished Name MemberDomain = MemberDN.Substring(MemberDN.IndexOf(@"DC=")).Replace(@"DC=", @"").Replace(@",", @"."); } } catch { MemberDN = null; MemberDomain = null; } string MemberName = null; if (Properties["samaccountname"] != null) { // forest users have the samAccountName set MemberName = Properties["samaccountname"][0].ToString(); } else { // external trust users have a SID, so convert it try { MemberName = ConvertFromSID.ConvertFrom_SID(new Args_ConvertFrom_SID { ObjectSID = new string[] { Properties["cn"][0].ToString() }, Domain = ADNameArguments.Domain, Server = ADNameArguments.Server, Credential = ADNameArguments.Credential }).First(); } catch { // if there's a problem contacting the domain to resolve the SID MemberName = Properties["cn"][0].ToString(); } } string MemberObjectClass = null; if (Properties["objectclass"].RegexContains(@"computer")) { MemberObjectClass = @"computer"; } else if (Properties["objectclass"].RegexContains(@"group")) { MemberObjectClass = @"group"; } else if (Properties["objectclass"].RegexContains(@"user")) { MemberObjectClass = @"user"; } else { MemberObjectClass = null; } GroupMember.MemberDomain = MemberDomain; GroupMember.MemberName = MemberName; GroupMember.MemberDistinguishedName = MemberDN; GroupMember.MemberObjectClass = MemberObjectClass; GroupMember.MemberSID = MemberSID; GroupMembers.Add(GroupMember); // if we're doing manual recursion if (args.Recurse && MemberDN.IsNotNullOrEmpty() && MemberObjectClass.IsRegexMatch(@"group")) { Logger.Write_Verbose($@"[Get-DomainGroupMember] Manually recursing on group: {MemberDN}"); var GroupArguments = new Args_Get_DomainGroupMember() { Domain = SearcherArguments.Domain, LDAPFilter = SearcherArguments.LDAPFilter, SearchBase = SearcherArguments.SearchBase, Server = SearcherArguments.Server, SearchScope = SearcherArguments.SearchScope, ResultPageSize = SearcherArguments.ResultPageSize, ServerTimeLimit = SearcherArguments.ServerTimeLimit, Tombstone = SearcherArguments.Tombstone, Credential = SearcherArguments.Credential, Identity = new string[] { MemberDN } }; GroupMembers.AddRange(Get_DomainGroupMember(GroupArguments)); } } } } GroupSearcher.Dispose(); } return(GroupMembers); }