Example #1
0
    def __getLocalAdminSids(self):
        dce = self.__getDceBinding(self.__samrBinding)
        dce.connect()
        dce.bind(samr.MSRPC_UUID_SAMR)
        resp = samr.hSamrConnect(dce)
        serverHandle = resp['ServerHandle']

        resp = samr.hSamrLookupDomainInSamServer(dce, serverHandle, 'Builtin')
        resp = samr.hSamrOpenDomain(dce,
                                    serverHandle=serverHandle,
                                    domainId=resp['DomainId'])
        domainHandle = resp['DomainHandle']
        resp = samr.hSamrEnumerateAliasesInDomain(dce, domainHandle)
        aliases = {}
        for alias in resp['Buffer']['Buffer']:
            aliases[alias['Name']] = alias['RelativeId']
        resp = samr.hSamrOpenAlias(dce,
                                   domainHandle,
                                   desiredAccess=MAXIMUM_ALLOWED,
                                   aliasId=aliases['Administrators'])
        resp = samr.hSamrGetMembersInAlias(dce, resp['AliasHandle'])
        memberSids = []
        for member in resp['Members']['Sids']:
            memberSids.append(member['SidPointer'].formatCanonical())
        dce.disconnect()
        return memberSids
Example #2
0
 def getAliasMembers(self, domainHandle, aliasId):
     aliasHandle = self.getAliasHandle(domainHandle, aliasId)
     resp = samr.hSamrGetMembersInAlias(self.dce, aliasHandle)
     memberSids = []
     for member in resp['Members']['Sids']:
         memberSids.append(member['SidPointer'].formatCanonical())
     return memberSids
Example #3
0
    def __fetchAdminSidList(self, rpctransport):
        dce = rpctransport.get_dce_rpc()

        domain = None
        entries = []

        dce.connect()
        dce.bind(samr.MSRPC_UUID_SAMR)

        admin_sids = []

        try:
            resp = samr.hSamrConnect(dce)
            serverHandle = resp['ServerHandle']

            resp = samr.hSamrEnumerateDomainsInSamServer(dce, serverHandle)
            domains = resp['Buffer']['Buffer']

            domainNames = []
            for domain in domains:
                domainNames.append(domain['Name'])

            domain = "Builtin"

            resp = samr.hSamrLookupDomainInSamServer(dce, serverHandle, domain)

            resp = samr.hSamrOpenDomain(dce,
                                        serverHandle=serverHandle,
                                        domainId=resp['DomainId'])
            domainHandle = resp['DomainHandle']

            resp = samr.hSamrEnumerateAliasesInDomain(dce, domainHandle)

            for alias in resp['Buffer']['Buffer']:
                if alias['RelativeId'] == 544:
                    # Admin group
                    resp = samr.hSamrOpenAlias(dce,
                                               domainHandle,
                                               desiredAccess=MAXIMUM_ALLOWED,
                                               aliasId=alias['RelativeId'])

                    resp = samr.hSamrGetMembersInAlias(dce,
                                                       resp["AliasHandle"])
                    for member in resp["Members"]["Sids"]:
                        admin_sids.append(
                            member["SidPointer"].formatCanonical())

        except ListUsersException as e:
            print("Error listing group: %s" % e)

        dce.disconnect()

        return admin_sids
