示例#1
0
        internal static void GetProps(SearchResultEntry entry, ResolvedEntry resolved, ref Gpo obj)
        {
            if (!Utils.IsMethodSet(ResolvedCollectionMethod.ObjectProps))
            {
                return;
            }

            obj.Properties.Add("description", entry.GetProp("description"));
            obj.Properties.Add("gpcpath", entry.GetProp("gpcfilesyspath"));
        }
示例#2
0
        internal static void GetProps(SearchResultEntry entry, ResolvedEntry resolved, ref Domain obj)
        {
            if (!Utils.IsMethodSet(ResolvedCollectionMethod.ObjectProps))
            {
                return;
            }

            obj.Properties.Add("description", entry.GetProp("description"));
            if (!int.TryParse(entry.GetProp("msds-behavior-version"), out var level))
            {
                level = -1;
            }
            string func;

            switch (level)
            {
            case 0:
                func = "2000 Mixed/Native";
                break;

            case 1:
                func = "2003 Interim";
                break;

            case 2:
                func = "2003";
                break;

            case 3:
                func = "2008";
                break;

            case 4:
                func = "2008 R2";
                break;

            case 5:
                func = "2012";
                break;

            case 6:
                func = "2012 R2";
                break;

            case 7:
                func = "2016";
                break;

            default:
                func = "Unknown";
                break;
            }

            obj.Properties.Add("functionallevel", func);
        }
示例#3
0
        private static IEnumerable <string> GetNetLoggedOn(ResolvedEntry entry, string computerDomain)
        {
            var users = new List <string>();

            const int queryLevel   = 1;
            var       resumeHandle = 0;

            var tWui1 = typeof(WKSTA_USER_INFO_1);

            //Call the API to get logged on users
            var result = NetWkstaUserEnum(entry.IngestCacheDisplay, queryLevel, out IntPtr intPtr, -1, out int entriesRead, out int _, ref resumeHandle);

            //If we don't get 0 or 234 return
            if (result != 0 && result != 234)
            {
                yield break;
            }
            var iter = intPtr;

            for (var i = 0; i < entriesRead; i++)
            {
                var data = (WKSTA_USER_INFO_1)Marshal.PtrToStructure(iter, tWui1);
                iter = (IntPtr)(iter.ToInt64() + Marshal.SizeOf(tWui1));

                var domain   = data.wkui1_logon_domain;
                var username = data.wkui1_username;

                if (domain.Equals(entry.ComputerSamAccountName, StringComparison.CurrentCultureIgnoreCase) ||
                    username.Trim().Equals("") || username.EndsWith("$", StringComparison.Ordinal))
                {
                    continue;
                }

                //Try to convert the domain part to a FQDN, if it doesn't work just use the computer's domain
                var domainName = _utils.DomainNetbiosToFqdn(domain) ?? computerDomain;
                users.Add($"{username}@{domainName}".ToUpper());
            }

            NetApiBufferFree(intPtr);

            foreach (var user in  users.Distinct())
            {
                yield return(user);
            }
        }
示例#4
0
        internal static IEnumerable <Session> DoLoggedOnCollection(ResolvedEntry target, string domainName)
        {
            if (!Utils.IsMethodSet(ResolvedCollectionMethod.LoggedOn) &&
                !Utils.IsMethodSet(ResolvedCollectionMethod.LoggedOnLoop))
            {
                yield break;
            }

            var t = Task <List <string> > .Factory.StartNew(() =>
            {
                var users = new List <string>();
                users.AddRange(GetRegistryLoggedOn(target));
                users.AddRange(GetNetLoggedOn(target, domainName));

                return(users);
            });

            var success = t.Wait(Timeout);

            if (!success)
            {
                throw new TimeoutException();
            }

            var sessions = new List <Session>();

            foreach (var u in t.Result.Distinct())
            {
                sessions.Add(new Session
                {
                    ComputerName = target.IngestCacheDisplay,
                    UserName     = u,
                    Weight       = 1
                });
            }

            foreach (var x in sessions)
            {
                yield return(x);
            }

            Utils.DoJitter();
        }
示例#5
0
        internal static void GetGroupInfo(SearchResultEntry entry, ResolvedEntry resolved, string domainSid, ref Computer u)
        {
            if (!Utils.IsMethodSet(ResolvedCollectionMethod.Group))
            {
                return;
            }

            var pgi = entry.GetProp("primarygroupid");

            if (pgi == null)
            {
                return;
            }

            var pgsid            = $"{domainSid}-{pgi}";
            var primaryGroupName = _utils.SidToDisplay(pgsid, Utils.ConvertDnToDomain(entry.DistinguishedName), Props, "group");

            u.PrimaryGroup = primaryGroupName;
        }
示例#6
0
        internal static void GetProps(SearchResultEntry entry, ResolvedEntry resolved, ref Group obj)
        {
            if (!Utils.IsMethodSet(ResolvedCollectionMethod.ObjectProps))
            {
                return;
            }
            var ac = entry.GetProp("admincount");

            if (ac != null)
            {
                var a = int.Parse(ac);
                obj.Properties.Add("admincount", a != 0);
            }
            else
            {
                obj.Properties.Add("admincount", false);
            }

            obj.Properties.Add("description", entry.GetProp("description"));
        }
示例#7
0
        //internal static void DoLoggedOnCollection(ResolvedEntry target, string domainName, ref Computer obj)
        //{
        //    if (!Utils.IsMethodSet(ResolvedCollectionMethod.LoggedOn))
        //        return;

        //    var users = new List<string>();
        //    users.AddRange(GetRegistryLoggedOn(target));
        //    users.AddRange(GetNetLoggedOn(target, domainName));

        //    var sessions = new List<Session>();

        //    foreach (var u in users.Distinct())
        //    {
        //        sessions.Add(new Session
        //        {
        //            ComputerName = target.IngestCacheDisplay,
        //            UserName = u,
        //            Weight = 1
        //        });
        //    }

        //    if (sessions.Count > 0)
        //        obj.Sessions = sessions.ToArray();
        //}

        private static IEnumerable <string> GetRegistryLoggedOn(ResolvedEntry target)
        {
            var users = new List <string>();

            try
            {
                //Remotely open the registry hive if its not our current one
                var key = RegistryKey.OpenRemoteBaseKey(RegistryHive.Users,
                                                        Environment.MachineName.Equals(target.ComputerSamAccountName, StringComparison.CurrentCultureIgnoreCase)
                        ? ""
                        : target.IngestCacheDisplay);

                //Find all the subkeys that match our regex
                var filtered = key.GetSubKeyNames()
                               .Where(sub => SidRegex.IsMatch(sub));

                foreach (var subkey in filtered)
                {
                    //Convert our sid to a username
                    var user = _utils.SidToDisplay(subkey, _utils.SidToDomainName(subkey),
                                                   RegistryProps, "user");

                    if (user == null)
                    {
                        continue;
                    }
                    users.Add(user.ToUpper());
                }
            }
            catch (Exception)
            {
                yield break;
            }

            foreach (var user in users.Distinct())
            {
                yield return(user);
            }
        }
