internal static async Task <LdapWrapper> CheckSMBOpen(LdapWrapper wrapper)
        {
            //Only perform checks if this is a Computer object
            if (wrapper is Computer computer)
            {
                //Stealth targetting - we've already determined our stealth targets, so if its not a stealth target, return
                if (Options.Instance.Stealth && !computer.IsStealthTarget)
                {
                    return(wrapper);
                }

                if (Options.Instance.WindowsOnly)
                {
                    //If the WindowsOnly flag is set, check the operatingsystem attribute
                    var os = wrapper.SearchResult.GetProperty("operatingsystem");

                    //Perform a search for the term windows in the operatingsystem string
                    if (!(os?.IndexOf("windows", StringComparison.CurrentCultureIgnoreCase) > -1))
                    {
                        //If this isn't a windows computer, we'll mark is as such and we'll skip the following port scan since its not necessary
                        computer.IsWindows = false;

                        //Add a computer status message to note why we skipped this computer
                        OutputTasks.AddComputerStatus(new ComputerStatus
                        {
                            ComputerName = computer.DisplayName,
                            Status       = "NotWindows",
                            Task         = "SMBCheck"
                        });
                        return(wrapper);
                    }
                }

                //If we're skipping port scan, just return the wrapper. PingFailed is set to false by default
                if (Options.Instance.SkipPortScan)
                {
                    return(wrapper);
                }

                //Do a check on port 445 and save the result
                computer.PingFailed = Helpers.CheckPort(computer.APIName, 445) == false;
                if (computer.PingFailed && Options.Instance.DumpComputerStatus)
                {
                    //If the port check failed, add a computer status note
                    OutputTasks.AddComputerStatus(new ComputerStatus
                    {
                        ComputerName = computer.DisplayName,
                        Status       = "SMBNotAvailable",
                        Task         = "SMBCheck"
                    });
                }

                //Do jitter/delay if specified
                await Helpers.DoDelay();
            }

            return(wrapper);
        }
        private static IEnumerable <Session> GetLoggedOnUsersRegistry(Computer computer)
        {
            if (Options.Instance.NoRegistryLoggedOn)
            {
                yield break;
            }

            RegistryKey          key = null;
            IEnumerable <string> filteredKeys;

            try
            {
                //Try to open the remote base key
                key = RegistryKey.OpenRemoteBaseKey(RegistryHive.Users, computer.APIName);

                //Find subkeys where the regex matches
                filteredKeys = key.GetSubKeyNames().Where(subkey => SidRegex.IsMatch(subkey));
            }
            catch (Exception e)
            {
                if (Options.Instance.DumpComputerStatus)
                {
                    OutputTasks.AddComputerStatus(new ComputerStatus
                    {
                        ComputerName = computer.DisplayName,
                        Status       = e.Message,
                        Task         = "RegistryLoggedOn"
                    });
                }
                yield break;
            }
            finally
            {
                //Ensure we dispose of the registry key
                key?.Dispose();
            }

            foreach (var sid in filteredKeys)
            {
                yield return(new Session
                {
                    ComputerId = computer.ObjectIdentifier,
                    UserId = sid
                });
            }

            if (Options.Instance.DumpComputerStatus)
            {
                OutputTasks.AddComputerStatus(new ComputerStatus
                {
                    ComputerName = computer.DisplayName,
                    Status       = "Success",
                    Task         = "RegistryLoggedOn"
                });
            }
        }
        internal static async Task <LdapWrapper> CheckSMBOpen(LdapWrapper wrapper)
        {
            if (wrapper is Computer computer)
            {
                if (Options.Instance.Stealth && !computer.IsStealthTarget)
                {
                    return(wrapper);
                }
                computer.PingFailed = Helpers.CheckPort(computer.APIName, 445) == false;
                if (computer.PingFailed && Options.Instance.DumpComputerStatus)
                {
                    OutputTasks.AddComputerStatus(new ComputerStatus
                    {
                        ComputerName = computer.DisplayName,
                        Status       = "SMBNotAvailable",
                        Task         = "SMBCheck"
                    });
                }

                await Helpers.DoDelay();
            }

            return(wrapper);
        }
