/// <summary> /// Enumerate all the trusts for the specified domain /// </summary> /// <param name="domain">Domain to enumerate</param> /// <returns>A list of DomainTrust objects for the domain </returns> public static IEnumerable <DomainTrust> DoTrustEnumeration(string domain) { if (domain == null || domain.Trim() == "") { yield break; } Utils.Verbose($"Enumerating trusts for {domain}"); var dc = _utils .DoSearch("(userAccountControl:1.2.840.113556.1.4.803:=8192)", SearchScope.Subtree, new[] { "dnshostname" }, domain).DefaultIfEmpty(null).FirstOrDefault(); if (dc == null) { yield break; } const uint flags = 63; var ddt = typeof(DsDomainTrusts); var result = DsEnumerateDomainTrusts(dc.GetProp("dnshostname"), flags, out var ptr, out var domainCount); if (result != 0) { yield break; } 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 DomainTrust { SourceDomain = domain }; var data = array[i]; var trustType = (TrustType)data.Flags; var trustAttribs = (TrustAttrib)data.TrustAttributes; if ((trustType & TrustType.DsDomainTreeRoot) == TrustType.DsDomainTreeRoot) { continue; } trust.TargetDomain = data.DnsDomainName; var inbound = (trustType & TrustType.DsDomainDirectInbound) == TrustType.DsDomainDirectInbound; var outbound = (trustType & TrustType.DsDomainDirectOutbound) == TrustType.DsDomainDirectOutbound; if (inbound && outbound) { trust.TrustDirection = "Bidirectional"; } else if (inbound) { trust.TrustDirection = "Inbound"; } else { trust.TrustDirection = "Outbound"; } trust.TrustType = (trustType & TrustType.DsDomainInForest) == TrustType.DsDomainInForest ? "ParentChild" : "External"; if ((trustAttribs & TrustAttrib.NonTransitive) == TrustAttrib.NonTransitive) { trust.IsTransitive = false; } yield return(trust); } }
/// <summary> /// Processes domain trusts for a domain object /// </summary> /// <param name="domain"></param> /// <returns></returns> public IEnumerable <DomainTrust> EnumerateDomainTrusts(string domain) { var query = CommonFilters.TrustedDomains; foreach (var result in _utils.QueryLDAP(query, SearchScope.Subtree, CommonProperties.DomainTrustProps, domain)) { var trust = new DomainTrust(); var targetSidBytes = result.GetByteProperty(LDAPProperties.SecurityIdentifier); if (targetSidBytes == null || targetSidBytes.Length == 0) { _log.LogTrace("Trust sid is null or empty for target: {Domain}", domain); continue; } string sid; try { sid = new SecurityIdentifier(targetSidBytes, 0).Value; } catch { _log.LogTrace("Failed to convert bytes to SID for target: {Domain}", domain); continue; } trust.TargetDomainSid = sid; if (int.TryParse(result.GetProperty(LDAPProperties.TrustDirection), out var td)) { trust.TrustDirection = (TrustDirection)td; } else { _log.LogTrace("Failed to convert trustdirection for target: {Domain}", domain); continue; } TrustAttributes attributes; if (int.TryParse(result.GetProperty(LDAPProperties.TrustAttributes), out var ta)) { attributes = (TrustAttributes)ta; } else { _log.LogTrace("Failed to convert trustattributes for target: {Domain}", domain); continue; } trust.IsTransitive = (attributes & TrustAttributes.NonTransitive) == 0; var name = result.GetProperty(LDAPProperties.CanonicalName)?.ToUpper(); if (name != null) { trust.TargetDomainName = name; } trust.SidFilteringEnabled = (attributes & TrustAttributes.FilterSids) != 0; trust.TrustType = TrustAttributesToType(attributes); yield return(trust); } }
public void GetDomainsAndTrusts(string DomainName) { if (dbmanager.IsDomainCompleted(DomainName) && !options.Rebuild) { return; } Console.WriteLine($"Building Domain Trust Data for {DomainName}"); List <string> enumerated = new List <string>(); Queue <string> ToEnum = new Queue <string>(); //Get our current domain's info string current = DomainName; ToEnum.Enqueue(current); //Convert the DNS name to the NetBIOS name IntPtr pDCI = IntPtr.Zero; DOMAIN_CONTROLLER_INFO info; int dsresult = DsGetDcName(null, current, 0, null, DSGETDCNAME_FLAGS.DS_IS_DNS_NAME | DSGETDCNAME_FLAGS.DS_RETURN_FLAT_NAME, out pDCI); info = (DOMAIN_CONTROLLER_INFO)Marshal.PtrToStructure(pDCI, typeof(DOMAIN_CONTROLLER_INFO)); string netbiosname = info.DomainName; NetApiBufferFree(pDCI); options.WriteVerbose("Grabbed initial trusts"); DomainDB temp = new DomainDB() { Completed = false, DomainDNSName = current, DomainShortName = netbiosname, DomainSid = helpers.GetDomainSid(current), Trusts = new List <DomainTrust>() }; dbmanager.InsertDomain(temp); while (!(ToEnum.Count == 0)) { string d = ToEnum.Dequeue(); dbmanager.GetDomain(d, out temp); enumerated.Add(d); options.WriteVerbose($"Grabbing trusts for {d}"); temp.DomainDNSName = d; DirectorySearcher searcher = helpers.GetDomainSearcher(d); if (searcher == null) { continue; } searcher.Filter = "(userAccountControl:1.2.840.113556.1.4.803:=8192)"; string server; try { SearchResult dc = searcher.FindOne(); server = dc.GetProp("dnshostname"); } catch { options.WriteVerbose($"Unable to get Domain Controller for {DomainName}"); continue; } searcher.Dispose(); List <DomainTrust> trusts = new List <DomainTrust>(); IntPtr ptr = IntPtr.Zero; uint types = 63; Type DDT = typeof(DS_DOMAIN_TRUSTS); uint result = DsEnumerateDomainTrusts(server, types, out ptr, out uint domaincount); int error = Marshal.GetLastWin32Error(); if (result == 0) { DS_DOMAIN_TRUSTS[] array = new DS_DOMAIN_TRUSTS[domaincount]; IntPtr iter = ptr; for (int i = 0; i < domaincount; i++) { DS_DOMAIN_TRUSTS t = (DS_DOMAIN_TRUSTS)Marshal.PtrToStructure(iter, DDT); array[i] = t; iter = (IntPtr)(iter.ToInt64() + Marshal.SizeOf(DDT)); } for (int i = 0; i < domaincount; i++) { DS_DOMAIN_TRUSTS t = array[i]; string dns = t.DnsDomainName; string netbios = t.NetbiosDomainName; TRUST_TYPE trust_type = (TRUST_TYPE)t.Flags; TRUST_ATTRIB trust_attrib = (TRUST_ATTRIB)t.TrustAttributes; if ((trust_type & TRUST_TYPE.DS_DOMAIN_TREE_ROOT) == TRUST_TYPE.DS_DOMAIN_TREE_ROOT) { continue; } DomainDB tempdomain = new DomainDB() { DomainDNSName = dns, DomainShortName = netbios }; ConvertSidToStringSid(t.DomainSid, out string s); tempdomain.DomainSid = s; tempdomain.Completed = false; tempdomain.Trusts = new List <DomainTrust>(); dbmanager.InsertDomain(tempdomain); DomainTrust temptrust = new DomainTrust() { TargetDomain = t.DnsDomainName }; bool inbound = false; bool outbound = false; inbound = (trust_type & TRUST_TYPE.DS_DOMAIN_DIRECT_INBOUND) == TRUST_TYPE.DS_DOMAIN_DIRECT_INBOUND; outbound = (trust_type & TRUST_TYPE.DS_DOMAIN_DIRECT_OUTBOUND) == TRUST_TYPE.DS_DOMAIN_DIRECT_OUTBOUND; if (inbound && outbound) { temptrust.TrustDirection = "Bidirectional"; } else if (inbound) { temptrust.TrustDirection = "Inbound"; } else { temptrust.TrustDirection = "Outbound"; } if ((trust_type & TRUST_TYPE.DS_DOMAIN_IN_FOREST) == TRUST_TYPE.DS_DOMAIN_IN_FOREST) { temptrust.TrustType = "ParentChild"; } else { temptrust.TrustType = "External"; } temptrust.IsTransitive = !((trust_attrib & TRUST_ATTRIB.NON_TRANSITIVE) == TRUST_ATTRIB.NON_TRANSITIVE); temptrust.SourceDomain = dns; trusts.Add(temptrust); if (!enumerated.Contains(dns)) { ToEnum.Enqueue(dns); } } temp.Trusts = trusts; dbmanager.InsertDomain(temp); NetApiBufferFree(ptr); } } }
public void StartEnumeration() { Console.WriteLine("Writing Domain Trusts"); BlockingCollection <DomainTrust> output = new BlockingCollection <DomainTrust>(); Task writer = CreateWriter(output); if (options.NoDB) { Dictionary <string, DomainDB> map = new Dictionary <string, DomainDB>(); foreach (string DomainName in helpers.GetDomainList()) { List <string> enumerated = new List <string>(); Queue <string> queue = new Queue <string>(); string current = DomainName; queue.Enqueue(current); while (queue.Count > 0) { current = queue.Dequeue(); enumerated.Add(current); options.WriteVerbose($"Enumerating {current}"); DirectorySearcher searcher = helpers.GetDomainSearcher(current); if (searcher == null) { continue; } searcher.Filter = "(userAccountControl:1.2.840.113556.1.4.803:=8192)"; string server; try { SearchResult dc = searcher.FindOne(); server = dc.GetProp("dnshostname"); } catch { options.WriteVerbose($"Unable to get Domain Controller for {DomainName}"); continue; } searcher.Dispose(); IntPtr ptr = IntPtr.Zero; uint types = 63; Type DDT = typeof(DS_DOMAIN_TRUSTS); uint result = DsEnumerateDomainTrusts(server, types, out ptr, out uint domaincount); int error = Marshal.GetLastWin32Error(); if (result == 0) { DS_DOMAIN_TRUSTS[] array = new DS_DOMAIN_TRUSTS[domaincount]; IntPtr iter = ptr; for (int i = 0; i < domaincount; i++) { DS_DOMAIN_TRUSTS t = (DS_DOMAIN_TRUSTS)Marshal.PtrToStructure(iter, DDT); array[i] = t; iter = (IntPtr)(iter.ToInt64() + Marshal.SizeOf(DDT)); } for (int i = 0; i < domaincount; i++) { DomainTrust trust = new DomainTrust() { SourceDomain = current }; DS_DOMAIN_TRUSTS t = array[i]; TRUST_TYPE trust_type = (TRUST_TYPE)t.Flags; TRUST_ATTRIB trust_attrib = (TRUST_ATTRIB)t.TrustAttributes; if ((trust_type & TRUST_TYPE.DS_DOMAIN_TREE_ROOT) == TRUST_TYPE.DS_DOMAIN_TREE_ROOT) { continue; } trust.TargetDomain = t.DnsDomainName; bool inbound = false; bool outbound = false; inbound = (trust_type & TRUST_TYPE.DS_DOMAIN_DIRECT_INBOUND) == TRUST_TYPE.DS_DOMAIN_DIRECT_INBOUND; outbound = (trust_type & TRUST_TYPE.DS_DOMAIN_DIRECT_OUTBOUND) == TRUST_TYPE.DS_DOMAIN_DIRECT_OUTBOUND; if (inbound && outbound) { trust.TrustDirection = "Bidirectional"; } else if (inbound) { trust.TrustDirection = "Inbound"; } else { trust.TrustDirection = "Outbound"; } if ((trust_type & TRUST_TYPE.DS_DOMAIN_IN_FOREST) == TRUST_TYPE.DS_DOMAIN_IN_FOREST) { trust.TrustType = "ParentChild"; } else { trust.TrustType = "External"; } trust.IsTransitive = !((trust_attrib & TRUST_ATTRIB.NON_TRANSITIVE) == TRUST_ATTRIB.NON_TRANSITIVE); output.Add(trust); if (!enumerated.Contains(t.DnsDomainName)) { queue.Enqueue(t.DnsDomainName); } } } } } } else { foreach (DomainDB d in db.GetDomains().FindAll()) { if (d.Trusts != null) { d.Trusts.ForEach(output.Add); } } } output.CompleteAdding(); writer.Wait(); Console.WriteLine("Finished Domain Trusts\n"); }