示例#8
0
        public static IEnumerable <LocalMember> GetGroupMembers(ResolvedEntry entry, LocalGroupRids rid)
        {
            if (rid.Equals(LocalGroupRids.Administrators) && !Utils.IsMethodSet(ResolvedCollectionMethod.LocalAdmin))
            {
                yield break;
            }

            if (rid.Equals(LocalGroupRids.RemoteDesktopUsers) && !Utils.IsMethodSet(ResolvedCollectionMethod.RDP))
            {
                yield break;
            }

            if (rid.Equals(LocalGroupRids.DcomUsers) && !Utils.IsMethodSet(ResolvedCollectionMethod.DCOM))
            {
                yield break;
            }

            Utils.Debug("Starting GetSamAdmins");
            string machineSid = null;

            Utils.Debug("Starting Task");
            var t = Task <SamEnumerationObject[]> .Factory.StartNew(() =>
            {
                try
                {
                    return(NetLocalGroupGetMembers(entry, (int)rid, out machineSid));
                }
                catch (ApiFailedException)
                {
                    return(new SamEnumerationObject[0]);
                }
                catch (SystemDownException)
                {
                    return(new SamEnumerationObject[0]);
                }
            });

            var success = t.Wait(Timeout);

            Utils.Debug("Task Finished");

            if (!success)
            {
                Utils.Debug("SamAdmin Timeout");
                throw new TimeoutException();
            }

            Utils.Debug("SamAdmin success");
            var resolvedObjects = t.Result;

            if (resolvedObjects.Length == 0)
            {
                Utils.Debug("SamAdmins returned 0 objects");
                yield break;
            }

            Utils.Debug("Processing data");
            //Process our list of stuff now
            foreach (var data in resolvedObjects)
            {
                var sid = data?.AccountSid;
                Utils.Debug($"Processing sid: {sid}");
                if (sid == null)
                {
                    Utils.Debug("Null sid");
                    continue;
                }

                if (data.AccountName.Equals(string.Empty))
                {
                    Utils.Debug("Empty AccountName");
                    continue;
                }


                if (sid.StartsWith(machineSid))
                {
                    Utils.Debug("Local Account");
                    continue;
                }


                string type;
                switch (data.SidUsage)
                {
                case SidNameUse.SidTypeUser:
                    type = "user";
                    break;

                case SidNameUse.SidTypeGroup:
                    type = "group";
                    break;

                case SidNameUse.SidTypeComputer:
                    type = "computer";
                    break;

                case SidNameUse.SidTypeWellKnownGroup:
                    type = "wellknown";
                    break;

                case SidNameUse.SidTypeAlias:
                    type = "group";
                    break;

                default:
                    type = null;
                    break;
                }

                if (type == null)
                {
                    continue;
                }

                if (data.AccountName.EndsWith("$"))
                {
                    type = "unknown";
                }

                string resolvedName;

                Utils.Debug($"Object Type: {type}");

                if (type.Equals("unknown"))
                {
                    Utils.Debug("Resolving Sid to object UnknownType");
                    var mp = _utils.UnknownSidTypeToDisplay(sid, _utils.SidToDomainName(sid),
                                                            AdminProps);
                    if (mp == null)
                    {
                        continue;
                    }

                    Utils.Debug($"Got Object: {mp.PrincipalName}");
                    resolvedName = mp.PrincipalName;
                    type         = mp.ObjectType;
                }
                else if (type == "wellknown")
                {
                    if (MappedPrincipal.GetCommon(sid, out var result))
                    {
                        if (result.PrincipalName.Equals("Local System"))
                        {
                            continue;
                        }

                        string domain;
                        try
                        {
                            var split = string.Join(".", entry.IngestCacheDisplay.Split('.').Skip(1).ToArray());
                            domain = split;
                        }
                        catch
                        {
                            domain = _utils.GetDomain(_options.Domain).Name;
                        }

                        type         = result.ObjectType;
                        resolvedName = $"{result.PrincipalName}@{domain}".ToUpper();
                    }
                    else
                    {
                        continue;
                    }
                }
                else
                {
                    Utils.Debug("Resolving Sid to Object");
                    resolvedName = _utils.SidToDisplay(sid, _utils.SidToDomainName(sid), AdminProps, type);
                    if (resolvedName == null)
                    {
                        continue;
                    }
                    Utils.Debug($"Got Object: {resolvedName}");
                }

                yield return(new LocalMember
                {
                    Type = type,
                    Name = resolvedName
                });
            }

            Utils.DoJitter();
        }
示例#9
0
        internal static void ResolveContainer(SearchResultEntry entry, ResolvedEntry resolved, ref Ou obj)
        {
            if (!Utils.IsMethodSet(ResolvedCollectionMethod.Container))
            {
                return;
            }

            var domain = Utils.ConvertDnToDomain(entry.DistinguishedName);

            var opts = entry.GetProp("gpoptions");

            obj.Properties.Add("blocksinheritance", opts != null && opts.Equals("1"));

            //Resolve GPLinks on the ou
            var links = new List <GpLink>();

            var gpLinks = entry.GetProp("gplink");

            if (gpLinks != null)
            {
                foreach (var l in gpLinks.Split(']', '[').Where(x => x.StartsWith("LDAP")))
                {
                    var split  = l.Split(';');
                    var dn     = split[0];
                    var status = split[1];
                    if (status.Equals("3") || status.Equals("1"))
                    {
                        continue;
                    }

                    var enforced = status.Equals("2");
                    var index    = dn.IndexOf("CN=", StringComparison.OrdinalIgnoreCase) + 4;
                    var name     = dn.Substring(index, index + 25).ToUpper();

                    if (!_gpoCache.ContainsKey(name))
                    {
                        continue;
                    }

                    var dName = _gpoCache[name];
                    links.Add(new GpLink
                    {
                        IsEnforced = enforced,
                        Name       = $"{dName}@{domain}"
                    });
                }

                obj.Links = links.ToArray();
            }

            var computers = new List <string>();
            var users     = new List <string>();
            var ous       = new List <string>();

            foreach (var subEntry in _utils.DoSearch(
                         "(|(samAccountType=805306368)(samAccountType=805306369)(objectclass=organizationalUnit))",
                         SearchScope.OneLevel,
                         new[]
            {
                "samaccountname", "name", "objectguid", "objectclass", "objectsid", "samaccounttype", "dnshostname"
            }, domain, entry.DistinguishedName))
            {
                var subResolved = subEntry.ResolveAdEntry();

                if (subResolved == null)
                {
                    continue;
                }

                if (subResolved.ObjectType.Equals("ou"))
                {
                    ous.Add(new Guid(subEntry.GetPropBytes("objectguid")).ToString().ToUpper());
                }
                else if (subResolved.ObjectType.Equals("computer"))
                {
                    computers.Add(subResolved.IngestCacheDisplay);
                }
                else
                {
                    users.Add(subResolved.IngestCacheDisplay);
                }
            }

            obj.Users = users.ToArray();

            obj.Computers = computers.ToArray();

            obj.ChildOus = ous.ToArray();
        }