Example #4
0
    def rpc_get_local_admins(self):
        binding = r'ncacn_np:%s[\PIPE\samr]' % self.addr

        dce = self.dce_rpc_connect(binding, samr.MSRPC_UUID_SAMR)

        if dce is None:
            logging.warning('Connection failed: %s' % binding)
            return

        try:
            resp = samr.hSamrConnect(dce)
            serverHandle = resp['ServerHandle']

            resp = samr.hSamrEnumerateDomainsInSamServer(dce, serverHandle)
            domains = resp['Buffer']['Buffer']

            sid = RPC_SID()
            sid.fromCanonical('S-1-5-32')

            logging.debug('Opening domain handle')

            resp = samr.hSamrOpenDomain(dce,
                                        serverHandle=serverHandle,
                                        desiredAccess=samr.DOMAIN_LOOKUP | MAXIMUM_ALLOWED,
                                        domainId=sid)
            domainHandle = resp['DomainHandle']

            resp = samr.hSamrOpenAlias(dce,
                                       domainHandle,
                                       desiredAccess=samr.ALIAS_LIST_MEMBERS | MAXIMUM_ALLOWED,
                                       aliasId=544)

            resp = samr.hSamrGetMembersInAlias(dce,
                                               aliasHandle=resp['AliasHandle'])

            for member in resp['Members']['Sids']:
                sid_string = member['SidPointer'].formatCanonical()

                logging.debug('Found SID: %s' % sid_string)

                self.sids.append(sid_string)
        except DCERPCException as e:
            logging.debug('Exception connecting to RPC: %s', e)
        except Exception as e:
            if 'connection reset' in str(e):
                logging.debug('Connection was reset: %s', e)
            else:
                raise e

        dce.disconnect()
Example #5
0
    def __getLocalAdminSids(self):
        dce = self.__getDceBinding(self.__samrBinding)
        dce.connect()
        dce.bind(samr.MSRPC_UUID_SAMR)
        resp = samr.hSamrConnect(dce)
        serverHandle = resp['ServerHandle']

        resp = samr.hSamrLookupDomainInSamServer(dce, serverHandle, 'Builtin')
        resp = samr.hSamrOpenDomain(dce, serverHandle=serverHandle, domainId=resp['DomainId'])
        domainHandle = resp['DomainHandle']
        resp = samr.hSamrOpenAlias(dce, domainHandle, desiredAccess=MAXIMUM_ALLOWED, aliasId=544)
        resp = samr.hSamrGetMembersInAlias(dce, resp['AliasHandle'])
        memberSids = []
        for member in resp['Members']['Sids']:
            memberSids.append(member['SidPointer'].formatCanonical())
        dce.disconnect()
        return memberSids
    def rpc_get_local_admins(self):
        binding = r'ncacn_np:%s[\PIPE\samr]' % self.addr

        dce = self.dce_rpc_connect(binding, samr.MSRPC_UUID_SAMR)

        if dce is None:
            logging.warning('Connection failed: %s', binding)
            return

        try:
            resp = samr.hSamrConnect(dce)
            serverHandle = resp['ServerHandle']
            # Attempt to get the SID from this computer to filter local accounts later
            try:
                resp = samr.hSamrLookupDomainInSamServer(dce, serverHandle, self.samname[:-1])
                self.sid = resp['DomainId'].formatCanonical()
            # This doesn't always work (for example on DCs)
            except DCERPCException as e:
                # Make it a string which is guaranteed not to match a SID
                self.sid = 'UNKNOWN'


            # Enumerate the domains known to this computer
            resp = samr.hSamrEnumerateDomainsInSamServer(dce, serverHandle)
            domains = resp['Buffer']['Buffer']

            # Query the builtin domain (derived from this SID)
            sid = RPC_SID()
            sid.fromCanonical('S-1-5-32')

            logging.debug('Opening domain handle')
            # Open a handle to this domain
            resp = samr.hSamrOpenDomain(dce,
                                        serverHandle=serverHandle,
                                        desiredAccess=samr.DOMAIN_LOOKUP | MAXIMUM_ALLOWED,
                                        domainId=sid)
            domainHandle = resp['DomainHandle']

            resp = samr.hSamrOpenAlias(dce,
                                       domainHandle,
                                       desiredAccess=samr.ALIAS_LIST_MEMBERS | MAXIMUM_ALLOWED,
                                       aliasId=544)
            resp = samr.hSamrGetMembersInAlias(dce,
                                               aliasHandle=resp['AliasHandle'])
            for member in resp['Members']['Sids']:
                sid_string = member['SidPointer'].formatCanonical()

                logging.debug('Found admin SID: %s', sid_string)
                if not sid_string.startswith(self.sid):
                    # If the sid is known, we can add the admin value directly
                    try:
                        siddata = self.ad.sidcache.get(sid_string)
                        logging.debug('Sid is cached: %s', siddata['principal'])
                        self.admins.append({'Name': siddata['principal'],
                                            'Type': siddata['type'].capitalize()})
                    except KeyError:
                        # Append it to the list of unresolved SIDs
                        self.admin_sids.append(sid_string)
                else:
                    logging.debug('Ignoring local group %s', sid_string)
        except DCERPCException as e:
            logging.debug('Exception connecting to RPC: %s', e)
        except Exception as e:
            if 'connection reset' in str(e):
                logging.debug('Connection was reset: %s', e)
            else:
                raise e

        dce.disconnect()
