Example #1
0
        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();
        }
Example #2
0
        private void fill_netserver_page()
        {
            try
            {
                SERVER_INFO_102 serv_info = WinApiNETwrapper.GetServerInfo_102(resource_intern.lpRemoteName);
                textBoxNetserverPlatformId.Text      = serv_info.sv102_platform_id.ToString();
                textBoxNetserverSoftwareType.Text    = IOhelper.NetserverTypeToString(serv_info.sv102_type);
                textBoxPlatformVersion.Text          = string.Format("{0}.{1}", serv_info.GetVersionMajor(), serv_info.sv102_version_minor);
                textBoxNetserverMaxUsers.Text        = serv_info.sv102_users.ToString();
                textBoxNetserverDisconnectTime.Text  = serv_info.sv102_disc.ToString();
                textBoxNetserverAnnounceTime.Text    = serv_info.sv102_announce.ToString();
                textBoxNetserverUsersPerLicense.Text = serv_info.sv102_licenses.ToString();
                textBoxNetserverUserPath.Text        = serv_info.sv102_userpath;
            }
            catch (Exception ex)
            {
                errorProvider1.SetIconAlignment(textBoxNetserverPlatformId, ErrorIconAlignment.MiddleLeft);
                errorProvider1.SetError(textBoxNetserverPlatformId, ex.Message);
            }

            try
            {
                NetRemoteComputerSupportsFeatures features = WinApiNETwrapper.GetComputerSupports(resource_intern.lpRemoteName);
                textBoxNetserverFeatures.Text = features.ToString();
            }
            catch (Exception ex)
            {
                errorProvider1.SetIconAlignment(textBoxNetserverFeatures, ErrorIconAlignment.MiddleLeft);
                errorProvider1.SetError(textBoxNetserverFeatures, ex.Message);
            }

            try
            {
                TIME_OF_DAY_INFO dt = WinApiNETwrapper.GetServerTime(resource_intern.lpRemoteName);
                textBoxNetserverDatetime.Text = string.Format("{0} {1},{2}", dt.GetCurrentDatetime().ToLongDateString(), dt.GetCurrentDatetime().ToLongTimeString(), dt.GetCurrentDatetime().Millisecond);
                textBoxNetserverUptime.Text   = dt.GetUptime().ToString();
            }
            catch (Exception ex)
            {
                errorProvider1.SetIconAlignment(textBoxNetserverDatetime, ErrorIconAlignment.MiddleLeft);
                errorProvider1.SetError(textBoxNetserverDatetime, ex.Message);
            }

            //NET_DISPLAY_GROUP[] groups = WinApiNETwrapper.QueryDisplayInfoGroup(resource_intern.lpRemoteName);
            //NET_DISPLAY_MACHINE[] machines = WinApiNETwrapper.QueryDisplayInfoMachine(resource_intern.lpRemoteName);
            //NET_DISPLAY_USER[] users = WinApiNETwrapper.QueryDisplayInfoUser(resource_intern.lpRemoteName);

            try
            {
                SERVER_TRANSPORT_INFO_1[] transports = WinApiNETwrapper.ServerTransportEnum_1(resource_intern.lpRemoteName);
                for (int i = 0; i < transports.Length; i++)
                {
                    ListViewItem lvi = new ListViewItem();
                    lvi.Text = transports[i].svti1_transportname;
                    lvi.SubItems.Add(transports[i].TransportAddress);
                    lvi.SubItems.Add(transports[i].svti1_networkaddress);
                    lvi.SubItems.Add(transports[i].svti1_domain);
                    lvi.SubItems.Add(transports[i].svti1_numberofvcs.ToString());
                    listViewTransports.Items.Add(lvi);
                }
                listViewTransports.Dock = DockStyle.Fill;
            }
            catch (Exception ex)
            {
                errorProvider1.SetIconAlignment(listViewTransports, ErrorIconAlignment.MiddleLeft);
                errorProvider1.SetError(listViewTransports, ex.Message);
            }

            /* net sessions */
            errorProvider1.SetIconAlignment(listViewSessions, ErrorIconAlignment.MiddleLeft);
            Array sessions = null;
            NetSessionEnumLevel session_level = NetSessionEnumLevel.INFO_502;

            try
            {
                //try level 502
                sessions = WinApiNETwrapper.NetSessionEnum(resource_intern.lpRemoteName, null, null, session_level);
            }
            catch (Exception)
            {
                //if exception try level 10
                session_level = NetSessionEnumLevel.INFO_10;
                try
                {
                    sessions = WinApiNETwrapper.NetSessionEnum(resource_intern.lpRemoteName, null, null, session_level);
                }
                catch (Exception ex_10)
                {
                    errorProvider1.SetError(listViewSessions, ex_10.Message);
                }
            }
            if (sessions != null)
            {
                listViewSessions.Dock = DockStyle.Fill;
                for (int i = 0; i < sessions.Length; i++)
                {
                    ListViewItem lvi = new ListViewItem();
                    switch (session_level)
                    {
                    case NetSessionEnumLevel.INFO_502:
                        SESSION_INFO_502 info_502 = (SESSION_INFO_502)sessions.GetValue(i);
                        lvi.Text = info_502.sesi502_cname;
                        lvi.SubItems.Add(info_502.sesi502_username);
                        lvi.SubItems.Add(info_502.sesi502_num_opens.ToString());
                        lvi.SubItems.Add(info_502.TimeActive.ToString());
                        lvi.SubItems.Add(info_502.TimeIdle.ToString());
                        lvi.SubItems.Add(info_502.sesi502_user_flags.ToString());
                        lvi.SubItems.Add(info_502.sesi502_cltype_name);
                        lvi.SubItems.Add(info_502.sesi502_transport);
                        break;

                    case NetSessionEnumLevel.INFO_10:
                        SESSION_INFO_10 info_10 = (SESSION_INFO_10)sessions.GetValue(i);
                        lvi.Text = info_10.sesi10_cname;
                        lvi.SubItems.Add(string.Empty);
                        lvi.SubItems.Add(string.Empty);
                        lvi.SubItems.Add(info_10.TimeActive.ToString());
                        lvi.SubItems.Add(info_10.TimeIdle.ToString());
                        lvi.SubItems.Add(string.Empty);
                        lvi.SubItems.Add(string.Empty);
                        lvi.SubItems.Add(string.Empty);
                        break;
                    }
                    listViewSessions.Items.Add(lvi);
                }
            }
            /* end of net sessions */

            /* open files */
            try
            {
                Array files = WinApiNETwrapper.NetFileEnum(resource_intern.lpRemoteName, null, null, NetFileEnumLevel.INFO_3);
                listViewFiles.Dock = DockStyle.Fill;
                for (int i = 0; i < files.Length; i++)
                {
                    FILE_INFO_3  f_info = (FILE_INFO_3)files.GetValue(i);
                    ListViewItem lvi    = new ListViewItem();
                    lvi.Text = string.Format("0x{0:X}", f_info.fi3_id);
                    lvi.SubItems.Add(f_info.fi3_permission.ToString());
                    lvi.SubItems.Add(f_info.fi3_num_locks.ToString());
                    lvi.SubItems.Add(f_info.fi3_pathname);
                    lvi.SubItems.Add(f_info.fi3_username);
                    listViewFiles.Items.Add(lvi);
                }
            }
            catch (Exception ex_files)
            {
                errorProvider1.SetIconAlignment(listViewFiles, ErrorIconAlignment.MiddleLeft);
                errorProvider1.SetError(listViewFiles, ex_files.Message);
            }
            /* end of open files */
        }