示例#10
0
        public static void GetObjectAces(SearchResultEntry entry, ResolvedEntry resolved, ref Ou g)
        {
            if (!Utils.IsMethodSet(ResolvedCollectionMethod.ACL))
            {
                return;
            }

            var aces = new List <ACL>();
            var ntSecurityDescriptor = entry.GetPropBytes("ntsecuritydescriptor");

            //If the ntsecuritydescriptor is null, no point in continuing
            //I'm still not entirely sure what causes this, but it can happen
            if (ntSecurityDescriptor == null)
            {
                return;
            }

            var domainName = Utils.ConvertDnToDomain(entry.DistinguishedName);

            //Convert the ntsecuritydescriptor bytes to a .net object
            var descriptor = new RawSecurityDescriptor(ntSecurityDescriptor, 0);

            //Grab the DACL
            var rawAcl = descriptor.DiscretionaryAcl;
            //Grab the Owner
            var ownerSid = descriptor.Owner.ToString();

            //Determine the owner of the object. Start by checking if we've already determined this is null
            if (!_nullSids.TryGetValue(ownerSid, out _))
            {
                //Check if its a common SID
                if (!MappedPrincipal.GetCommon(ownerSid, out var owner))
                {
                    //Resolve the sid manually if we still dont have it
                    var ownerDomain = _utils.SidToDomainName(ownerSid) ?? domainName;
                    owner = _utils.UnknownSidTypeToDisplay(ownerSid, ownerDomain, Props);
                }
                else
                {
                    owner.PrincipalName = $"{owner.PrincipalName}@{domainName}";
                }

                //Filter out the Local System principal which pretty much every entry has
                if (owner != null && !owner.PrincipalName.Contains("LOCAL SYSTEM") && !owner.PrincipalName.Contains("CREATOR OWNER"))
                {
                    aces.Add(new ACL
                    {
                        AceType       = "",
                        RightName     = "Owner",
                        PrincipalName = owner.PrincipalName,
                        PrincipalType = owner.ObjectType
                    });
                }
                else
                {
                    //We'll cache SIDs we've failed to resolve previously so we dont keep trying
                    _nullSids.TryAdd(ownerSid, new byte());
                }
            }

            foreach (var genericAce in rawAcl)
            {
                var qAce = genericAce as QualifiedAce;
                if (qAce == null)
                {
                    continue;
                }

                var objectSid = qAce.SecurityIdentifier.ToString();
                if (_nullSids.TryGetValue(objectSid, out _))
                {
                    continue;
                }

                //Check if its a common sid
                if (!MappedPrincipal.GetCommon(objectSid, out var mappedPrincipal))
                {
                    //If not common, lets resolve it normally
                    var objectDomain =
                        _utils.SidToDomainName(objectSid) ??
                        domainName;
                    mappedPrincipal = _utils.UnknownSidTypeToDisplay(objectSid, objectDomain, Props);
                    if (mappedPrincipal == null)
                    {
                        _nullSids.TryAdd(objectSid, new byte());
                        continue;
                    }
                }
                else
                {
                    if (mappedPrincipal.PrincipalName == "ENTERPRISE DOMAIN CONTROLLERS")
                    {
                        var dObj = _utils.GetForest(domainName);
                        var d    = dObj == null ? domainName : dObj.RootDomain.Name;
                        mappedPrincipal.PrincipalName = $"{mappedPrincipal.PrincipalName}@{d}".ToUpper();
                    }
                    else
                    {
                        mappedPrincipal.PrincipalName = $"{mappedPrincipal.PrincipalName}@{domainName}".ToUpper();
                    }
                }

                if (mappedPrincipal.PrincipalName.Contains("LOCAL SYSTEM") || mappedPrincipal.PrincipalName.Contains("CREATOR OWNER"))
                {
                    continue;
                }

                //Convert our right to an ActiveDirectoryRight enum object, and then to a string
                var adRight       = (ActiveDirectoryRights)Enum.ToObject(typeof(ActiveDirectoryRights), qAce.AccessMask);
                var adRightString = adRight.ToString();

                //Get the ACE for our right
                var ace  = qAce as ObjectAce;
                var guid = ace != null?ace.ObjectAceType.ToString() : "";

                var inheritedObjectType = ace != null?ace.InheritedObjectAceType.ToString() : "00000000-0000-0000-0000-000000000000";

                var flags       = ace == null ? AceFlags.None : ace.AceFlags;
                var isInherited = (flags & AceFlags.InheritOnly) != 0;

                isInherited = isInherited && (inheritedObjectType == "00000000-0000-0000-0000-000000000000" ||
                                              inheritedObjectType == "bf967aa5-0de6-11d0-a285-00aa003049e2");

                //Special case used for example by Exchange: the ACE is inherited but also applies to the object it is set on
                // this is verified by looking if this ACE is not inherited, and is not an inherit-only ACE
                if (!isInherited && (flags & AceFlags.InheritOnly) != AceFlags.InheritOnly && (flags & AceFlags.Inherited) != AceFlags.Inherited)
                {
                    //If these conditions hold the ACE applies to this object anyway
                    isInherited = true;
                }

                if (!isInherited)
                {
                    continue;
                }

                var toContinue = false;

                _guidMap.TryGetValue(guid, out var mappedGuid);

                //Interesting OU ACEs - GenericAll, GenericWrite, WriteDacl, WriteOwner,
                toContinue |= adRightString.Contains("WriteDacl") ||
                              adRightString.Contains("WriteOwner");

                if (adRightString.Contains("GenericAll"))
                {
                    toContinue |= "00000000-0000-0000-0000-000000000000".Equals(guid) || guid.Equals("") || toContinue;
                }
                if (adRightString.Contains("WriteProperty"))
                {
                    toContinue |= guid.Equals("00000000-0000-0000-0000-000000000000") ||
                                  guid.Equals("f30e3bbe-9ff0-11d1-b603-0000f80367c1") || guid.Equals("") ||
                                  toContinue;
                }

                if (!toContinue)
                {
                    continue;
                }

                if (adRightString.Contains("GenericAll"))
                {
                    if (mappedGuid == "ms-Mcs-AdmPwd")
                    {
                        aces.Add(new ACL
                        {
                            AceType       = "",
                            PrincipalName = mappedPrincipal.PrincipalName,
                            PrincipalType = mappedPrincipal.ObjectType,
                            RightName     = "ReadLAPSPassword"
                        });
                    }
                    else
                    {
                        aces.Add(new ACL
                        {
                            AceType       = "",
                            PrincipalName = mappedPrincipal.PrincipalName,
                            PrincipalType = mappedPrincipal.ObjectType,
                            RightName     = "GenericAll"
                        });
                    }
                }

                if (adRightString.Contains("WriteOwner"))
                {
                    aces.Add(new ACL
                    {
                        AceType       = "",
                        PrincipalName = mappedPrincipal.PrincipalName,
                        PrincipalType = mappedPrincipal.ObjectType,
                        RightName     = "WriteOwner"
                    });
                }

                if (adRightString.Contains("WriteDacl"))
                {
                    aces.Add(new ACL
                    {
                        AceType       = "",
                        PrincipalName = mappedPrincipal.PrincipalName,
                        PrincipalType = mappedPrincipal.ObjectType,
                        RightName     = "WriteDacl"
                    });
                }

                if (adRightString.Contains("ExtendedRight"))
                {
                    if (mappedGuid == "ms-Mcs-AdmPwd")
                    {
                        aces.Add(new ACL
                        {
                            AceType       = "",
                            PrincipalName = mappedPrincipal.PrincipalName,
                            PrincipalType = mappedPrincipal.ObjectType,
                            RightName     = "ReadLAPSPassword"
                        });
                    }
                    else
                    {
                        aces.Add(new ACL
                        {
                            AceType       = "All",
                            PrincipalName = mappedPrincipal.PrincipalName,
                            PrincipalType = mappedPrincipal.ObjectType,
                            RightName     = "ExtendedRight"
                        });
                    }
                }
            }

            g.Aces = aces.Distinct().ToArray();
        }