Exemple #4
0
        /// <summary>
        /// Wraps the GetNetLocalGroupMembers call with a timeout, and then processes the results into objects
        /// </summary>
        /// <param name="computer"></param>
        /// <param name="rid">The relative ID of the group we want to query</param>
        /// <returns></returns>
        private static async Task <List <GenericMember> > GetNetLocalGroupMembers(Computer computer, LocalGroupRids rid)
        {
            var sids            = new IntPtr[0];
            var groupMemberList = new List <GenericMember>();
            var task            = Task.Run(() => CallLocalGroupApi(computer, rid, out sids));

            //Run the API call along with a 10 second timeout
            if (await Task.WhenAny(task, Task.Delay(10000)) != task)
            {
                OutputTasks.AddComputerStatus(new ComputerStatus
                {
                    ComputerName = computer.DisplayName,
                    Status       = "Timeout",
                    Task         = $"GetNetLocalGroup-{rid}"
                });
                return(groupMemberList);
            }

            //Check the result of the task
            var taskResult = task.Result;

            if (!taskResult)
            {
                return(groupMemberList);
            }

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

            //Take our pointers to sids and convert them into string sids for matching
            var convertedSids = new List <string>();

            for (var i = 0; i < sids.Length; i++)
            {
                try
                {
                    var sid = new SecurityIdentifier(sids[i]).Value;
                    convertedSids.Add(sid);
                }
                catch
                {
                    //SID Resolution failed for some reason, so ignore it
                }
                finally
                {
                    //Set the IntPtr to zero, so we can GC those
                    sids[i] = IntPtr.Zero;
                }
            }
            //Null out sids, so garbage collection takes care of it
            sids = null;

            //Extract the domain SID from the computer's sid, to avoid creating more SecurityIdentifier objects
            var domainSid = computer.ObjectIdentifier.Substring(0, computer.ObjectIdentifier.LastIndexOf('-'));

            // The first account in our list should always be the default RID 500 for the machine, but we'll take some extra precautions
            var machineSid = convertedSids.DefaultIfEmpty("DUMMYSTRING").FirstOrDefault(x => x.EndsWith("-500") && !x.StartsWith(domainSid)) ?? "DUMMYSTRING";

            //If we found a machine sid, strip the ending bit off
            if (machineSid.StartsWith("S-1-5-21"))
            {
                machineSid = machineSid.Substring(0, machineSid.LastIndexOf('-'));
            }

            foreach (var sid in convertedSids)
            {
                //Filter out local accounts
                if (sid.StartsWith(machineSid))
                {
                    continue;
                }

                var(finalSid, type) = await ResolutionHelpers.ResolveSidAndGetType(sid, computer.Domain);

                //Filter out null sids, usually from deconflictions
                if (finalSid == null)
                {
                    continue;
                }

                groupMemberList.Add(new GenericMember
                {
                    MemberType = type,
                    MemberId   = finalSid
                });
            }

            return(groupMemberList);
        }