Example #7
0
    def get_netlocalgroup(self,
                          queried_groupname=str(),
                          list_groups=False,
                          recurse=False):
        from impacket.nt_errors import STATUS_MORE_ENTRIES
        results = list()

        resp = samr.hSamrConnect(self._rpc_connection)
        server_handle = resp['ServerHandle']

        # We first list every domain in the SAM
        resp = samr.hSamrEnumerateDomainsInSamServer(self._rpc_connection,
                                                     server_handle)
        domains = resp['Buffer']['Buffer']
        domain_handles = dict()
        for local_domain in domains:
            resp = samr.hSamrLookupDomainInSamServer(self._rpc_connection,
                                                     server_handle,
                                                     local_domain['Name'])
            domain_sid = 'S-1-5-{}'.format('-'.join(
                str(x) for x in resp['DomainId']['SubAuthority']))
            resp = samr.hSamrOpenDomain(self._rpc_connection,
                                        serverHandle=server_handle,
                                        domainId=resp['DomainId'])
            domain_handles[domain_sid] = resp['DomainHandle']

        # If we list the groups
        if list_groups:
            # We browse every domain
            for domain_sid, domain_handle in domain_handles.items():
                # We enumerate local groups in every domain
                enumeration_context = 0
                groups = list()
                while True:
                    resp = samr.hSamrEnumerateAliasesInDomain(
                        self._rpc_connection,
                        domain_handle,
                        enumerationContext=enumeration_context)
                    groups += resp['Buffer']['Buffer']

                    enumeration_context = resp['EnumerationContext']
                    if resp['ErrorCode'] != STATUS_MORE_ENTRIES:
                        break

                # We get information on every group
                for group in groups:
                    resp = samr.hSamrRidToSid(self._rpc_connection,
                                              domain_handle,
                                              rid=group['RelativeId'])
                    sid = 'S-1-5-{}'.format('-'.join(
                        str(x) for x in resp['Sid']['SubAuthority']))

                    resp = samr.hSamrOpenAlias(self._rpc_connection,
                                               domain_handle,
                                               aliasId=group['RelativeId'])
                    alias_handle = resp['AliasHandle']
                    resp = samr.hSamrQueryInformationAlias(
                        self._rpc_connection, alias_handle)

                    final_group = rpcobj.Group(resp['Buffer']['General'])
                    final_group.add_attributes({
                        'server': self._target_computer,
                        'sid': sid
                    })

                    results.append(final_group)

                    samr.hSamrCloseHandle(self._rpc_connection, alias_handle)

                samr.hSamrCloseHandle(self._rpc_connection, domain_handle)
        # If we query a group
        else:
            queried_group_rid = None
            queried_group_domain_handle = None

            # If the user is looking for a particular group
            if queried_groupname:
                # We look for it in every domain
                for _, domain_handle in domain_handles.items():
                    try:
                        resp = samr.hSamrLookupNamesInDomain(
                            self._rpc_connection, domain_handle,
                            [queried_groupname])
                        queried_group_rid = resp['RelativeIds']['Element'][0][
                            'Data']
                        queried_group_domain_handle = domain_handle
                        break
                    except (DCERPCSessionError, KeyError, IndexError):
                        continue
                else:
                    raise ValueError(
                        'The group \'{}\' was not found on the target server'.
                        format(queried_groupname))
            # Otherwise, we look for the local Administrators group
            else:
                queried_group_rid = 544
                resp = samr.hSamrLookupDomainInSamServer(
                    self._rpc_connection, server_handle, 'BUILTIN')
                resp = samr.hSamrOpenDomain(self._rpc_connection,
                                            serverHandle=server_handle,
                                            domainId=resp['DomainId'])
                queried_group_domain_handle = resp['DomainHandle']

            # We get a handle on the group, and list its members
            try:
                group = samr.hSamrOpenAlias(self._rpc_connection,
                                            queried_group_domain_handle,
                                            aliasId=queried_group_rid)
                resp = samr.hSamrGetMembersInAlias(self._rpc_connection,
                                                   group['AliasHandle'])
            except DCERPCSessionError:
                raise ValueError(
                    'The name \'{}\' is not a valid group on the target server'
                    .format(queried_groupname))

            # For every user, we look for information in every local domain
            for member in resp['Members']['Sids']:
                attributes = dict()
                member_rid = member['SidPointer']['SubAuthority'][-1]
                member_sid = 'S-1-5-{}'.format('-'.join(
                    str(x) for x in member['SidPointer']['SubAuthority']))

                attributes['server'] = self._target_computer
                attributes['sid'] = member_sid

                for domain_sid, domain_handle in domain_handles.items():
                    # We've found a local member
                    if member_sid.startswith(domain_sid):
                        attributes['isdomain'] = False
                        resp = samr.hSamrQueryInformationDomain(
                            self._rpc_connection, domain_handle)
                        member_domain = resp['Buffer']['General2']['I1'][
                            'DomainName']
                        try:
                            resp = samr.hSamrOpenUser(self._rpc_connection,
                                                      domain_handle,
                                                      userId=member_rid)
                            member_handle = resp['UserHandle']
                            attributes['isgroup'] = False
                            resp = samr.hSamrQueryInformationUser(
                                self._rpc_connection, member_handle)
                            attributes['name'] = '{}/{}'.format(
                                member_domain,
                                resp['Buffer']['General']['UserName'])
                        except DCERPCSessionError:
                            resp = samr.hSamrOpenAlias(self._rpc_connection,
                                                       domain_handle,
                                                       aliasId=member_rid)
                            member_handle = resp['AliasHandle']
                            attributes['isgroup'] = True
                            resp = samr.hSamrQueryInformationAlias(
                                self._rpc_connection, member_handle)
                            attributes['name'] = '{}/{}'.format(
                                member_domain,
                                resp['Buffer']['General']['Name'])
                        attributes['lastlogin'] = str()
                        break
                # It's a domain member
                else:
                    attributes['isdomain'] = True
                    if self._ldap_connection is not None:
                        try:
                            ad_object = self.get_adobject(
                                queried_sid=member_sid)[0]
                            member_dn = ad_object.distinguishedname
                            member_domain = member_dn[member_dn.
                                                      index('DC='):].replace(
                                                          'DC=', '').replace(
                                                              ',', '.')
                            try:
                                attributes['name'] = '{}/{}'.format(
                                    member_domain, ad_object.samaccountname)
                            except AttributeError:
                                # Here, the member is a foreign security principal
                                # TODO: resolve it properly
                                attributes['name'] = '{}/{}'.format(
                                    member_domain, ad_object.objectsid)
                            attributes['isgroup'] = ad_object.isgroup
                            try:
                                attributes['lastlogin'] = ad_object.lastlogon
                            except AttributeError:
                                attributes['lastlogin'] = str()
                        except IndexError:
                            # We did not manage to resolve this SID against the DC
                            attributes['isdomain'] = False
                            attributes['isgroup'] = False
                            attributes['name'] = attributes['sid']
                            attributes['lastlogin'] = str()
                    else:
                        attributes['isgroup'] = False
                        attributes['name'] = str()
                        attributes['lastlogin'] = str()

                results.append(rpcobj.RPCObject(attributes))

                # If we recurse and the member is a domain group, we query every member
                # TODO: implement check on self._domain_controller here?
                if self._ldap_connection and self._domain_controller and recurse and attributes[
                        'isdomain'] and attributes['isgroup']:
                    for domain_member in self.get_netgroupmember(
                            full_data=True,
                            recurse=True,
                            queried_sid=attributes['sid']):
                        domain_member_attributes = dict()
                        domain_member_attributes['isdomain'] = True
                        member_dn = domain_member.distinguishedname
                        member_domain = member_dn[member_dn.
                                                  index('DC='):].replace(
                                                      'DC=',
                                                      '').replace(',', '.')
                        domain_member_attributes['name'] = '{}/{}'.format(
                            member_domain, domain_member.samaccountname)
                        domain_member_attributes[
                            'isgroup'] = domain_member.isgroup
                        domain_member_attributes['isdomain'] = True
                        domain_member_attributes['server'] = attributes['name']
                        domain_member_attributes[
                            'sid'] = domain_member.objectsid
                        try:
                            domain_member_attributes[
                                'lastlogin'] = ad_object.lastlogon
                        except AttributeError:
                            domain_member_attributes['lastlogin'] = str()
                        results.append(
                            rpcobj.RPCObject(domain_member_attributes))

        return results