示例#11
0
        public static void GetObjectAces(SearchResultEntry entry, ResolvedEntry resolved, ref Computer obj)
        {
            if (!Utils.IsMethodSet(ResolvedCollectionMethod.ACL))
            {
                return;
            }

            var aces = new List <ACL>();
            var ntSecurityDescriptor = entry.GetPropBytes("ntsecuritydescriptor");

            //If the ntsecuritydescriptor is null, no point in continuing
            //I'm still not entirely sure what causes this, but it can happen
            if (ntSecurityDescriptor == null)
            {
                return;
            }

            var domainName = Utils.ConvertDnToDomain(entry.DistinguishedName);

            var newDescriptor = new ActiveDirectorySecurity();

            newDescriptor.SetSecurityDescriptorBinaryForm(ntSecurityDescriptor);
            var owner = GetAclOwner(newDescriptor, domainName);

            if (owner != null)
            {
                aces.Add(new ACL
                {
                    AceType       = "",
                    RightName     = "Owner",
                    PrincipalName = owner.PrincipalName,
                    PrincipalType = owner.ObjectType
                });
            }


            foreach (ActiveDirectoryAccessRule ace in newDescriptor.GetAccessRules(true, true, typeof(SecurityIdentifier)))
            {
                //Ignore null aces
                if (ace == null)
                {
                    continue;
                }

                //Ignore Deny aces
                if (!ace.AccessControlType.Equals(AccessControlType.Allow))
                {
                    continue;
                }

                //Resolve the principal in the ACE
                var principal = GetAcePrincipal(ace, domainName);

                //If its null, we don't care so move on
                if (principal == null)
                {
                    continue;
                }

                //Check if our ACE applies through inheritance rules
                if (!CheckAceInheritanceRules(ace, resolved.ObjectType))
                {
                    continue;
                }

                //Interesting Computer ACEs - GenericAll, WriteDacl, GenericWrite, WriteProperty (AllowedToAct), WriteOwner, ExtendedRight (LAPS)
                var rights        = ace.ActiveDirectoryRights;
                var objectAceType = ace.ObjectType.ToString();

                _guidMap.TryGetValue(objectAceType, out var mappedGuid);

                if (rights.HasFlag(ActiveDirectoryRights.GenericAll))
                {
                    if (objectAceType == AllGuid || objectAceType == "")
                    {
                        aces.Add(new ACL
                        {
                            AceType       = "",
                            RightName     = "GenericAll",
                            PrincipalName = principal.PrincipalName,
                            PrincipalType = principal.ObjectType
                        });
                    }
                    else if (mappedGuid != null && mappedGuid == "ms-Mcs-AdmPwd")
                    {
                        aces.Add(new ACL
                        {
                            AceType       = "",
                            RightName     = "ReadLAPSPassword",
                            PrincipalName = principal.PrincipalName,
                            PrincipalType = principal.ObjectType
                        });
                    }
                    //GenericAll includes every other flag, so continue here so we don't duplicate privs
                    continue;
                }

                if (rights.HasFlag(ActiveDirectoryRights.GenericWrite) ||
                    rights.HasFlag(ActiveDirectoryRights.WriteProperty))
                {
                    //GenericWrite encapsulates WriteProperty
                    if (rights.HasFlag(ActiveDirectoryRights.GenericWrite) &&
                        (objectAceType == AllGuid || objectAceType == ""))
                    {
                        aces.Add(new ACL
                        {
                            AceType       = "",
                            RightName     = "GenericWrite",
                            PrincipalName = principal.PrincipalName,
                            PrincipalType = principal.ObjectType
                        });
                    }
                    else if (rights.HasFlag(ActiveDirectoryRights.WriteProperty))
                    {
                        if (objectAceType == AllGuid || objectAceType == "")
                        {
                            aces.Add(new ACL
                            {
                                AceType       = "",
                                RightName     = "GenericWrite",
                                PrincipalName = principal.PrincipalName,
                                PrincipalType = principal.ObjectType
                            });
                        }
                        else if (objectAceType == "3f78c3e5-f79a-46bd-a0b8-9d18116ddc79")
                        {
                            aces.Add(new ACL
                            {
                                AceType       = "AllowedToAct",
                                PrincipalName = principal.PrincipalName,
                                PrincipalType = principal.ObjectType,
                                RightName     = "WriteProperty"
                            });
                        }
                    }
                }

                if (rights.HasFlag(ActiveDirectoryRights.WriteDacl))
                {
                    aces.Add(new ACL
                    {
                        AceType       = "",
                        RightName     = "WriteDacl",
                        PrincipalName = principal.PrincipalName,
                        PrincipalType = principal.ObjectType
                    });
                }

                if (rights.HasFlag(ActiveDirectoryRights.WriteOwner))
                {
                    aces.Add(new ACL
                    {
                        AceType       = "",
                        RightName     = "WriteOwner",
                        PrincipalName = principal.PrincipalName,
                        PrincipalType = principal.ObjectType
                    });
                }

                if (rights.HasFlag(ActiveDirectoryRights.ExtendedRight))
                {
                    if (entry.GetProp("ms-mcs-admpwdexpirationtime") != null)
                    {
                        if (mappedGuid != null && mappedGuid == "ms-Mcs-AdmPwd")
                        {
                            aces.Add(new ACL
                            {
                                AceType       = "",
                                RightName     = "ReadLAPSPassword",
                                PrincipalName = principal.PrincipalName,
                                PrincipalType = principal.ObjectType
                            });
                        }
                        else if (objectAceType == AllGuid || objectAceType == "")
                        {
                            aces.Add(new ACL
                            {
                                AceType       = "All",
                                RightName     = "ExtendedRight",
                                PrincipalName = principal.PrincipalName,
                                PrincipalType = principal.ObjectType
                            });
                        }
                    }
                }
            }

            obj.Aces = aces.Distinct().ToArray();
        }
