Пример #1
0
        /// <summary>
        /// Creates an instance of an RPCServer which is used for making SharpHound specific API calls for computers
        /// </summary>
        /// <param name="name">The name of the computer to connect too. This should be the network name of the computer</param>
        /// <param name="domain">The domain name of the computer</param>
        /// <param name="samAccountName">The samaccountname of the computer</param>
        /// <param name="computerSid">The security identifier for the computer</param>
        /// <exception cref="APIException">An exception if the an API fails to connect initially. Generally indicates the server is unavailable or permissions aren't available.</exception>
        internal RPCServer(string name, string domain, string samAccountName, string computerSid)
        {
            _computerDomain = domain;
            _computerSAN    = samAccountName;
            _computerSID    = computerSid;
            var sid      = new SecurityIdentifier("S-1-5-32");
            var sidBytes = new byte[sid.BinaryLength];

            sid.GetBinaryForm(sidBytes, 0);

            var us = new NativeMethods.UNICODE_STRING(name);
            //Every API call we make relies on both SamConnect and SamOpenDomain
            //Make these calls immediately and save the handles. If either fails, nothing else is going to work
            var status = SamConnect(ref us, out _serverHandle,
                                    SamAccessMasks.SamServerLookupDomain | SamAccessMasks.SamServerConnect, ref _obj);

            if (status != NativeMethods.NtStatus.StatusSuccess)
            {
                SamCloseHandle(_serverHandle);
                throw new APIException
                      {
                          Status  = status.ToString(),
                          APICall = "SamConnect"
                      };
            }

            status = SamOpenDomain(_serverHandle, DomainAccessMask.Lookup, sidBytes, out _domainHandle);
            if (status != NativeMethods.NtStatus.StatusSuccess)
            {
                throw new APIException
                      {
                          Status  = status.ToString(),
                          APICall = "SamOpenDomain"
                      };
            }
        }
Пример #2
0
 private static extern NativeMethods.NtStatus SamLookupDomainInSamServer(
     IntPtr serverHandle,
     ref NativeMethods.UNICODE_STRING name,
     out IntPtr sid);
Пример #3
0
 private static extern NativeMethods.NtStatus SamConnect(
     ref NativeMethods.UNICODE_STRING serverName,
     out IntPtr serverHandle,
     SamAccessMasks desiredAccess,
     ref NativeMethods.OBJECT_ATTRIBUTES objectAttributes
     );
Пример #4
0
        internal string GetMachineSid()
        {
            if (Cache.GetMachineSid(_computerSID, out var machineSid))
            {
                return(machineSid);
            }

            NativeMethods.NtStatus status;
            //Try the simplest method first, getting the SID directly using samaccountname
            try
            {
                var san = new NativeMethods.UNICODE_STRING(_computerSAN);
                status = SamLookupDomainInSamServer(_serverHandle, ref san, out var temp);
                if (status == NativeMethods.NtStatus.StatusSuccess)
                {
                    machineSid = new SecurityIdentifier(temp).Value;
                    SamFreeMemory(temp);
                    Cache.AddMachineSid(_computerSID, machineSid);
                    return(machineSid);
                }
            }
            catch
            {
                //pass
            }

            machineSid = "DUMMYSTRING";

            //As a fallback, try and retrieve the local administrators group and get the first account with a rid of 500
            //If at any time we encounter a failure, just return a dummy sid that wont match anything

            status = SamOpenAlias(_domainHandle, AliasOpenFlags.ListMembers,
                                  (int)LocalGroupRids.Administrators, out var aliasHandle);
            if (status != NativeMethods.NtStatus.StatusSuccess)
            {
                SamCloseHandle(aliasHandle);
                return(machineSid);
            }


            status = SamGetMembersInAlias(aliasHandle, out var members, out var count);
            if (status != NativeMethods.NtStatus.StatusSuccess)
            {
                SamCloseHandle(aliasHandle);
                return(machineSid);
            }

            SamCloseHandle(aliasHandle);

            if (count == 0)
            {
                SamFreeMemory(members);
                return(machineSid);
            }

            var sids = new List <string>();

            for (var i = 0; i < count; i++)
            {
                try
                {
                    var ptr = Marshal.ReadIntPtr(members, Marshal.SizeOf(typeof(IntPtr)) * i);
                    var sid = new SecurityIdentifier(ptr).Value;
                    sids.Add(sid);
                }
                catch (Exception e)
                {
                    Logging.Debug($"Exception converting sid: {e}");
                }
            }

            var domainSid = new SecurityIdentifier(_computerSID).AccountDomainSid.Value.ToUpper();

            machineSid = sids.Select(x =>
            {
                try
                {
                    return(new SecurityIdentifier(x).Value);
                }
                catch
                {
                    return(null);
                }
            }).Where(x => x != null).DefaultIfEmpty(null).FirstOrDefault(x => x.EndsWith("-500") && !x.ToUpper().StartsWith(domainSid));

            if (machineSid == null)
            {
                return("DUMMYSTRING");
            }

            machineSid = new SecurityIdentifier(machineSid).AccountDomainSid.Value;

            Cache.AddMachineSid(_computerSID, machineSid);
            return(machineSid);
        }