Example #8
0
    def rpc_get_group_members(self, group_rid, resultlist):
        binding = r'ncacn_np:%s[\PIPE\samr]' % self.addr
        unresolved = []
        dce = self.dce_rpc_connect(binding, samr.MSRPC_UUID_SAMR)

        if dce is None:
            return

        try:
            resp = samr.hSamrConnect(dce)
            serverHandle = resp['ServerHandle']
            # Attempt to get the SID from this computer to filter local accounts later
            try:
                resp = samr.hSamrLookupDomainInSamServer(
                    dce, serverHandle, self.samname[:-1])
                self.sid = resp['DomainId'].formatCanonical()
            # This doesn't always work (for example on DCs)
            except DCERPCException as e:
                # Make it a string which is guaranteed not to match a SID
                self.sid = 'UNKNOWN'

            # Enumerate the domains known to this computer
            resp = samr.hSamrEnumerateDomainsInSamServer(dce, serverHandle)
            domains = resp['Buffer']['Buffer']

            # Query the builtin domain (derived from this SID)
            sid = RPC_SID()
            sid.fromCanonical('S-1-5-32')

            logging.debug('Opening domain handle')
            # Open a handle to this domain
            resp = samr.hSamrOpenDomain(dce,
                                        serverHandle=serverHandle,
                                        desiredAccess=samr.DOMAIN_LOOKUP
                                        | MAXIMUM_ALLOWED,
                                        domainId=sid)
            domainHandle = resp['DomainHandle']
            try:
                resp = samr.hSamrOpenAlias(
                    dce,
                    domainHandle,
                    desiredAccess=samr.ALIAS_LIST_MEMBERS | MAXIMUM_ALLOWED,
                    aliasId=group_rid)
            except samr.DCERPCSessionError as error:
                # Group does not exist
                if 'STATUS_NO_SUCH_ALIAS' in str(error):
                    logging.debug('No group with RID %d exists', group_rid)
                    return
            resp = samr.hSamrGetMembersInAlias(dce,
                                               aliasHandle=resp['AliasHandle'])
            for member in resp['Members']['Sids']:
                sid_string = member['SidPointer'].formatCanonical()

                logging.debug('Found %d SID: %s', group_rid, sid_string)
                if not sid_string.startswith(self.sid):
                    # If the sid is known, we can add the admin value directly
                    try:
                        siddata = self.ad.sidcache.get(sid_string)
                        if siddata is None:
                            unresolved.append(sid_string)
                        else:
                            logging.debug('Sid is cached: %s',
                                          siddata['principal'])
                            resultlist.append({
                                'ObjectIdentifier':
                                sid_string,
                                'ObjectType':
                                siddata['type'].capitalize()
                            })
                    except KeyError:
                        # Append it to the list of unresolved SIDs
                        unresolved.append(sid_string)
                else:
                    logging.debug('Ignoring local group %s', sid_string)
        except DCERPCException as e:
            if 'rpc_s_access_denied' in str(e):
                logging.debug(
                    'Access denied while enumerating groups on %s, likely a patched OS',
                    self.hostname)
            else:
                raise
        except Exception as e:
            if 'connection reset' in str(e):
                logging.debug('Connection was reset: %s', e)
            else:
                raise e

        dce.disconnect()
        return unresolved