示例#12
0
        public static void GetObjectAces(SearchResultEntry entry, ResolvedEntry resolved, ref Domain obj)
        {
            if (!Utils.IsMethodSet(ResolvedCollectionMethod.ACL))
            {
                return;
            }

            var aces = new List <ACL>();
            var ntSecurityDescriptor = entry.GetPropBytes("ntsecuritydescriptor");

            //If the ntsecuritydescriptor is null, no point in continuing
            //I'm still not entirely sure what causes this, but it can happen
            if (ntSecurityDescriptor == null)
            {
                return;
            }

            var domainName = Utils.ConvertDnToDomain(entry.DistinguishedName);

            var newDescriptor = new ActiveDirectorySecurity();

            newDescriptor.SetSecurityDescriptorBinaryForm(ntSecurityDescriptor);
            var owner = GetAclOwner(newDescriptor, domainName);

            if (owner != null)
            {
                aces.Add(new ACL
                {
                    AceType       = "",
                    RightName     = "Owner",
                    PrincipalName = owner.PrincipalName,
                    PrincipalType = owner.ObjectType
                });
            }

            foreach (ActiveDirectoryAccessRule ace in newDescriptor.GetAccessRules(true, true, typeof(SecurityIdentifier)))
            {
                //Ignore null aces
                if (ace == null)
                {
                    continue;
                }

                //Ignore Deny aces
                if (!ace.AccessControlType.Equals(AccessControlType.Allow))
                {
                    continue;
                }

                //Resolve the principal in the ACE
                var principal = GetAcePrincipal(ace, domainName);

                //If its null, we don't care so move on
                if (principal == null)
                {
                    continue;
                }

                //Check if our ACE applies through inheritance rules
                if (!CheckAceInheritanceRules(ace, resolved.ObjectType))
                {
                    continue;
                }

                //Interesting Domain ACEs - GenericAll, WriteDacl, WriteOwner, Replication Rights, AllExtendedRights
                var rights        = ace.ActiveDirectoryRights;
                var objectAceType = ace.ObjectType.ToString();

                if (rights.HasFlag(ActiveDirectoryRights.GenericAll))
                {
                    if (objectAceType == AllGuid || objectAceType == "")
                    {
                        aces.Add(new ACL
                        {
                            AceType       = "",
                            RightName     = "GenericAll",
                            PrincipalName = principal.PrincipalName,
                            PrincipalType = principal.ObjectType
                        });
                    }
                    //GenericAll includes every other flag, so continue here so we don't duplicate privs
                    continue;
                }

                if (rights.HasFlag(ActiveDirectoryRights.WriteDacl))
                {
                    aces.Add(new ACL
                    {
                        AceType       = "",
                        RightName     = "WriteDacl",
                        PrincipalName = principal.PrincipalName,
                        PrincipalType = principal.ObjectType
                    });
                }

                if (rights.HasFlag(ActiveDirectoryRights.WriteOwner))
                {
                    aces.Add(new ACL
                    {
                        AceType       = "",
                        RightName     = "WriteOwner",
                        PrincipalName = principal.PrincipalName,
                        PrincipalType = principal.ObjectType
                    });
                }

                if (rights.HasFlag(ActiveDirectoryRights.ExtendedRight))
                {
                    if (objectAceType == "1131f6aa-9c07-11d1-f79f-00c04fc2dcd2")
                    {
                        aces.Add(new ACL
                        {
                            AceType       = "GetChanges",
                            RightName     = "ExtendedRight",
                            PrincipalName = principal.PrincipalName,
                            PrincipalType = principal.ObjectType
                        });
                    }
                    else if (objectAceType == "1131f6ad-9c07-11d1-f79f-00c04fc2dcd2")
                    {
                        aces.Add(new ACL
                        {
                            AceType       = "GetChangesAll",
                            RightName     = "ExtendedRight",
                            PrincipalName = principal.PrincipalName,
                            PrincipalType = principal.ObjectType
                        });
                    }
                    else if (objectAceType == AllGuid || objectAceType == "")
                    {
                        aces.Add(new ACL
                        {
                            AceType       = "All",
                            RightName     = "ExtendedRight",
                            PrincipalName = principal.PrincipalName,
                            PrincipalType = principal.ObjectType
                        });
                    }
                }
            }

            obj.Aces = aces.Distinct().ToArray();
        }
示例#13
0
        public static IEnumerable <Session> GetNetSessions(ResolvedEntry target, string computerDomain)
        {
            if (!Utils.IsMethodSet(ResolvedCollectionMethod.Session) &&
                !Utils.IsMethodSet(ResolvedCollectionMethod.SessionLoop))
            {
                yield break;
            }

            Utils.Debug($"Starting NetSessionEnum for {target.IngestCacheDisplay}");
            var resumeHandle = IntPtr.Zero;
            var si10         = typeof(SESSION_INFO_10);

            var entriesRead = 0;
            var ptrInfo     = IntPtr.Zero;

            var t = Task <int> .Factory.StartNew(() => NetSessionEnum(target.IngestCacheDisplay, null, null, 10,
                                                                      out ptrInfo, -1, out entriesRead,
                                                                      out _, ref resumeHandle));

            var success = t.Wait(Timeout);

            if (!success)
            {
                throw new TimeoutException();
            }

            var returnValue = t.Result;

            Utils.Debug($"EntriesRead from NetSessionEnum: {entriesRead}");
            Utils.Debug($"ReturnValue from NetSessionEnum: {returnValue}");

            //If we don't get a success, just break
            if (returnValue != (int)NERR.NERR_Success)
            {
                yield break;
            }

            var results = new SESSION_INFO_10[entriesRead];
            var iter    = ptrInfo;

            //Loop over the data and store it into an array
            for (var i = 0; i < entriesRead; i++)
            {
                results[i] = (SESSION_INFO_10)Marshal.PtrToStructure(iter, si10);
                iter       = (IntPtr)(iter.ToInt64() + Marshal.SizeOf(si10));
            }

            //Free the IntPtr
            NetApiBufferFree(ptrInfo);
            foreach (var result in results)
            {
                var username = result.sesi10_username;
                var cname    = result.sesi10_cname;

                if (cname == null || username.EndsWith("$") || username.Trim() == "" || username == "$" ||
                    username == _options.CurrentUser || username == "ANONYMOUS LOGON")
                {
                    continue;
                }

                if (cname.StartsWith("\\", StringComparison.CurrentCulture))
                {
                    cname = cname.TrimStart('\\');
                }

                if (cname.Equals("[::1]") || cname.Equals("127.0.0.1"))
                {
                    cname = target.IngestCacheDisplay;
                }

                Utils.Debug($"Result Username: {username}");

                Utils.Debug($"Original cname: {cname}");
                var watch       = Stopwatch.StartNew();
                var dnsHostName = _utils.ResolveCname(cname, computerDomain).Replace("\\", "");
                watch.Stop();
                Utils.Debug($"Name resolution took {watch.ElapsedMilliseconds}");
                Utils.Debug($"Result cname: {dnsHostName}");

                //If we're skipping Global Catalog deconfliction, just return a session
                if (_options.SkipGcDeconfliction)
                {
                    yield return(new Session {
                        ComputerName = dnsHostName, UserName = username, Weight = 2
                    });
                }
                else
                {
                    //Check our cache first
                    if (!_cache.GetGcMap(username.ToUpper(), out var possible))
                    {
                        Utils.Debug($"Missed cache hit for {username}");
                        //If we didn't get a cache hit, search the global catalog
                        var temp = new List <string>();
                        foreach (var entry in _utils.DoSearch(
                                     $"(&(samAccountType=805306368)(samaccountname={username}))", SearchScope.Subtree,
                                     new[] { "distinguishedname" }, useGc: true))
                        {
                            temp.Add(Utils.ConvertDnToDomain(entry.DistinguishedName).ToUpper());
                        }

                        possible = temp.ToArray();
                        _cache.AddGcMap(username.ToUpper(), possible);
                    }
                    else
                    {
                        Utils.Debug($"Cache hit for {username}");
                        if (possible == null)
                        {
                            possible = new string[0];
                        }
                    }

                    switch (possible.Length)
                    {
                    case 0:
                        //Object isn't in GC, so we'll default to the computer's domain
                        yield return(new Session
                        {
                            UserName = $"{username}@{computerDomain}",
                            ComputerName = dnsHostName,
                            Weight = 2
                        });

                        break;

                    case 1:
                        //Exactly one instance of this samaccountname, the best scenario
                        yield return(new Session
                        {
                            UserName = $"{username}@{possible.First()}",
                            ComputerName = dnsHostName,
                            Weight = 2
                        });

                        break;

                    default:
                        //Multiple possibilities (whyyyyy)
                        //Add a weight of 1 for same domain as computer, 2 for others
                        foreach (var possibility in possible)
                        {
                            var weight = possibility.Equals(computerDomain, StringComparison.CurrentCultureIgnoreCase) ? 1 : 2;

                            yield return(new Session
                            {
                                Weight = weight,
                                ComputerName = dnsHostName.ToUpper(),
                                UserName = $"{username}@{possibility}"
                            });
                        }
                        break;
                    }
                }
            }

            Utils.DoJitter();
        }