Exemple #5
0
        /// <summary>
        /// Modified version of GetNetLocalGroupMembers which eliminates several unnecessary LSA/SAMRPC calls
        /// </summary>
        /// <param name="computer"></param>
        /// <param name="rid"></param>
        /// <param name="sids"></param>
        /// <returns></returns>
        private static bool CallLocalGroupApi(Computer computer, LocalGroupRids rid, out IntPtr[] sids)
        {
            //Initialize pointers for later
            var serverHandle = IntPtr.Zero;
            var domainHandle = IntPtr.Zero;
            var aliasHandle  = IntPtr.Zero;
            var members      = IntPtr.Zero;

            sids = new IntPtr[0];

            //Create some objects required for SAMRPC calls
            var server           = new UNICODE_STRING(computer.APIName);
            var objectAttributes = new OBJECT_ATTRIBUTES();

            try
            {
                //Step 1: Call SamConnect to open a handle to the computer's SAM
                //0x1 = SamServerLookupDomain, 0x20 = SamServerConnect
                var status = SamConnect(ref server, out serverHandle, 0x1 | 0x20, ref objectAttributes);

                switch (status)
                {
                case NtStatus.StatusRpcServerUnavailable:
                    if (Options.Instance.DumpComputerStatus)
                    {
                        OutputTasks.AddComputerStatus(new ComputerStatus
                        {
                            ComputerName = computer.DisplayName,
                            Status       = status.ToString(),
                            Task         = $"GetNetLocalGroup-{rid}"
                        });
                    }

                    return(false);

                case NtStatus.StatusSuccess:
                    break;

                default:
                    if (Options.Instance.DumpComputerStatus)
                    {
                        OutputTasks.AddComputerStatus(new ComputerStatus
                        {
                            ComputerName = computer.DisplayName,
                            Status       = status.ToString(),
                            Task         = $"GetNetLocalGroup-{rid}"
                        });
                    }
                    return(false);
                }

                //Step 2 - Open the built in domain, which is identified by the SID S-1-5-32
                //0x200 = Lookup
                status = SamOpenDomain(serverHandle, 0x200, LocalSidBytes.Value, out domainHandle);

                if (status != NtStatus.StatusSuccess)
                {
                    if (Options.Instance.DumpComputerStatus)
                    {
                        OutputTasks.AddComputerStatus(new ComputerStatus
                        {
                            ComputerName = computer.DisplayName,
                            Status       = status.ToString(),
                            Task         = $"GetNetLocalGroup-{rid}"
                        });
                    }
                    return(false);
                }

                //Step 3 - Open the alias that corresponds to the group we want to enumerate.
                //0x4 = ListMembers
                status = SamOpenAlias(domainHandle, 0x4, (int)rid, out aliasHandle);

                if (status != NtStatus.StatusSuccess)
                {
                    if (Options.Instance.DumpComputerStatus)
                    {
                        OutputTasks.AddComputerStatus(new ComputerStatus
                        {
                            ComputerName = computer.DisplayName,
                            Status       = status.ToString(),
                            Task         = $"GetNetLocalGroup-{rid}"
                        });
                    }
                }

                //Step 4 - Get the members of the alias we opened in step 3.
                status = SamGetMembersInAlias(aliasHandle, out members, out var count);

                if (status != NtStatus.StatusSuccess)
                {
                    if (Options.Instance.DumpComputerStatus)
                    {
                        OutputTasks.AddComputerStatus(new ComputerStatus
                        {
                            ComputerName = computer.DisplayName,
                            Status       = status.ToString(),
                            Task         = $"GetNetLocalGroup-{rid}"
                        });
                    }
                    return(false);
                }

                //If we didn't get any objects, just return false
                if (count == 0)
                {
                    return(false);
                }

                //Copy the IntPtr to an array so we can loop over it
                sids = new IntPtr[count];
                Marshal.Copy(members, sids, 0, count);

                return(true);
            }
            finally
            {
                //Free memory from handles acquired during the process
                if (serverHandle != IntPtr.Zero)
                {
                    SamCloseHandle(serverHandle);
                }
                if (domainHandle != IntPtr.Zero)
                {
                    SamCloseHandle(domainHandle);
                }
                if (aliasHandle != IntPtr.Zero)
                {
                    SamCloseHandle(aliasHandle);
                }

                if (members != IntPtr.Zero)
                {
                    SamFreeMemory(members);
                }
            }
        }
        /// <summary>
        /// Wraps the NetWkstaUserEnum API call in a timeout
        /// </summary>
        /// <param name="computer"></param>
        /// <returns></returns>
        private static async Task <List <Session> > GetLoggedOnUsersAPI(Computer computer)
        {
            var resumeHandle        = 0;
            var workstationInfoType = typeof(WKSTA_USER_INFO_1);
            var ptrInfo             = IntPtr.Zero;
            var entriesRead         = 0;
            var sessionList         = new List <Session>();

            try
            {
                var task = Task.Run(() => NetWkstaUserEnum(computer.APIName, 1, 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         = "NetWkstaUserEnum"
                        });
                    }

                    return(sessionList);
                }

                var taskResult = task.Result;
                //Check the result of the task. 234 and 0 are both acceptable.
                if (taskResult != 0 && taskResult != 234)
                {
                    if (Options.Instance.DumpComputerStatus)
                    {
                        OutputTasks.AddComputerStatus(new ComputerStatus
                        {
                            ComputerName = computer.DisplayName,
                            Status       = ((NetApiStatus)taskResult).ToString(),
                            Task         = "NetWkstaUserEnum"
                        });
                    }
                    return(sessionList);
                }

                var iterator = ptrInfo;

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

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

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

                    //Remove local accounts
                    if (domain.Equals(computer.SamAccountName, StringComparison.CurrentCultureIgnoreCase))
                    {
                        continue;
                    }

                    //Remove blank accounts and computer accounts
                    if (username.Trim() == "" || username.EndsWith("$") || username == "ANONYMOUS LOGON" || username == Options.Instance.CurrentUserName)
                    {
                        continue;
                    }

                    //Any domain with a space is unusable (ex: NT AUTHORITY, FONT DRIVER HOST)
                    if (domain.Contains(" "))
                    {
                        continue;
                    }

                    var(rSuccess, sid, _) = await ResolutionHelpers.ResolveAccountNameToSidAndType(username, domain);

                    if (rSuccess)
                    {
                        sessionList.Add(new Session
                        {
                            UserId     = sid,
                            ComputerId = computer.ObjectIdentifier
                        });
                    }
                    else
                    {
                        sessionList.Add(new Session
                        {
                            UserId     = $"{username}@{Helpers.NormalizeDomainName(domain)}".ToUpper(),
                            ComputerId = computer.ObjectIdentifier
                        });
                    }
                }

                return(sessionList);
            }
            finally
            {
                if (ptrInfo != IntPtr.Zero)
                {
                    NetApiBufferFree(ptrInfo);
                }
            }
        }