Example #9
0
    def get_netlocalgroup(self, queried_groupname=str(), list_groups=False,
                          recurse=False):
        from impacket.nt_errors import STATUS_MORE_ENTRIES
        results = list()

        resp = samr.hSamrConnect(self._rpc_connection)
        server_handle = resp['ServerHandle']

        # We first list every domain in the SAM
        resp = samr.hSamrEnumerateDomainsInSamServer(self._rpc_connection, server_handle)
        domains = resp['Buffer']['Buffer']
        domain_handles = dict()
        for local_domain in domains:
            resp = samr.hSamrLookupDomainInSamServer(self._rpc_connection, server_handle, local_domain['Name'])
            domain_sid = 'S-1-5-{}'.format('-'.join(str(x) for x in resp['DomainId']['SubAuthority']))
            resp = samr.hSamrOpenDomain(self._rpc_connection, serverHandle=server_handle, domainId=resp['DomainId'])
            domain_handles[domain_sid] = resp['DomainHandle']

        # If we list the groups
        if list_groups:
            # We browse every domain
            for domain_sid, domain_handle in domain_handles.items():
                # We enumerate local groups in every domain
                enumeration_context = 0
                groups = list()
                while True:
                    resp = samr.hSamrEnumerateAliasesInDomain(self._rpc_connection, domain_handle,
                            enumerationContext=enumeration_context)
                    groups += resp['Buffer']['Buffer']

                    enumeration_context = resp['EnumerationContext']
                    if resp['ErrorCode'] != STATUS_MORE_ENTRIES:
                        break

                # We get information on every group
                for group in groups:
                    resp = samr.hSamrRidToSid(self._rpc_connection, domain_handle, rid=group['RelativeId'])
                    sid = 'S-1-5-{}'.format('-'.join(str(x) for x in resp['Sid']['SubAuthority']))

                    resp = samr.hSamrOpenAlias(self._rpc_connection, domain_handle, aliasId=group['RelativeId'])
                    alias_handle = resp['AliasHandle']
                    resp = samr.hSamrQueryInformationAlias(self._rpc_connection, alias_handle)

                    final_group = rpcobj.Group(resp['Buffer']['General'])
                    final_group.add_attributes({'server': self._target_computer, 'sid': sid})

                    results.append(final_group)

                    samr.hSamrCloseHandle(self._rpc_connection, alias_handle)

                samr.hSamrCloseHandle(self._rpc_connection, domain_handle)
        # If we query a group
        else:
            queried_group_rid = None
            queried_group_domain_handle = None

            # If the user is looking for a particular group
            if queried_groupname:
                # We look for it in every domain
                for _, domain_handle in domain_handles.items():
                    try:
                        resp = samr.hSamrLookupNamesInDomain(self._rpc_connection, domain_handle, [queried_groupname])
                        queried_group_rid = resp['RelativeIds']['Element'][0]['Data']
                        queried_group_domain_handle = domain_handle
                        break
                    except (DCERPCSessionError, KeyError, IndexError):
                        continue
                else:
                    raise ValueError('The group \'{}\' was not found on the target server'.format(queried_groupname))
            # Otherwise, we look for the local Administrators group
            else:
                queried_group_rid = 544
                resp = samr.hSamrLookupDomainInSamServer(self._rpc_connection, server_handle, 'BUILTIN')
                resp = samr.hSamrOpenDomain(self._rpc_connection, serverHandle=server_handle, domainId=resp['DomainId'])
                queried_group_domain_handle = resp['DomainHandle']

            # We get a handle on the group, and list its members
            try:
                group = samr.hSamrOpenAlias(self._rpc_connection, queried_group_domain_handle, aliasId=queried_group_rid)
                resp = samr.hSamrGetMembersInAlias(self._rpc_connection, group['AliasHandle'])
            except DCERPCSessionError:
                raise ValueError('The name \'{}\' is not a valid group on the target server'.format(queried_groupname))

            # For every user, we look for information in every local domain
            for member in resp['Members']['Sids']:
                attributes = dict()
                member_rid = member['SidPointer']['SubAuthority'][-1]
                member_sid = 'S-1-5-{}'.format('-'.join(str(x) for x in member['SidPointer']['SubAuthority']))

                attributes['server'] = self._target_computer
                attributes['sid'] = member_sid

                for domain_sid, domain_handle in domain_handles.items():
                    # We've found a local member
                    if member_sid.startswith(domain_sid):
                        attributes['isdomain'] = False
                        resp = samr.hSamrQueryInformationDomain(self._rpc_connection, domain_handle)
                        member_domain = resp['Buffer']['General2']['I1']['DomainName']
                        try:
                            resp = samr.hSamrOpenUser(self._rpc_connection, domain_handle, userId=member_rid)
                            member_handle = resp['UserHandle']
                            attributes['isgroup'] = False
                            resp = samr.hSamrQueryInformationUser(self._rpc_connection, member_handle)
                            attributes['name'] = '{}/{}'.format(member_domain, resp['Buffer']['General']['UserName'])
                        except DCERPCSessionError:
                            resp = samr.hSamrOpenAlias(self._rpc_connection, domain_handle, aliasId=member_rid)
                            member_handle = resp['AliasHandle']
                            attributes['isgroup'] = True
                            resp = samr.hSamrQueryInformationAlias(self._rpc_connection, member_handle)
                            attributes['name'] = '{}/{}'.format(member_domain, resp['Buffer']['General']['Name'])
                        attributes['lastlogin'] = str()
                        break
                # It's a domain member
                else:
                    attributes['isdomain'] = True
                    if self._ldap_connection is not None:
                        try:
                            ad_object = self.get_adobject(queried_sid=member_sid)[0]
                            member_dn = ad_object.distinguishedname
                            member_domain = member_dn[member_dn.index('DC='):].replace('DC=', '').replace(',', '.')
                            try:
                                attributes['name'] = '{}/{}'.format(member_domain, ad_object.samaccountname)
                            except AttributeError:
                                # Here, the member is a foreign security principal
                                # TODO: resolve it properly
                                attributes['name'] = '{}/{}'.format(member_domain, ad_object.objectsid)
                            attributes['isgroup'] = ad_object.isgroup
                            try:
                                attributes['lastlogin'] = ad_object.lastlogon
                            except AttributeError:
                                attributes['lastlogin'] = str()
                        except IndexError:
                            # We did not manage to resolve this SID against the DC
                            attributes['isdomain'] = False
                            attributes['isgroup'] = False
                            attributes['name'] = attributes['sid']
                            attributes['lastlogin'] = str()
                    else:
                        attributes['isgroup'] = False
                        attributes['name'] = str()
                        attributes['lastlogin'] = str()

                results.append(rpcobj.RPCObject(attributes))

                # If we recurse and the member is a domain group, we query every member
                # TODO: implement check on self._domain_controller here?
                if self._ldap_connection and self._domain_controller and recurse and attributes['isdomain'] and attributes['isgroup']:
                    for domain_member in self.get_netgroupmember(full_data=True, recurse=True, queried_sid=attributes['sid']):
                        domain_member_attributes = dict()
                        domain_member_attributes['isdomain'] = True
                        member_dn = domain_member.distinguishedname
                        member_domain = member_dn[member_dn.index('DC='):].replace('DC=', '').replace(',', '.')
                        domain_member_attributes['name'] = '{}/{}'.format(member_domain, domain_member.samaccountname)
                        domain_member_attributes['isgroup'] = domain_member.isgroup
                        domain_member_attributes['isdomain'] = True
                        domain_member_attributes['server'] = attributes['name']
                        domain_member_attributes['sid'] = domain_member.objectsid
                        try:
                            domain_member_attributes['lastlogin'] = ad_object.lastlogon
                        except AttributeError:
                            domain_member_attributes['lastlogin'] = str()
                        results.append(rpcobj.RPCObject(domain_member_attributes))

        return results