示例#14
0
        public static void GetGroupInfo(SearchResultEntry entry, ResolvedEntry resolved, string domainSid, ref Group u)
        {
            if (!Utils.IsMethodSet(ResolvedCollectionMethod.Group))
            {
                return;
            }

            var fMembers             = new List <GroupMember>();
            var principalDisplayName = resolved.IngestCacheDisplay;
            var principalDomainName  = Utils.ConvertDnToDomain(entry.DistinguishedName);

            if (resolved.ObjectType == "group")
            {
                _cache.AddMapValue(entry.DistinguishedName, "group", principalDisplayName);
            }

            var members = entry.GetPropArray("member");

            if (members.Length == 0)
            {
                var tempMembers = new List <string>();
                var bottom      = 0;

                while (true)
                {
                    var top   = bottom + 1499;
                    var range = $"member;range={bottom}-{top}";
                    bottom += 1500;
                    //Try ranged retrieval
                    var result = _utils.DoSearch("(objectclass=*)", SearchScope.Base, new[] { range },
                                                 principalDomainName,
                                                 entry.DistinguishedName).DefaultIfEmpty(null).FirstOrDefault();

                    //We didn't get an object back. Break out of the loop
                    if (result?.Attributes.AttributeNames == null)
                    {
                        break;
                    }
                    var en = result.Attributes.AttributeNames.GetEnumerator();

                    //If the enumerator fails, that means theres really no members at all
                    if (!en.MoveNext())
                    {
                        break;
                    }

                    if (en.Current == null)
                    {
                        continue;
                    }
                    var attrib = en.Current.ToString();
                    if (attrib.EndsWith("-*"))
                    {
                        //We're done here, no more members to grab
                        break;
                    }
                    tempMembers.AddRange(result.GetPropArray(attrib));
                }

                members = tempMembers.ToArray();
            }

            foreach (var dn in members)
            {
                //Check our cache first
                if (!_cache.GetMapValueUnknownType(dn, out var principal))
                {
                    if (dn.Contains("ForeignSecurityPrincipals"))
                    {
                        var sid = dn.Split(',')[0].Substring(3);
                        if (dn.Contains("CN=S-1-5-21"))
                        {
                            var domain = _utils.SidToDomainName(sid);
                            if (domain == null)
                            {
                                Utils.Verbose($"Unable to resolve domain for FSP {dn}");
                                continue;
                            }

                            principal = _utils.UnknownSidTypeToDisplay(sid, domain, Props);
                        }
                        else
                        {
                            if (!MappedPrincipal.GetCommon(sid, out principal))
                            {
                                continue;
                            }

                            principal.PrincipalName = $"{principal.PrincipalName}@{principalDomainName}";
                        }
                    }
                    else
                    {
                        var objEntry = _utils
                                       .DoSearch("(objectclass=*)", SearchScope.Base, Props, Utils.ConvertDnToDomain(dn), dn)
                                       .DefaultIfEmpty(null).FirstOrDefault();

                        if (objEntry == null)
                        {
                            principal = null;
                        }
                        else
                        {
                            var resolvedObj = objEntry.ResolveAdEntry();
                            if (resolvedObj == null || resolvedObj.ObjectType == "domain")
                            {
                                principal = null;
                            }
                            else
                            {
                                _cache.AddMapValue(dn, resolvedObj.ObjectType, resolvedObj.IngestCacheDisplay);
                                principal = new MappedPrincipal
                                            (
                                    resolvedObj.IngestCacheDisplay,
                                    resolvedObj.ObjectType
                                            );
                            }
                        }
                    }
                }

                if (principal != null)
                {
                    fMembers.Add(new GroupMember
                    {
                        MemberName = principal.PrincipalName,
                        MemberType = principal.ObjectType
                    });
                }
            }

            u.Members = fMembers.Distinct().ToArray();
        }
示例#15
0
        internal static void GetProps(SearchResultEntry entry, ResolvedEntry resolved, ref Computer obj)
        {
            if (!Utils.IsMethodSet(ResolvedCollectionMethod.ObjectProps))
            {
                return;
            }
            var  uac = entry.GetProp("useraccountcontrol");
            bool enabled, unconstrained, trustedToAuth;

            if (int.TryParse(uac, out var flag))
            {
                var flags = (UacFlags)flag;
                enabled       = (flags & UacFlags.AccountDisable) == 0;
                unconstrained = (flags & UacFlags.TrustedForDelegation) == UacFlags.TrustedForDelegation;
                trustedToAuth = (flags & UacFlags.TrustedToAuthForDelegation) != 0;
            }
            else
            {
                unconstrained = false;
                enabled       = true;
                trustedToAuth = false;
            }

            var comps = new List <string>();

            if (trustedToAuth)
            {
                var delegates = entry.GetPropArray("msds-allowedToDelegateTo");
                obj.Properties.Add("allowedtodelegate", delegates);

                foreach (var d in delegates)
                {
                    var hname = d.Contains("/") ? d.Split('/')[1] : d;
                    hname = hname.Split(':')[0];
                    var resolvedHost =
                        Utils.Instance.ResolveHost(hname, Utils.ConvertDnToDomain(entry.DistinguishedName));
                    if (resolvedHost.Contains("."))
                    {
                        comps.Add(resolvedHost.ToUpper());
                    }
                }
            }
            obj.AllowedToDelegate = comps.Distinct().ToArray();

            var allowedToAct = entry.GetPropBytes("msDS-AllowedToActOnBehalfOfOtherIdentity");

            if (allowedToAct != null)
            {
                var principals = new List <LocalMember>();
                var sd         = new ActiveDirectorySecurity();
                sd.SetSecurityDescriptorBinaryForm(allowedToAct, AccessControlSections.Access);
                var utils = Utils.Instance;
                foreach (ActiveDirectoryAccessRule rule in sd.GetAccessRules(true, true, typeof(SecurityIdentifier)))
                {
                    var sid    = rule.IdentityReference.Value;
                    var domain = utils.SidToDomainName(sid) ?? Utils.ConvertDnToDomain(entry.DistinguishedName);
                    if (!MappedPrincipal.GetCommon(sid, out var principal))
                    {
                        principal = utils.UnknownSidTypeToDisplay(sid, domain, Props);
                    }
                    else
                    {
                        if (sid == "S-1-5-9")
                        {
                            var dObj = utils.GetForest(domain);
                            var d    = dObj == null ? domain : dObj.RootDomain.Name;
                            principal.PrincipalName = $"ENTERPRISE DOMAIN CONTROLLERS@{d}".ToUpper();
                        }
                        else
                        {
                            principal.PrincipalName = $"{principal.PrincipalName}@{domain}".ToUpper();
                        }
                    }

                    if (principal == null)
                    {
                        continue;
                    }

                    principals.Add(new LocalMember
                    {
                        Name = principal.PrincipalName,
                        Type = principal.ObjectType
                    });
                }

                obj.AllowedToAct = principals.ToArray();
            }

            obj.Properties.Add("enabled", enabled);
            obj.Properties.Add("unconstraineddelegation", unconstrained);
            obj.Properties.Add("lastlogon", ConvertToUnixEpoch(entry.GetProp("lastlogon")));
            obj.Properties.Add("lastlogontimestamp", ConvertToUnixEpoch(entry.GetProp("lastlogontimestamp")));
            obj.Properties.Add("pwdlastset", ConvertToUnixEpoch(entry.GetProp("pwdlastset")));
            obj.Properties.Add("serviceprincipalnames", entry.GetPropArray("serviceprincipalname"));
            var os = entry.GetProp("operatingsystem");
            var sp = entry.GetProp("operatingsystemservicepack");

            if (sp != null)
            {
                os = $"{os} {sp}";
            }

            obj.Properties.Add("operatingsystem", os);
            obj.Properties.Add("description", entry.GetProp("description"));
        }
