internal static async Task <LdapWrapper> ResolveObjectProperties(LdapWrapper wrapper) { var result = wrapper.SearchResult; wrapper.Properties.Add("description", result.GetProperty("description")); if (wrapper is Domain domain) { ParseDomainProperties(domain); } else if (wrapper is Computer computer) { await ParseComputerProperties(computer); } else if (wrapper is User user) { await ParseUserProperties(user); } else if (wrapper is GPO gpo) { ParseGPOProperties(gpo); } else if (wrapper is OU ou) { ParseOUProperties(ou); } else if (wrapper is Group group) { ParseGroupProperties(group); } return(wrapper); }
internal static void WriteJsonOutput(LdapWrapper wrapper) { switch (wrapper) { case Computer computer: _computerOutput.Value.WriteObject(computer); break; case Domain domain: _domainOutput.Value.WriteObject(domain); break; case GPO gpo: _gpoOutput.Value.WriteObject(gpo); break; case Group group: _groupOutput.Value.WriteObject(group); break; case OU ou: _ouOutput.Value.WriteObject(ou); break; case User user: _userOutput.Value.WriteObject(user); break; } _currentCount++; }
internal static async Task <LdapWrapper> ProcessNetSessions(LdapWrapper wrapper) { if (wrapper is Computer computer && !computer.PingFailed) { //If ExcludeDC is set remove DCs from collection if (Options.Instance.ExcludeDomainControllers && computer.IsDomainController) { return(wrapper); } //If stealth is set, only do session enum if the computer is marked as a stealth target if (Options.Instance.Stealth && !computer.IsStealthTarget) { return(wrapper); } var sessions = await GetNetSessions(computer); var temp = computer.Sessions.ToList(); temp.AddRange(sessions); computer.Sessions = temp.Distinct().ToArray(); await Helpers.DoDelay(); } return(wrapper); }
/// <summary> /// Gets the primary group info for users/computers /// </summary> /// <param name="wrapper"></param> private static void GetPrimaryGroupInfo(LdapWrapper wrapper) { //Grab the primarygroupid attribute var primaryGroupId = wrapper.SearchResult.GetProperty("primarygroupid"); if (primaryGroupId == null) { return; } //Grab the domain sid from the wrapper instead of querying LDAP var domainSid = wrapper.ObjectIdentifier.Substring(0, wrapper.ObjectIdentifier.LastIndexOf("-", StringComparison.Ordinal)); //Append the primarygroupid to the domainsid var primaryGroupSid = $"{domainSid}-{primaryGroupId}"; if (wrapper is Computer c) { c.PrimaryGroupSid = primaryGroupSid; } else if (wrapper is User u) { u.PrimaryGroupSid = primaryGroupSid; } }
internal static async Task <LdapWrapper> CheckSMBOpen(LdapWrapper wrapper) { //Only perform checks if this is a Computer object if (wrapper is Computer computer) { //Stealth targetting - we've already determined our stealth targets, so if its not a stealth target, return if (Options.Instance.Stealth && !computer.IsStealthTarget) { return(wrapper); } if (Options.Instance.WindowsOnly) { //If the WindowsOnly flag is set, check the operatingsystem attribute var os = wrapper.SearchResult.GetProperty("operatingsystem"); //Perform a search for the term windows in the operatingsystem string if (!(os?.IndexOf("windows", StringComparison.CurrentCultureIgnoreCase) > -1)) { //If this isn't a windows computer, we'll mark is as such and we'll skip the following port scan since its not necessary computer.IsWindows = false; //Add a computer status message to note why we skipped this computer OutputTasks.AddComputerStatus(new ComputerStatus { ComputerName = computer.DisplayName, Status = "NotWindows", Task = "SMBCheck" }); return(wrapper); } } //If we're skipping port scan, just return the wrapper. PingFailed is set to false by default if (Options.Instance.SkipPortScan) { return(wrapper); } //Do a check on port 445 and save the result computer.PingFailed = Helpers.CheckPort(computer.APIName, 445) == false; if (computer.PingFailed && Options.Instance.DumpComputerStatus) { //If the port check failed, add a computer status note OutputTasks.AddComputerStatus(new ComputerStatus { ComputerName = computer.DisplayName, Status = "SMBNotAvailable", Task = "SMBCheck" }); } //Do jitter/delay if specified await Helpers.DoDelay(); } return(wrapper); }
internal static LdapWrapper ResolveDomainTrusts(LdapWrapper wrapper) { if (wrapper is Domain domain) { DoTrustEnumeration(domain); } return(wrapper); }
internal void WriteObject(LdapWrapper json) { Serializer.Serialize(JsonWriter, json); Count++; if (Count % 100 == 0) { JsonWriter.Flush(); } }
internal static async Task <LdapWrapper> ProcessSPNS(LdapWrapper wrapper) { if (wrapper is User user) { await ProcessUserSPNs(user); } return(wrapper); }
/// <summary> /// Parses remaining properties when the --CollectAllProperties flag is specified /// </summary> /// <param name="wrapper"></param> private static void ParseAllProperties(LdapWrapper wrapper) { var result = wrapper.SearchResult; var flag = IsTextUnicodeFlags.IS_TEXT_UNICODE_STATISTICS; foreach (var property in result.Attributes.AttributeNames) { var propName = property.ToString().ToLower(); if (ReservedAttributes.Contains(propName)) { continue; } var collection = result.Attributes[propName]; if (collection.Count == 0) { continue; } if (collection.Count == 1) { var testBytes = result.GetPropertyAsBytes(propName); if (testBytes == null || testBytes.Length == 0 || !IsTextUnicode(testBytes, testBytes.Length, ref flag)) { continue; } var testString = result.GetProperty(propName); if (!string.IsNullOrEmpty(testString)) { if (propName == "badpasswordtime") { wrapper.Properties.Add(propName, ConvertToUnixEpoch(testString)); } else { wrapper.Properties.Add(propName, BestGuessConvert(testString)); } } } else { var arrBytes = result.GetPropertyAsArrayOfBytes(propName); if (arrBytes.Length == 0 || !IsTextUnicode(arrBytes[0], arrBytes[0].Length, ref flag)) { continue; } var arr = result.GetPropertyAsArray(propName); if (arr.Length > 0) { wrapper.Properties.Add(propName, arr.Select(BestGuessConvert).ToArray()); } } } }
/// <summary> /// Base function for processing ACES /// </summary> /// <param name="wrapper"></param> /// <returns></returns> internal static async Task <LdapWrapper> ProcessAces(LdapWrapper wrapper) { var aclAces = await ProcessDACL(wrapper); var gmsaAces = await ProcessGMSA(wrapper); wrapper.Aces = aclAces.Concat(gmsaAces).ToArray(); return(wrapper); }
/// <summary> /// Processes the msds-groupmsamembership property, and determines who can read the password /// </summary> /// <param name="wrapper"></param> /// <returns></returns> private static async Task <List <ACL> > ProcessGMSA(LdapWrapper wrapper) { var aces = new List <ACL>(); //Grab the property as a byte array var securityDescriptor = wrapper.SearchResult.GetPropertyAsBytes("msds-groupmsamembership"); //If the property is null, its either not a GMSA or something went wrong, so just exit out if (securityDescriptor == null) { return(aces); } //Create a new ActiveDirectorySecurity object and set the bytes to the descriptor var descriptor = new ActiveDirectorySecurity(); descriptor.SetSecurityDescriptorBinaryForm(securityDescriptor); // Loop over the entries in the security descriptor foreach (ActiveDirectoryAccessRule ace in descriptor.GetAccessRules(true, true, typeof(SecurityIdentifier))) { //Ignore null aces if (ace == null) { continue; } //Ignore deny aces (although this should never show up in GMSAs if (ace.AccessControlType == AccessControlType.Deny) { continue; } //Pre-process the principal for the SID var principalSid = FilterAceSids(ace.IdentityReference.Value); //Ignore null SIDs if (principalSid == null) { continue; } //Resolve the principal SID and grab its type var(finalSid, type) = await ResolutionHelpers.ResolveSidAndGetType(principalSid, wrapper.Domain); aces.Add(new ACL { RightName = "ReadGMSAPassword", AceType = "", PrincipalSID = finalSid, PrincipalType = type, IsInherited = false }); } return(aces); }
internal static async Task <LdapWrapper> EnumerateContainer(LdapWrapper wrapper) { if (wrapper is OU ou) { await ProcessOUObject(ou); } else if (wrapper is Domain domain) { await ProcessDomainObject(domain); } return(wrapper); }
internal static async Task <LdapWrapper> ProcessGroupMembership(LdapWrapper wrapper) { if (wrapper is Group group) { await GetGroupMembership(group); } else if (wrapper is Computer || wrapper is User) { GetPrimaryGroupInfo(wrapper); } return(wrapper); }
/// <summary> /// Grab properties from Group objects /// </summary> /// <param name="wrapper"></param> private static void ParseGroupProperties(LdapWrapper wrapper) { var result = wrapper.SearchResult; var adminCount = result.GetProperty("admincount"); if (adminCount != null) { var a = int.Parse(adminCount); wrapper.Properties.Add("admincount", a != 0); } else { wrapper.Properties.Add("admincount", false); } }
internal static async Task <LdapWrapper> ProcessLoggedOn(LdapWrapper wrapper) { if (wrapper is Computer computer && !computer.PingFailed) { var sessions = new List <Session>(); sessions.AddRange(await GetLoggedOnUsersAPI(computer)); sessions.AddRange(GetLoggedOnUsersRegistry(computer)); var temp = computer.Sessions.ToList(); temp.AddRange(sessions); computer.Sessions = temp.Distinct().ToArray(); } await Helpers.DoDelay(); return(wrapper); }
/// <summary> /// Post-processing on wrapper objects to set stealth/domain controller targets /// </summary> /// <param name="wrapper"></param> private static void PostProcessWrapper(LdapWrapper wrapper) { var opts = Options.Instance; if (wrapper is Computer computer) { if (opts.Stealth && StealthProducer.IsSidStealthTarget(computer.ObjectIdentifier)) { computer.IsStealthTarget = true; } if (opts.ExcludeDomainControllers && BaseProducer.IsSidDomainController(computer.ObjectIdentifier)) { computer.IsDomainController = true; } } }
/// <summary> /// Entrypoint for the pipeline /// </summary> /// <param name="wrapper"></param> /// <returns></returns> internal static async Task <LdapWrapper> ProcessLoggedOn(LdapWrapper wrapper) { if (wrapper is Computer computer) { //Make sure we're targetting a windows or non-contactable computer if (computer.IsWindows && !computer.PingFailed) { var sessions = new List <Session>(); sessions.AddRange(await GetLoggedOnUsersAPI(computer)); sessions.AddRange(GetLoggedOnUsersRegistry(computer)); var temp = computer.Sessions.ToList(); temp.AddRange(sessions); computer.Sessions = temp.Distinct().ToArray(); } } await Helpers.DoDelay(); return(wrapper); }
private static void GetPrimaryGroupInfo(LdapWrapper wrapper) { var primaryGroupId = wrapper.SearchResult.GetProperty("primarygroupid"); if (primaryGroupId == null) { return; } var domainSid = wrapper.ObjectIdentifier.Substring(0, wrapper.ObjectIdentifier.LastIndexOf("-", StringComparison.Ordinal)); var primaryGroupSid = $"{domainSid}-{primaryGroupId}"; if (wrapper is Computer c) { c.PrimaryGroupSid = primaryGroupSid; } else if (wrapper is User u) { u.PrimaryGroupSid = primaryGroupSid; } }
internal static async Task <LdapWrapper> GetLocalGroupMembers(LdapWrapper wrapper) { if (wrapper is Computer computer && computer.IsWindows && !computer.PingFailed) { var opts = Options.Instance.ResolvedCollectionMethods; if ((opts & CollectionMethodResolved.DCOM) != 0) { var temp = computer.DcomUsers.ToList(); temp.AddRange((await GetNetLocalGroupMembers(computer, LocalGroupRids.DcomUsers)).Distinct()); computer.DcomUsers = temp.ToArray(); await Helpers.DoDelay(); } if ((opts & CollectionMethodResolved.LocalAdmin) != 0) { var temp = computer.LocalAdmins.ToList(); temp.AddRange((await GetNetLocalGroupMembers(computer, LocalGroupRids.Administrators)).Distinct()); computer.LocalAdmins = temp.ToArray(); await Helpers.DoDelay(); } if ((opts & CollectionMethodResolved.RDP) != 0) { var temp = computer.RemoteDesktopUsers.ToList(); temp.AddRange((await GetNetLocalGroupMembers(computer, LocalGroupRids.RemoteDesktopUsers)).Distinct()); computer.RemoteDesktopUsers = temp.ToArray(); await Helpers.DoDelay(); } if ((opts & CollectionMethodResolved.PSRemote) != 0) { var temp = computer.PSRemoteUsers.ToList(); temp.AddRange((await GetNetLocalGroupMembers(computer, LocalGroupRids.PSRemote)).Distinct()); computer.PSRemoteUsers = temp.ToArray(); await Helpers.DoDelay(); } } return(wrapper); }
internal static async Task <LdapWrapper> CheckSMBOpen(LdapWrapper wrapper) { if (wrapper is Computer computer) { if (Options.Instance.Stealth && !computer.IsStealthTarget) { return(wrapper); } computer.PingFailed = Helpers.CheckPort(computer.APIName, 445) == false; if (computer.PingFailed && Options.Instance.DumpComputerStatus) { OutputTasks.AddComputerStatus(new ComputerStatus { ComputerName = computer.DisplayName, Status = "SMBNotAvailable", Task = "SMBCheck" }); } await Helpers.DoDelay(); } return(wrapper); }
internal static LdapWrapper ProcessDACL(LdapWrapper wrapper) { }
internal static async Task <LdapWrapper> ProcessDACL(LdapWrapper wrapper) { var aces = new List <ACL>(); var ntSecurityDescriptor = wrapper.SearchResult.GetPropertyAsBytes("ntsecuritydescriptor"); //If the NTSecurityDescriptor is null, something screwy is happening. Nothing to process here, so continue in the pipeline if (ntSecurityDescriptor == null) { return(wrapper); } var descriptor = new ActiveDirectorySecurity(); descriptor.SetSecurityDescriptorBinaryForm(ntSecurityDescriptor); var ownerSid = ProcessACESID(descriptor.GetOwner(typeof(SecurityIdentifier)).Value); if (ownerSid != null) { if (CommonPrincipal.GetCommonSid(ownerSid, out var commonPrincipal)) { aces.Add(new ACL { PrincipalSID = Helpers.ConvertCommonSid(ownerSid, wrapper.Domain), RightName = "Owner", AceType = "", PrincipalType = commonPrincipal.Type, IsInherited = false }); } else { var ownerType = await Helpers.LookupSidType(ownerSid); aces.Add(new ACL { PrincipalSID = ownerSid, RightName = "Owner", AceType = "", PrincipalType = ownerType, IsInherited = false }); } } foreach (ActiveDirectoryAccessRule ace in descriptor.GetAccessRules(true, true, typeof(SecurityIdentifier))) { //Ignore Null Aces if (ace == null) { continue; } //Ignore deny aces if (ace.AccessControlType == AccessControlType.Deny) { continue; } //Check if the ACE actually applies to our object based on the object type if (!IsAceInherited(ace, BaseGuids[wrapper.GetType()])) { continue; } var principalSid = ProcessACESID(ace.IdentityReference.Value); if (principalSid == null) { continue; } LdapTypeEnum principalType; if (CommonPrincipal.GetCommonSid(principalSid, out var commonPrincipal)) { principalSid = Helpers.ConvertCommonSid(principalSid, wrapper.Domain); principalType = commonPrincipal.Type; } else { principalType = await Helpers.LookupSidType(principalSid); } var rights = ace.ActiveDirectoryRights; var objectAceType = ace.ObjectType.ToString(); var isInherited = ace.IsInherited; if (rights.HasFlag(ActiveDirectoryRights.GenericAll)) { if (objectAceType == AllGuid || objectAceType == "") { aces.Add(new ACL { PrincipalSID = principalSid, RightName = "GenericAll", AceType = "", PrincipalType = principalType, IsInherited = isInherited }); } //GenericAll includes every other right, and we dont want to duplicate. So continue in the loop continue; } //WriteDacl and WriteOwner are always useful to us regardless of object type if (rights.HasFlag(ActiveDirectoryRights.WriteDacl)) { aces.Add(new ACL { PrincipalSID = principalSid, AceType = "", RightName = "WriteDacl", PrincipalType = principalType, IsInherited = isInherited }); } if (rights.HasFlag(ActiveDirectoryRights.WriteOwner)) { aces.Add(new ACL { RightName = "WriteOwner", AceType = "", PrincipalSID = principalSid, PrincipalType = principalType, IsInherited = isInherited }); } //Process object specific ACEs //Extended rights apply to Users, Domains, Computers if (rights.HasFlag(ActiveDirectoryRights.ExtendedRight)) { if (wrapper is Domain) { switch (objectAceType) { case "1131f6aa-9c07-11d1-f79f-00c04fc2dcd2": aces.Add(new ACL { AceType = "GetChanges", RightName = "ExtendedRight", PrincipalSID = principalSid, PrincipalType = principalType, IsInherited = isInherited }); break; case "1131f6ad-9c07-11d1-f79f-00c04fc2dcd2": aces.Add(new ACL { AceType = "GetChangesAll", RightName = "ExtendedRight", PrincipalSID = principalSid, PrincipalType = principalType, IsInherited = isInherited }); break; case AllGuid: case "": aces.Add(new ACL { AceType = "All", RightName = "ExtendedRight", PrincipalSID = principalSid, PrincipalType = principalType, IsInherited = isInherited }); break; } } else if (wrapper is User) { switch (objectAceType) { case "00299570-246d-11d0-a768-00aa006e0529": aces.Add(new ACL { AceType = "User-Force-Change-Password", PrincipalSID = principalSid, RightName = "ExtendedRight", PrincipalType = principalType, IsInherited = isInherited }); break; case AllGuid: case "": aces.Add(new ACL { AceType = "All", PrincipalSID = principalSid, RightName = "ExtendedRight", PrincipalType = principalType, IsInherited = isInherited }); break; } } else if (wrapper is Computer) { Helpers.GetDirectorySearcher(wrapper.Domain).GetNameFromGuid(objectAceType, out var mappedGuid); if (wrapper.SearchResult.GetProperty("ms-mcs-admpwdexpirationtime") != null) { if (objectAceType == AllGuid || objectAceType == "") { aces.Add(new ACL { AceType = "All", RightName = "ExtendedRight", PrincipalSID = principalSid, PrincipalType = principalType, IsInherited = isInherited }); } else if (mappedGuid != null && mappedGuid == "ms-Mcs-AdmPwd") { aces.Add(new ACL { AceType = "", RightName = "ReadLAPSPassword", PrincipalSID = principalSid, PrincipalType = principalType, IsInherited = isInherited }); } } } } //PropertyWrites apply to Groups, User, Computer //GenericWrite encapsulates WriteProperty, so we need to check them at the same time to avoid duplicate edges if (rights.HasFlag(ActiveDirectoryRights.GenericWrite) || rights.HasFlag(ActiveDirectoryRights.WriteProperty)) { if (objectAceType == AllGuid || objectAceType == "") { aces.Add(new ACL { AceType = "", RightName = "GenericWrite", PrincipalSID = principalSid, PrincipalType = principalType, IsInherited = isInherited }); } if (wrapper is User) { if (objectAceType == "f3a64788-5306-11d1-a9c5-0000f80367c1") { aces.Add(new ACL { AceType = "WriteSPN", RightName = "WriteProperty", PrincipalSID = principalSid, PrincipalType = principalType, IsInherited = isInherited }); } } else if (wrapper is Group) { if (objectAceType == "bf9679c0-0de6-11d0-a285-00aa003049e2") { aces.Add(new ACL { AceType = "AddMember", RightName = "WriteProperty", PrincipalSID = principalSid, PrincipalType = principalType, IsInherited = isInherited }); } } else if (wrapper is Computer) { if (objectAceType == "3f78c3e5-f79a-46bd-a0b8-9d18116ddc79") { aces.Add(new ACL { AceType = "AllowedToAct", RightName = "WriteProperty", PrincipalSID = principalSid, PrincipalType = principalType, IsInherited = isInherited }); } } } } wrapper.Aces = aces.Distinct().ToArray(); return(wrapper); }
/// <summary> /// Processes the ACL for an object /// </summary> /// <param name="wrapper"></param> /// <returns></returns> private static async Task <List <ACL> > ProcessDACL(LdapWrapper wrapper) { var aces = new List <ACL>(); //Grab the ntsecuritydescriptor attribute as bytes var ntSecurityDescriptor = wrapper.SearchResult.GetPropertyAsBytes("ntsecuritydescriptor"); //If the NTSecurityDescriptor is null, something screwy is happening. Nothing to process here, so continue in the pipeline if (ntSecurityDescriptor == null) { return(aces); } //Create a new ActiveDirectorySecurity object and set the bytes in to this value var descriptor = new ActiveDirectorySecurity(); descriptor.SetSecurityDescriptorBinaryForm(ntSecurityDescriptor); //Pre-process the sid of the object owner var ownerSid = FilterAceSids(descriptor.GetOwner(typeof(SecurityIdentifier)).Value); if (ownerSid != null) { //Resolve the owner's SID to its corresponding type var(finalSid, type) = await ResolutionHelpers.ResolveSidAndGetType(ownerSid, wrapper.Domain); //If resolution worked, store the Owner ACE into our final result if (finalSid != null) { aces.Add(new ACL { PrincipalSID = finalSid, RightName = "Owner", AceType = "", PrincipalType = type, IsInherited = false }); } } foreach (ActiveDirectoryAccessRule ace in descriptor.GetAccessRules(true, true, typeof(SecurityIdentifier))) { //Ignore Null Aces if (ace == null) { continue; } //Ignore deny aces if (ace.AccessControlType == AccessControlType.Deny) { continue; } //Check if the ACE actually applies to our object based on the object type if (!IsAceInherited(ace, BaseGuids[wrapper.GetType()])) { continue; } //Grab the sid of the principal on this ACE var principalSid = FilterAceSids(ace.IdentityReference.Value); if (principalSid == null) { continue; } //Resolve the principal's SID to its type var(finalSid, type) = await ResolutionHelpers.ResolveSidAndGetType(principalSid, wrapper.Domain); if (finalSid == null) { continue; } //Start processing the rights in this ACE var rights = ace.ActiveDirectoryRights; var objectAceType = ace.ObjectType.ToString(); var isInherited = ace.IsInherited; //GenericAll is applicable to everything if (rights.HasFlag(ActiveDirectoryRights.GenericAll)) { if (objectAceType == AllGuid || objectAceType == "") { aces.Add(new ACL { PrincipalSID = finalSid, RightName = "GenericAll", AceType = "", PrincipalType = type, IsInherited = isInherited }); } //GenericAll includes every other right, and we dont want to duplicate. So continue in the loop continue; } //WriteDacl and WriteOwner are always useful to us regardless of object type if (rights.HasFlag(ActiveDirectoryRights.WriteDacl)) { aces.Add(new ACL { PrincipalSID = finalSid, AceType = "", RightName = "WriteDacl", PrincipalType = type, IsInherited = isInherited }); } if (rights.HasFlag(ActiveDirectoryRights.WriteOwner)) { aces.Add(new ACL { RightName = "WriteOwner", AceType = "", PrincipalSID = finalSid, PrincipalType = type, IsInherited = isInherited }); } //Process object specific ACEs //Extended rights apply to Users, Domains, Computers if (rights.HasFlag(ActiveDirectoryRights.ExtendedRight)) { if (wrapper is Domain) { switch (objectAceType) { case "1131f6aa-9c07-11d1-f79f-00c04fc2dcd2": aces.Add(new ACL { AceType = "GetChanges", RightName = "ExtendedRight", PrincipalSID = finalSid, PrincipalType = type, IsInherited = isInherited }); break; case "1131f6ad-9c07-11d1-f79f-00c04fc2dcd2": aces.Add(new ACL { AceType = "GetChangesAll", RightName = "ExtendedRight", PrincipalSID = finalSid, PrincipalType = type, IsInherited = isInherited }); break; case AllGuid: case "": aces.Add(new ACL { AceType = "All", RightName = "ExtendedRight", PrincipalSID = finalSid, PrincipalType = type, IsInherited = isInherited }); break; } } else if (wrapper is User) { switch (objectAceType) { case "00299570-246d-11d0-a768-00aa006e0529": aces.Add(new ACL { AceType = "User-Force-Change-Password", PrincipalSID = finalSid, RightName = "ExtendedRight", PrincipalType = type, IsInherited = isInherited }); break; case AllGuid: case "": aces.Add(new ACL { AceType = "All", PrincipalSID = finalSid, RightName = "ExtendedRight", PrincipalType = type, IsInherited = isInherited }); break; } } else if (wrapper is Computer) { //Computer extended rights are important when the computer has LAPS Helpers.GetDirectorySearcher(wrapper.Domain).GetAttributeFromGuid(objectAceType, out var mappedGuid); if (wrapper.SearchResult.GetProperty("ms-mcs-admpwdexpirationtime") != null) { if (objectAceType == AllGuid || objectAceType == "") { aces.Add(new ACL { AceType = "All", RightName = "ExtendedRight", PrincipalSID = finalSid, PrincipalType = type, IsInherited = isInherited }); } else if (mappedGuid != null && mappedGuid == "ms-Mcs-AdmPwd") { aces.Add(new ACL { AceType = "", RightName = "ReadLAPSPassword", PrincipalSID = finalSid, PrincipalType = type, IsInherited = isInherited }); } } } } //PropertyWrites apply to Groups, User, Computer, GPO //GenericWrite encapsulates WriteProperty, so we need to check them at the same time to avoid duplicate edges if (rights.HasFlag(ActiveDirectoryRights.GenericWrite) || rights.HasFlag(ActiveDirectoryRights.WriteProperty)) { if (wrapper is User || wrapper is Group || wrapper is Computer || wrapper is GPO) { if (objectAceType == AllGuid || objectAceType == "") { aces.Add(new ACL { AceType = "", RightName = "GenericWrite", PrincipalSID = finalSid, PrincipalType = type, IsInherited = isInherited }); } } if (wrapper is User) { if (objectAceType == "f3a64788-5306-11d1-a9c5-0000f80367c1") { aces.Add(new ACL { AceType = "WriteSPN", RightName = "WriteProperty", PrincipalSID = finalSid, PrincipalType = type, IsInherited = isInherited }); } } else if (wrapper is Group) { if (objectAceType == "bf9679c0-0de6-11d0-a285-00aa003049e2") { aces.Add(new ACL { AceType = "AddMember", RightName = "WriteProperty", PrincipalSID = finalSid, PrincipalType = type, IsInherited = isInherited }); } } else if (wrapper is Computer) { if (objectAceType == "3f78c3e5-f79a-46bd-a0b8-9d18116ddc79") { aces.Add(new ACL { AceType = "AllowedToAct", RightName = "WriteProperty", PrincipalSID = finalSid, PrincipalType = type, IsInherited = isInherited }); } } } } return(aces); }