Exemple #7
0
        /// <summary>
        /// Wraps the GetNetLocalGroupMembers call with a timeout, and then processes the results into objects
        /// </summary>
        /// <param name="computer"></param>
        /// <param name="rid">The relative ID of the group we want to query</param>
        /// <returns></returns>
        private static async Task <List <GenericMember> > GetNetLocalGroupMembers(Computer computer, LocalGroupRids rid)
        {
            var sids            = new IntPtr[0];
            var groupMemberList = new List <GenericMember>();
            var task            = Task.Run(() => CallLocalGroupApi(computer, rid, out sids));

            if (await Task.WhenAny(task, Task.Delay(10000)) != task)
            {
                OutputTasks.AddComputerStatus(new ComputerStatus
                {
                    ComputerName = computer.DisplayName,
                    Status       = "Timeout",
                    Task         = $"GetNetLocalGroup-{rid}"
                });
                return(groupMemberList);
            }

            var taskResult = task.Result;

            if (!taskResult)
            {
                return(groupMemberList);
            }

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

            //Take our pointers to sids and convert them into string sids for matching
            var convertedSids = new List <string>();

            for (var i = 0; i < sids.Length; i++)
            {
                try
                {
                    var sid = new SecurityIdentifier(sids[i]).Value;
                    convertedSids.Add(sid);
                }
                catch
                {
                    // ignored
                }
                finally
                {
                    //Set the IntPtr to zero, so we can GC those
                    sids[i] = IntPtr.Zero;
                }
            }
            //Null out sids, so garbage collection takes care of it
            sids = null;

            //Extract the domain SID from the computer's sid, to avoid creating more SecurityIdentifier objects
            var    domainSid = computer.ObjectIdentifier.Substring(0, computer.ObjectIdentifier.LastIndexOf('-'));
            string machineSid;

            // The first account in our list should always be the default RID 500 for the machine, but we'll take some extra precautions
            try
            {
                machineSid = convertedSids.First(x => x.EndsWith("-500") && !x.StartsWith(domainSid));
            }
            catch
            {
                machineSid = "DUMMYSTRING";
            }

            foreach (var sid in convertedSids)
            {
                if (sid.StartsWith(machineSid))
                {
                    continue;
                }

                LdapTypeEnum type;
                var          finalSid = sid;
                if (CommonPrincipal.GetCommonSid(finalSid, out var common))
                {
                    finalSid = Helpers.ConvertCommonSid(sid, null);
                    type     = common.Type;
                }
                else
                {
                    type = await Helpers.LookupSidType(sid);
                }

                groupMemberList.Add(new GenericMember
                {
                    MemberType = type,
                    MemberId   = finalSid
                });
            }

            return(groupMemberList);
        }
Exemple #8
0
        private static async Task <List <Session> > GetLoggedOnUsersRegistry(Computer computer)
        {
            var sessionList = new List <Session>();

            if (Options.Instance.NoRegistryLoggedOn)
            {
                return(sessionList);
            }

            RegistryKey key = null;

            try
            {
                //Try to open the remote base key
                var task = Task.Run(() => RegistryKey.OpenRemoteBaseKey(RegistryHive.Users, computer.APIName));
                if (await Task.WhenAny(task, Task.Delay(10000)) != task)
                {
                    if (Options.Instance.DumpComputerStatus)
                    {
                        OutputTasks.AddComputerStatus(new ComputerStatus
                        {
                            ComputerName = computer.DisplayName,
                            Status       = "Timeout",
                            Task         = "RegistryLoggedOn"
                        });
                    }

                    return(sessionList);
                }

                key = task.Result;

                //Find subkeys where the regex matches
                var filteredKeys = key.GetSubKeyNames().Where(subkey => SidRegex.IsMatch(subkey));

                foreach (var sid in filteredKeys)
                {
                    sessionList.Add(new Session
                    {
                        ComputerId = computer.ObjectIdentifier,
                        UserId     = sid
                    });
                }

                if (Options.Instance.DumpComputerStatus)
                {
                    OutputTasks.AddComputerStatus(new ComputerStatus
                    {
                        ComputerName = computer.DisplayName,
                        Status       = "Success",
                        Task         = "RegistryLoggedOn"
                    });
                }
                return(sessionList);
            }
            catch (Exception e)
            {
                if (Options.Instance.DumpComputerStatus)
                {
                    OutputTasks.AddComputerStatus(new ComputerStatus
                    {
                        ComputerName = computer.DisplayName,
                        Status       = e.Message,
                        Task         = "RegistryLoggedOn"
                    });
                }
                return(sessionList);
            }
            finally
            {
                //Ensure we dispose of the registry key
                key?.Dispose();
            }
        }
Exemple #9
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);
                }
            }
        }