示例#16
0
        private static SamEnumerationObject[] NetLocalGroupGetMembers(ResolvedEntry entry, int rid, out string machineSid)
        {
            Utils.Debug("Starting NetLocalGroupGetMembers");
            var server = new UNICODE_STRING(entry.IngestCacheDisplay);
            //Connect to the server with the proper access maskes. This gives us our server handle
            var obj = default(OBJECT_ATTRIBUTES);

            Utils.Debug("Starting SamConnect");
            var status = SamConnect(ref server, out var serverHandle,
                                    SamAccessMasks.SamServerLookupDomain |
                                    SamAccessMasks.SamServerConnect, ref obj);

            Utils.Debug($"SamConnect returned {status}");
            switch (status)
            {
            case NtStatus.StatusRpcServerUnavailable:
                throw new SystemDownException();

            case NtStatus.StatusSuccess:
                break;

            default:
                throw new ApiFailedException();
            }

            Utils.Debug("Starting SamLookupDomainInSamServer");

            //Use SamLookupDomainInServer with the hostname to find the machine sid if possible
            try
            {
                var san = new UNICODE_STRING(entry.ComputerSamAccountName);
                SamLookupDomainInSamServer(serverHandle, ref san, out var temp);
                //This will throw an exception if we didn't actually find the alias
                machineSid = new SecurityIdentifier(temp).Value;
                SamFreeMemory(temp);
            }
            catch
            {
                machineSid = "DUMMYSTRINGSHOULDNOTMATCH";
            }

            Utils.Debug($"Resolved Machine Sid {machineSid}");

            Utils.Debug("Starting SamOpenDomain");
            //Open the domain for the S-1-5-32 (BUILTIN) alias
            status = SamOpenDomain(serverHandle, DomainAccessMask.Lookup, _sidbytes, out var domainHandle);
            Utils.Debug($"SamOpenDomain returned {status}");
            if (!status.Equals(NtStatus.StatusSuccess))
            {
                SamCloseHandle(serverHandle);
                throw new ApiFailedException();
            }

            Utils.Debug("Starting SamOpenAlias");
            //Open the alias for the desired RID
            status = SamOpenAlias(domainHandle, AliasOpenFlags.ListMembers, rid, out var aliasHandle);
            Utils.Debug($"SamOpenAlias returned {status}");
            if (!status.Equals(NtStatus.StatusSuccess))
            {
                SamCloseHandle(domainHandle);
                SamCloseHandle(serverHandle);
                throw new ApiFailedException();
            }

            Utils.Debug("Starting SamGetMembersInAlias");
            //Get the members in the alias. This returns a list of SIDs
            status = SamGetMembersInAlias(aliasHandle, out var members, out var count);
            Utils.Debug($"SamGetMembersInAlias returned {status}");
            if (!status.Equals(NtStatus.StatusSuccess))
            {
                SamCloseHandle(aliasHandle);
                SamCloseHandle(domainHandle);
                SamCloseHandle(serverHandle);
                throw new ApiFailedException();
            }

            Utils.Debug("Cleaning up handles");
            SamCloseHandle(aliasHandle);
            SamCloseHandle(domainHandle);
            SamCloseHandle(serverHandle);

            if (count == 0)
            {
                SamFreeMemory(members);
                return(new SamEnumerationObject[0]);
            }

            Utils.Debug("Copying data");
            //Copy the data of our sids to a new array so it doesn't get eaten
            var grabbedSids = new IntPtr[count];

            Marshal.Copy(members, grabbedSids, 0, count);

            var sids = new string[count];

            //Convert the bytes to strings for usage
            for (var i = 0; i < count; i++)
            {
                try
                {
                    sids[i] = new SecurityIdentifier(grabbedSids[i]).Value;
                }
                catch
                {
                    sids[i] = null;
                }
            }



            Utils.Debug("Starting LsaOpenPolicy");
            //Open the LSA policy on the target machine
            var obja = default(OBJECT_ATTRIBUTES);

            status = LsaOpenPolicy(ref server, ref obja,
                                   LsaOpenMask.ViewLocalInfo | LsaOpenMask.LookupNames, out var policyHandle);
            Utils.Debug($"LSAOpenPolicy returned {status}");
            if (!status.Equals(NtStatus.StatusSuccess))
            {
                LsaClose(policyHandle);
                SamFreeMemory(members);
                throw new ApiFailedException();
            }

            Utils.Debug("Starting LSALookupSids");
            var nameList   = IntPtr.Zero;
            var domainList = IntPtr.Zero;

            //Call LsaLookupSids using the sids we got from SamGetMembersInAlias
            status = LsaLookupSids(policyHandle, count, members, ref domainList,
                                   ref nameList);
            Utils.Debug($"LSALookupSids returned {status}");
            if (!status.Equals(NtStatus.StatusSuccess) && !status.Equals(NtStatus.StatusSomeMapped))
            {
                LsaClose(policyHandle);
                LsaFreeMemory(domainList);
                LsaFreeMemory(nameList);
                SamFreeMemory(members);
                throw new ApiFailedException();
            }

            Utils.Debug("Finished API calls");
            //Convert the returned names into structures
            var iter            = nameList;
            var translatedNames = new LsaTranslatedNames[count];

            Utils.Debug("Resolving names");
            for (var i = 0; i < count; i++)
            {
                translatedNames[i] = (LsaTranslatedNames)Marshal.PtrToStructure(iter, typeof(LsaTranslatedNames));
                iter = (IntPtr)(iter.ToInt64() + Marshal.SizeOf(typeof(LsaTranslatedNames)));
            }

            Utils.Debug("Resolving domains");
            //Convert the returned domain list to a structure
            var lsaDomainList =
                (LsaReferencedDomainList)(Marshal.PtrToStructure(domainList, typeof(LsaReferencedDomainList)));

            //Convert the domain list to individual structures
            var trustInfos = new LsaTrustInformation[lsaDomainList.count];

            iter = lsaDomainList.domains;
            for (var i = 0; i < lsaDomainList.count; i++)
            {
                trustInfos[i] = (LsaTrustInformation)Marshal.PtrToStructure(iter, typeof(LsaTrustInformation));
                iter          = (IntPtr)(iter.ToInt64() + Marshal.SizeOf(typeof(LsaTrustInformation)));
            }

            Utils.Debug("Matching up data");
            var resolvedObjects = new SamEnumerationObject[translatedNames.Length];

            //Match up sids, domain names, and account names
            for (var i = 0; i < translatedNames.Length; i++)
            {
                var x = translatedNames[i];

                if (x.DomainIndex > trustInfos.Length || x.DomainIndex < 0 || trustInfos.Length == 0)
                {
                    continue;
                }

                resolvedObjects[i] =
                    new SamEnumerationObject
                {
                    AccountDomain = trustInfos[x.DomainIndex].name.ToString(),
                    AccountName   = x.Name.ToString(),
                    AccountSid    = sids[i],
                    SidUsage      = x.Use
                };
            }

            Utils.Debug("Cleaning up");
            //Cleanup
            SamFreeMemory(members);
            LsaFreeMemory(domainList);
            LsaFreeMemory(nameList);
            LsaClose(policyHandle);
            Utils.Debug("Done NetLocalGroupGetMembers");
            return(resolvedObjects);
        }
