public static IEnumerable <Session> GetNetSessions(ResolvedEntry target, string computerDomain) { if (!Utils.IsMethodSet(ResolvedCollectionMethod.Session) && !Utils.IsMethodSet(ResolvedCollectionMethod.SessionLoop)) { yield break; } 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.BloodHoundDisplay, 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; Utils.Debug($"Result Username: {username}"); Utils.Debug($"Result cname: {cname}"); if (cname == null || username.EndsWith("$") || username.Trim() == "" || username == "$" || username == _options.CurrentUser) { continue; } if (cname.StartsWith("\\", StringComparison.CurrentCulture)) { cname = cname.TrimStart('\\'); } if (cname.Equals("[::1]") || cname.Equals("127.0.0.1")) { cname = target.BloodHoundDisplay; } var dnsHostName = _utils.ResolveHost(cname); Utils.Debug($"Result cname: {dnsHostName}"); if (dnsHostName == null) { continue; } //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, out var possible) || possible == null) { //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" }, computerDomain, "", true)) { temp.Add(Utils.ConvertDnToDomain(entry.DistinguishedName).ToUpper()); } possible = temp.ToArray(); _cache.AddGcMap(username, possible); } 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(); }