Example #3
0
        public static IEnumerable <Session> GetNetSessions(ResolvedEntry target, string computerDomain)
        {
            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 int _, ref resumeHandle));

            var success = t.Wait(Timeout);

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

            var returnValue = t.Result;

            //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)
                {
                    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);

                //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 string[] possible) || possible == null)
Example #4
0
        /// <summary>
        /// Wraps the NetSessionEnum API call with a timeout and parses the
        /// </summary>
        /// <param name="computer"></param>
        /// <returns></returns>
        private static async Task <List <Session> > GetNetSessions(Computer computer)
        {
            var resumeHandle    = IntPtr.Zero;
            var sessionInfoType = typeof(SESSION_INFO_10);

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

            var sessionList = new List <Session>();

            try
            {
                var task = Task.Run(() => NetSessionEnum(computer.APIName, null, null, 10,
                                                         out ptrInfo, -1, out entriesRead, out _, ref resumeHandle));

                if (await Task.WhenAny(task, Task.Delay(10000)) != task)
                {
                    if (Options.Instance.DumpComputerStatus)
                    {
                        OutputTasks.AddComputerStatus(new ComputerStatus
                        {
                            ComputerName = computer.DisplayName,
                            Status       = "Timeout",
                            Task         = "NetSessionEnum"
                        });
                    }
                    return(sessionList);
                }

                var taskResult = task.Result;

                if (taskResult != 0)
                {
                    if (Options.Instance.DumpComputerStatus)
                    {
                        OutputTasks.AddComputerStatus(new ComputerStatus
                        {
                            ComputerName = computer.DisplayName,
                            Status       = ((NetApiStatus)taskResult).ToString(),
                            Task         = "NetSessionEnum"
                        });
                    }
                    return(sessionList);
                }


                var sessions = new SESSION_INFO_10[entriesRead];
                var iterator = ptrInfo;

                for (var i = 0; i < entriesRead; i++)
                {
                    sessions[i] = (SESSION_INFO_10)Marshal.PtrToStructure(iterator, sessionInfoType);
                    iterator    = (IntPtr)(iterator.ToInt64() + Marshal.SizeOf(sessionInfoType));
                }

                if (Options.Instance.DumpComputerStatus)
                {
                    OutputTasks.AddComputerStatus(new ComputerStatus
                    {
                        ComputerName = computer.DisplayName,
                        Status       = "Success",
                        Task         = "NetSessionEnum"
                    });
                }

                foreach (var session in sessions)
                {
                    var sessionUsername = session.sesi10_username;
                    var computerName    = session.sesi10_cname;

                    if (computerName == null)
                    {
                        continue;
                    }

                    string computerSid = null;

                    //Filter out computer accounts, Anonymous Logon, empty users
                    if (sessionUsername.EndsWith(
                            "$") || sessionUsername.Trim() == "" || sessionUsername == "$" || sessionUsername ==
                        Options.Instance.CurrentUserName || sessionUsername == "ANONYMOUS LOGON")
                    {
                        continue;
                    }

                    //Remove leading backslashes
                    if (computerName.StartsWith("\\"))
                    {
                        computerName = computerName.TrimStart('\\');
                    }

                    //If the session is pointing to localhost, we already know what the SID of the computer is
                    if (computerName.Equals("[::1]") || computerName.Equals("127.0.0.1"))
                    {
                        computerSid = computer.ObjectIdentifier;
                    }

                    //Try converting the computer name to a SID
                    computerSid = computerSid ?? await Helpers.TryResolveHostToSid(computerName, computer.Domain);

                    //Try converting the username to a SID
                    var searcher = Helpers.GetDirectorySearcher(computer.Domain);
                    var sids     = await searcher.LookupUserInGC(sessionUsername);

                    if (sids.Length > 0)
                    {
                        foreach (var sid in sids)
                        {
                            sessionList.Add(new Session
                            {
                                ComputerId = computerSid,
                                UserId     = sid
                            });
                        }
                    }
                    else
                    {
                        var(sidSuccess, userSid) =
                            await Helpers.AccountNameToSid(sessionUsername, computer.Domain, false);

                        if (sidSuccess)
                        {
                            sessionList.Add(new Session
                            {
                                ComputerId = computerSid,
                                UserId     = userSid
                            });
                        }
                        else
                        {
                            sessionList.Add(new Session
                            {
                                ComputerId = computerSid,
                                UserId     = sessionUsername
                            });
                        }
                    }
                }

                return(sessionList);
            }
            finally
            {
                if (ptrInfo != IntPtr.Zero)
                {
                    NetApiBufferFree(ptrInfo);
                }
            }
        }