示例#17
0
        internal static void DoTrustEnumeration(ResolvedEntry resolved, ref Domain obj)
        {
            if (!Utils.IsMethodSet(ResolvedCollectionMethod.Trusts))
            {
                return;
            }

            if (resolved == null)
            {
                return;
            }

            var trusts = new List <Trust>();
            var dc     = _utils.GetUsableDomainController(_utils.GetDomain(resolved.IngestCacheDisplay));

            //var dc = _utils
            //    .DoSearch("(userAccountControl:1.2.840.113556.1.4.803:=8192)", SearchScope.Subtree,
            //        new[] { "dnshostname" }, resolved.IngestCacheDisplay).DefaultIfEmpty(null).FirstOrDefault();

            if (dc == null)
            {
                return;
            }


            const uint flags  = 63;
            var        ddt    = typeof(DsDomainTrusts);
            var        result = DsEnumerateDomainTrusts(dc, flags, out var ptr, out var domainCount);

            if (result != 0)
            {
                return;
            }

            var array = new DsDomainTrusts[domainCount];

            var iter = ptr;

            //Loop over the data and store it in an array
            for (var i = 0; i < domainCount; i++)
            {
                array[i] = (DsDomainTrusts)Marshal.PtrToStructure(iter, ddt);
                iter     = (IntPtr)(iter.ToInt64() + Marshal.SizeOf(ddt));
            }

            NetApiBufferFree(ptr);

            for (var i = 0; i < domainCount; i++)
            {
                var trust = new Trust();

                var data         = array[i];
                var trustFlags   = (TrustFlags)data.Flags;
                var trustAttribs = (TrustAttrib)data.TrustAttributes;

                // the domain itself
                if ((trustFlags & TrustFlags.DsDomainPrimary) == TrustFlags.DsDomainPrimary)
                {
                    continue;
                }

                if (data.DnsDomainName == null)
                {
                    continue;
                }
                trust.TargetName = data.DnsDomainName;
                var inbound  = (trustFlags & TrustFlags.DsDomainDirectInbound) == TrustFlags.DsDomainDirectInbound;
                var outbound = (trustFlags & TrustFlags.DsDomainDirectOutbound) == TrustFlags.DsDomainDirectOutbound;

                if (inbound && outbound)
                {
                    trust.TrustDirection = (int)TrustDirection.Bidirectional;
                }
                else if (inbound)
                {
                    trust.TrustDirection = (int)TrustDirection.Inbound;
                }
                else if (outbound)
                {
                    trust.TrustDirection = (int)TrustDirection.Outbound;
                }
                else
                {
                    // a trust with no direction is probably not enabled (According to MS documentation)
                    // see: https://docs.microsoft.com/fr-fr/windows/desktop/api/ntsecapi/ns-ntsecapi-_trusted_domain_information_ex (TrustDirection)
                    continue;
                }

                // parentChild occure only when one of the domain is the forest root
                // Check is trusted domain is the current forest root or if trusted domain's parent is current enumerated domain
                if (((trustFlags & TrustFlags.DsDomainTreeRoot) == TrustFlags.DsDomainTreeRoot) && ((trustFlags & TrustFlags.DsDomainInForest) == TrustFlags.DsDomainInForest) ||
                    array[data.ParentIndex].DnsDomainName.ToUpper() == resolved.IngestCacheDisplay)
                {
                    trust.TrustType = "ParentChild";
                }
                else if ((trustFlags & TrustFlags.DsDomainInForest) == TrustFlags.DsDomainInForest)
                {
                    trust.TrustType = "CrossLink";
                }
                else if ((trustAttribs & TrustAttrib.ForestTransitive) == TrustAttrib.ForestTransitive)
                {
                    trust.TrustType = "Forest";
                }
                else
                {
                    trust.TrustType = "External";
                }

                if ((trustAttribs & TrustAttrib.NonTransitive) == TrustAttrib.NonTransitive)
                {
                    trust.IsTransitive = false;
                }
                else
                {
                    trust.IsTransitive = true;
                }

                trusts.Add(trust);
            }

            obj.Trusts = trusts.ToArray();
        }
示例#18
0
        internal static void GetProps(SearchResultEntry entry, ResolvedEntry resolved, ref User obj)
        {
            if (!Utils.IsMethodSet(ResolvedCollectionMethod.ObjectProps))
            {
                return;
            }
            var  uac = entry.GetProp("useraccountcontrol");
            bool enabled, trustedToAuth, sensitive, dontReqPreAuth, passwdNotReq, unconstrained;

            if (int.TryParse(uac, out var flag))
            {
                var flags = (UacFlags)flag;
                enabled        = (flags & UacFlags.AccountDisable) == 0;
                trustedToAuth  = (flags & UacFlags.TrustedToAuthForDelegation) != 0;
                sensitive      = (flags & UacFlags.NotDelegated) != 0;
                dontReqPreAuth = (flags & UacFlags.DontReqPreauth) != 0;
                passwdNotReq   = (flags & UacFlags.PasswordNotRequired) != 0;
                unconstrained  = (flags & UacFlags.TrustedForDelegation) != 0;
            }
            else
            {
                trustedToAuth  = false;
                enabled        = true;
                sensitive      = false;
                dontReqPreAuth = false;
                passwdNotReq   = false;
                unconstrained  = false;
            }

            var comps = new List <string>();

            if (trustedToAuth)
            {
                var delegates = entry.GetPropArray("msds-allowedToDelegateTo");
                obj.Properties.Add("allowedtodelegate", delegates);

                foreach (var d in delegates)
                {
                    var hname = d.Contains("/") ? d.Split('/')[1] : d;
                    hname = hname.Split(':')[0];
                    var resolvedHost = Utils.Instance.ResolveHost(hname, Utils.ConvertDnToDomain(entry.DistinguishedName));
                    if (resolvedHost.Contains("."))
                    {
                        comps.Add(resolvedHost.ToUpper());
                    }
                }
            }
            obj.AllowedToDelegate = comps.Distinct().ToArray();

            obj.Properties.Add("enabled", enabled);
            //var history = entry.GetPropBytes("sidhistory");
            //obj.SidHistory = history != null ? new SecurityIdentifier(history, 0).Value : "";
            obj.Properties.Add("lastlogon", ConvertToUnixEpoch(entry.GetProp("lastlogon")));
            obj.Properties.Add("lastlogontimestamp", ConvertToUnixEpoch(entry.GetProp("lastlogontimestamp")));
            obj.Properties.Add("pwdlastset", ConvertToUnixEpoch(entry.GetProp("pwdlastset")));
            var spn = entry.GetPropArray("serviceprincipalname");

            obj.Properties.Add("serviceprincipalnames", spn);
            obj.Properties.Add("hasspn", spn.Length > 0);
            obj.Properties.Add("displayname", entry.GetProp("displayname"));
            obj.Properties.Add("email", entry.GetProp("mail"));
            obj.Properties.Add("title", entry.GetProp("title"));
            obj.Properties.Add("homedirectory", entry.GetProp("homedirectory"));
            obj.Properties.Add("description", entry.GetProp("description"));
            obj.Properties.Add("userpassword", entry.GetProp("userpassword"));
            obj.Properties.Add("sensitive", sensitive);
            obj.Properties.Add("dontreqpreauth", dontReqPreAuth);
            obj.Properties.Add("passwordnotreqd", passwdNotReq);
            obj.Properties.Add("unconstraineddelegation", unconstrained);
            var ac = entry.GetProp("admincount");

            if (ac != null)
            {
                var a = int.Parse(ac);
                obj.Properties.Add("admincount", a != 0);
            }
            else
            {
                obj.Properties.Add("admincount", false);
            }
        }