Example #5
0
        List <SessionInfo> GetNetSessions(string server, string ComputerDomain)
        {
            List <SessionInfo> toReturn = new List <SessionInfo>();
            IntPtr             PtrInfo  = IntPtr.Zero;
            int    val;
            IntPtr ResumeHandle = IntPtr.Zero;

            Type si10 = typeof(SESSION_INFO_10);

            val = NetSessionEnum(server, null, null, 10, out PtrInfo, -1, out int EntriesRead, out int TotalRead, ref ResumeHandle);

            SESSION_INFO_10[] results = new SESSION_INFO_10[EntriesRead];

            if (val == (int)NERR.NERR_Success)
            {
                IntPtr iter = PtrInfo;
                for (int i = 0; i < EntriesRead; i++)
                {
                    results[i] = (SESSION_INFO_10)Marshal.PtrToStructure(iter, si10);
                    iter       = (IntPtr)(iter.ToInt64() + Marshal.SizeOf(si10));
                }
            }

            NetApiBufferFree(PtrInfo);

            foreach (SESSION_INFO_10 x in results)
            {
                string username = x.sesi10_username;
                string cname    = x.sesi10_cname;

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

                if (cname.Equals("[::1]"))
                {
                    cname = server;
                }

                if (cname.Equals("127.0.0.1"))
                {
                    cname = server;
                }

                if (username.EndsWith("$", StringComparison.CurrentCulture))
                {
                    continue;
                }

                if (username.Trim() == "" || username == "$" || username == CurrentUser)
                {
                    continue;
                }

                if (!ResolveCache.TryGetValue(cname, out string DNSHostName))
                {
                    try
                    {
                        DNSHostName = Dns.GetHostEntry(cname).HostName;
                        ResolveCache.TryAdd(cname, DNSHostName);
                    }
                    catch
                    {
                        DNSHostName = cname;
                    }
                }

                GlobalCatalogMap obj;
                if (options.SkipGCDeconfliction)
                {
                    obj = new GlobalCatalogMap
                    {
                        Username      = username,
                        PossibleNames = new List <string>()
                    };
                }
                else
                {
                    if (!manager.GetGCMap(username, out obj))
                    {
                        DirectorySearcher GCSearcher = helpers.GetDomainSearcher(ADSPath: GCPath);
                        GCSearcher.Filter = $"(&(samAccountType=805306368)(samaccountname={username}))";
                        GCSearcher.PropertiesToLoad.AddRange(new string[] { "distinguishedname" });
                        List <string> possible = new List <string>();
                        foreach (SearchResult r in GCSearcher.FindAll())
                        {
                            string dn     = r.GetProp("distinguishedname");
                            string domain = Helpers.DomainFromDN(dn);
                            possible.Add(domain.ToUpper());
                        }
                        GCSearcher.Dispose();
                        obj = new GlobalCatalogMap
                        {
                            PossibleNames = possible,
                            Username      = username
                        };
                        manager.InsertGCObject(obj);
                    }
                }

                if (DNSHostName == null)
                {
                    DNSHostName = cname;
                }

                if (obj.PossibleNames.Count == 0)
                {
                    //We didn't find the object in the GC at all. Default to computer domain
                    toReturn.Add(new SessionInfo
                    {
                        ComputerName = DNSHostName,
                        UserName     = $"{username}@{ComputerDomain}",
                        Weight       = 2
                    });
                }
                else if (obj.PossibleNames.Count == 1)
                {
                    //We found only one instance of the object
                    toReturn.Add(new SessionInfo
                    {
                        ComputerName = DNSHostName,
                        UserName     = $"{username}@{obj.PossibleNames.First()}",
                        Weight       = 1
                    });
                }
                else
                {
                    //Multiple possibilities. Add each one with a weight of 1 for the same domain as the computer
                    foreach (string p in obj.PossibleNames)
                    {
                        int weight;
                        if (p.ToUpper().Equals(ComputerDomain.ToUpper()))
                        {
                            weight = 1;
                        }
                        else
                        {
                            weight = 2;
                        }
                        toReturn.Add(new SessionInfo
                        {
                            ComputerName = DNSHostName,
                            UserName     = $"{username}@{p}",
                            Weight       = weight
                        });
                    }
                }
            }
            return(toReturn);
        }