Exemple #1
0
    def __bruteForce(self, rpctransport, maxRid):
        dce = rpctransport.get_dce_rpc()
        dce.connect()

        # Want encryption? Uncomment next line
        # But make SIMULTANEOUS variable <= 100
        # dce.set_auth_level(ntlm.NTLM_AUTH_PKT_PRIVACY)

        # Want fragmentation? Uncomment next line
        # dce.set_max_fragment_size(32)

        dce.bind(lsat.MSRPC_UUID_LSAT)
        resp = lsat.hLsarOpenPolicy2(dce, MAXIMUM_ALLOWED | lsat.POLICY_LOOKUP_NAMES)
        policyHandle = resp["PolicyHandle"]

        resp = lsad.hLsarQueryInformationPolicy2(
            dce, policyHandle, lsad.POLICY_INFORMATION_CLASS.PolicyAccountDomainInformation
        )

        domainSid = resp["PolicyInformation"]["PolicyAccountDomainInfo"]["DomainSid"].formatCanonical()

        soFar = 0
        SIMULTANEOUS = 1000
        for j in range(maxRid / SIMULTANEOUS + 1):
            if (maxRid - soFar) / SIMULTANEOUS == 0:
                sidsToCheck = (maxRid - soFar) % SIMULTANEOUS
            else:
                sidsToCheck = SIMULTANEOUS

            if sidsToCheck == 0:
                break

            sids = list()
            for i in xrange(soFar, soFar + sidsToCheck):
                sids.append(domainSid + "-%d" % i)
            try:
                lsat.hLsarLookupSids(dce, policyHandle, sids, lsat.LSAP_LOOKUP_LEVEL.LsapLookupWksta)
            except DCERPCException, e:
                if str(e).find("STATUS_NONE_MAPPED") >= 0:
                    soFar += SIMULTANEOUS
                    continue
                elif str(e).find("STATUS_SOME_NOT_MAPPED") >= 0:
                    resp = e.get_packet()
                else:
                    raise

            for n, item in enumerate(resp["TranslatedNames"]["Names"]):
                if item["Use"] != SID_NAME_USE.SidTypeUnknown:
                    self.__logger.highlight(
                        "%d: %s\\%s (%s)"
                        % (
                            soFar + n,
                            resp["ReferencedDomains"]["Domains"][item["DomainIndex"]]["Name"],
                            item["Name"],
                            SID_NAME_USE.enumItems(item["Use"]).name,
                        )
                    )
            soFar += SIMULTANEOUS
Exemple #2
0
    def __bruteForce(self, rpctransport, maxRid):
        dce = rpctransport.get_dce_rpc()
        entries = []
        dce.connect()

        # Want encryption? Uncomment next line
        # But make SIMULTANEOUS variable <= 100
        #dce.set_auth_level(ntlm.NTLM_AUTH_PKT_PRIVACY)

        # Want fragmentation? Uncomment next line
        #dce.set_max_fragment_size(32)

        dce.bind(lsat.MSRPC_UUID_LSAT)
        
        resp = lsat.hLsarOpenPolicy2(dce, MAXIMUM_ALLOWED | lsat.POLICY_LOOKUP_NAMES)
        policyHandle = resp['PolicyHandle']

        if self.__domain_sids: # get the Domain SID
            resp = lsad.hLsarQueryInformationPolicy2(dce, policyHandle, lsad.POLICY_INFORMATION_CLASS.PolicyPrimaryDomainInformation)
            domainSid =  resp['PolicyInformation']['PolicyPrimaryDomainInfo']['Sid'].formatCanonical()
        else: # Get the target host SID
            resp = lsad.hLsarQueryInformationPolicy2(dce, policyHandle, lsad.POLICY_INFORMATION_CLASS.PolicyAccountDomainInformation)
            domainSid = resp['PolicyInformation']['PolicyAccountDomainInfo']['DomainSid'].formatCanonical()

        logging.info('Domain SID is: %s' % domainSid)

        soFar = 0
        SIMULTANEOUS = 1000
        for j in range(maxRid/SIMULTANEOUS+1):
            if (maxRid - soFar) / SIMULTANEOUS == 0:
                sidsToCheck = (maxRid - soFar) % SIMULTANEOUS
            else: 
                sidsToCheck = SIMULTANEOUS
 
            if sidsToCheck == 0:
                break

            sids = list()
            for i in xrange(soFar, soFar+sidsToCheck):
                sids.append(domainSid + '-%d' % i)
            try:
                lsat.hLsarLookupSids(dce, policyHandle, sids,lsat.LSAP_LOOKUP_LEVEL.LsapLookupWksta)
            except DCERPCException, e:
                if str(e).find('STATUS_NONE_MAPPED') >= 0:
                    soFar += SIMULTANEOUS
                    continue
                elif str(e).find('STATUS_SOME_NOT_MAPPED') >= 0:
                    resp = e.get_packet()
                else: 
                    raise

            for n, item in enumerate(resp['TranslatedNames']['Names']):
                if item['Use'] != SID_NAME_USE.SidTypeUnknown:
                    print "%d: %s\\%s (%s)" % (
                    soFar + n, resp['ReferencedDomains']['Domains'][item['DomainIndex']]['Name'], item['Name'],
                    SID_NAME_USE.enumItems(item['Use']).name)
            soFar += SIMULTANEOUS
Exemple #3
0
 def __resolveSids(self, sids):
     dce = self.__getDceBinding(self.__lsaBinding)
     dce.connect()
     dce.bind(lsat.MSRPC_UUID_LSAT)
     resp = lsat.hLsarOpenPolicy2(dce, MAXIMUM_ALLOWED | lsat.POLICY_LOOKUP_NAMES)
     policyHandle = resp['PolicyHandle']
     resp = lsat.hLsarLookupSids(dce, policyHandle, sids, lsat.LSAP_LOOKUP_LEVEL.LsapLookupWksta)
     names = []
     for n, item in enumerate(resp['TranslatedNames']['Names']):
         names.append(u"{}\\{}".format(resp['ReferencedDomains']['Domains'][item['DomainIndex']]['Name'].encode('utf-16-le'), item['Name']))
     dce.disconnect()
     return names
Exemple #4
0
    def getForestSid(self):
        logging.debug('Calling NRPC DsrGetDcNameEx()')

        stringBinding = r'ncacn_np:%s[\pipe\netlogon]' % self.__kdcHost

        rpctransport = transport.DCERPCTransportFactory(stringBinding)

        if hasattr(rpctransport, 'set_credentials'):
            rpctransport.set_credentials(self.__username,self.__password, self.__domain, self.__lmhash, self.__nthash)

        dce = rpctransport.get_dce_rpc()
        dce.connect()
        dce.bind(MSRPC_UUID_NRPC)

        resp = hDsrGetDcNameEx(dce, NULL, NULL, NULL, NULL, 0)
        forestName = resp['DomainControllerInfo']['DnsForestName'][:-1]
        logging.debug('DNS Forest name is %s' % forestName)
        dce.disconnect()

        logging.debug('Calling LSAT hLsarQueryInformationPolicy2()')

        stringBinding = r'ncacn_np:%s[\pipe\lsarpc]' % forestName

        rpctransport = transport.DCERPCTransportFactory(stringBinding)

        if hasattr(rpctransport, 'set_credentials'):
            rpctransport.set_credentials(self.__username,self.__password, self.__domain, self.__lmhash, self.__nthash)

        dce = rpctransport.get_dce_rpc()
        dce.connect()
        dce.bind(MSRPC_UUID_LSAT)

        resp = hLsarOpenPolicy2(dce, MAXIMUM_ALLOWED | POLICY_LOOKUP_NAMES)
        policyHandle = resp['PolicyHandle']

        resp = hLsarQueryInformationPolicy2(dce, policyHandle, POLICY_INFORMATION_CLASS.PolicyAccountDomainInformation)
        dce.disconnect()

        forestSid = resp['PolicyInformation']['PolicyAccountDomainInfo']['DomainSid'].formatCanonical()
        logging.info("Forest SID: %s"% forestSid)

        return forestSid
Exemple #5
0
    def run(self):
        global getting_usernames
        global got_usernames
        if getting_usernames:
            return
        getting_usernames = True
        rpctransport = transport.SMBTransport(
            self.__SMBConnection.getRemoteHost(),
            filename=r'\lsarpc',
            smb_connection=self.__SMBConnection)
        dce = rpctransport.get_dce_rpc()
        maxRid = 50000
        dce.connect()

        dce.bind(lsat.MSRPC_UUID_LSAT)
        resp = lsat.hLsarOpenPolicy2(
            dce, MAXIMUM_ALLOWED | lsat.POLICY_LOOKUP_NAMES)
        policyHandle = resp['PolicyHandle']

        # Get Domain Sid if we are in a domain
        logging.info('Dumping usernames')
        resp = lsad.hLsarQueryInformationPolicy2(
            dce, policyHandle,
            lsad.POLICY_INFORMATION_CLASS.PolicyPrimaryDomainInformation)
        in_domain = True
        if resp['PolicyInformation']['PolicyPrimaryDomainInfo']['Sid']:
            domainSid = resp['PolicyInformation']['PolicyPrimaryDomainInfo'][
                'Sid'].formatCanonical()
        else:
            # If we get an exception, maybe we aren't in a domain. Get local Sid instead
            logging.info(
                'Target not joined to a domain. Getting local accounts instead'
            )
            in_domain = False
            resp = lsad.hLsarQueryInformationPolicy2(
                dce, policyHandle,
                lsad.POLICY_INFORMATION_CLASS.PolicyAccountDomainInformation)
            domainSid = resp['PolicyInformation']['PolicyAccountDomainInfo'][
                'DomainSid'].formatCanonical()

        fh = None
        if self.config.outputFile:
            try:
                fh = open(self.config.outputFile, 'w+')
            except Exception:
                logging.exception('Could not open file for writing')

        soFar = 0
        SIMULTANEOUS = 1000
        for j in range(maxRid / SIMULTANEOUS + 1):
            if (maxRid - soFar) / SIMULTANEOUS == 0:
                sidsToCheck = (maxRid - soFar) % SIMULTANEOUS
            else:
                sidsToCheck = SIMULTANEOUS

            if sidsToCheck == 0:
                break

            sids = list()
            for i in xrange(soFar, soFar + sidsToCheck):
                sids.append(domainSid + '-%d' % i)
            try:
                lsat.hLsarLookupSids(dce, policyHandle, sids,
                                     lsat.LSAP_LOOKUP_LEVEL.LsapLookupWksta)
            except DCERPCException as e:
                if str(e).find('STATUS_NONE_MAPPED') >= 0:
                    soFar += SIMULTANEOUS
                    continue
                elif str(e).find('STATUS_SOME_NOT_MAPPED') >= 0:
                    resp = e.get_packet()
                else:
                    raise

            for n, item in enumerate(resp['TranslatedNames']['Names']):
                if item['Use'] != SID_NAME_USE.SidTypeUnknown:
                    line = "%d: %s\\%s (%s)" % (
                        soFar + n, resp['ReferencedDomains']['Domains'][
                            item['DomainIndex']]['Name'], item['Name'],
                        SID_NAME_USE.enumItems(item['Use']).name)
                    print line
                    if fh:
                        fh.write(line + '\n')

            soFar += SIMULTANEOUS

        if fh:
            fh.close()
        dce.disconnect()

        if in_domain:
            # Only works if we are relaying to a domain member
            SAMRDump().dump(self.__SMBConnection)

        got_usernames = True
Exemple #6
0
    def __bruteForce(self, rpctransport, maxRid):
        dce = rpctransport.get_dce_rpc()
        entries = []
        dce.connect()

        # Want encryption? Uncomment next line
        # But make SIMULTANEOUS variable <= 100
        #dce.set_auth_level(ntlm.NTLM_AUTH_PKT_PRIVACY)

        # Want fragmentation? Uncomment next line
        #dce.set_max_fragment_size(32)

        dce.bind(lsat.MSRPC_UUID_LSAT)

        resp = lsat.hLsarOpenPolicy2(
            dce, MAXIMUM_ALLOWED | lsat.POLICY_LOOKUP_NAMES)
        policyHandle = resp['PolicyHandle']

        if self.__domain_sids:  # get the Domain SID
            resp = lsad.hLsarQueryInformationPolicy2(
                dce, policyHandle,
                lsad.POLICY_INFORMATION_CLASS.PolicyPrimaryDomainInformation)
            domainSid = resp['PolicyInformation']['PolicyPrimaryDomainInfo'][
                'Sid'].formatCanonical()
        else:  # Get the target host SID
            resp = lsad.hLsarQueryInformationPolicy2(
                dce, policyHandle,
                lsad.POLICY_INFORMATION_CLASS.PolicyAccountDomainInformation)
            domainSid = resp['PolicyInformation']['PolicyAccountDomainInfo'][
                'DomainSid'].formatCanonical()

        logging.info('Domain SID is: %s' % domainSid)

        soFar = 0
        SIMULTANEOUS = 1000
        for j in range(maxRid // SIMULTANEOUS + 1):
            if (maxRid - soFar) // SIMULTANEOUS == 0:
                sidsToCheck = (maxRid - soFar) % SIMULTANEOUS
            else:
                sidsToCheck = SIMULTANEOUS

            if sidsToCheck == 0:
                break

            sids = list()
            for i in range(soFar, soFar + sidsToCheck):
                sids.append(domainSid + '-%d' % i)
            try:
                lsat.hLsarLookupSids(dce, policyHandle, sids,
                                     lsat.LSAP_LOOKUP_LEVEL.LsapLookupWksta)
            except DCERPCException as e:
                if str(e).find('STATUS_NONE_MAPPED') >= 0:
                    soFar += SIMULTANEOUS
                    continue
                elif str(e).find('STATUS_SOME_NOT_MAPPED') >= 0:
                    resp = e.get_packet()
                else:
                    raise

            for n, item in enumerate(resp['TranslatedNames']['Names']):
                if item['Use'] != SID_NAME_USE.SidTypeUnknown:
                    print("%d: %s\\%s (%s)" %
                          (soFar + n, resp['ReferencedDomains']['Domains'][
                              item['DomainIndex']]['Name'], item['Name'],
                           SID_NAME_USE.enumItems(item['Use']).name))
            soFar += SIMULTANEOUS

        dce.disconnect()

        return entries
    def rpc_resolve_sids(self):
        """
        Resolve any remaining unknown SIDs for local administrator accounts.
        """
        # If all sids were already cached, we can just return
        if len(self.admin_sids) == 0:
            return
        binding = r'ncacn_np:%s[\PIPE\lsarpc]' % self.addr

        dce = self.dce_rpc_connect(binding, lsat.MSRPC_UUID_LSAT)

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

        try:
            resp = lsat.hLsarOpenPolicy2(dce, lsat.POLICY_LOOKUP_NAMES | MAXIMUM_ALLOWED)
        except Exception as e:
            if str(e).find('Broken pipe') >= 0:
                return
            else:
                raise

        policyHandle = resp['PolicyHandle']

        # We could look up the SIDs all at once, but if not all SIDs are mapped, we don't know which
        # ones were resolved and which not, making it impossible to map them in the cache.
        # Therefor we use more SAMR calls at the start, but after a while most SIDs will be reliable
        # in our cache and this function doesn't even need to get called anymore.
        for sid_string in self.admin_sids:
            try:
                resp = lsat.hLsarLookupSids(dce, policyHandle, [sid_string], lsat.LSAP_LOOKUP_LEVEL.LsapLookupWksta)
            except DCERPCException as e:
                if str(e).find('STATUS_NONE_MAPPED') >= 0:
                    logging.warning('SID %s lookup failed, return status: STATUS_NONE_MAPPED', sid_string)
                    # Try next SID
                    continue
                elif str(e).find('STATUS_SOME_NOT_MAPPED') >= 0:
                    # Not all could be resolved, work with the ones that could
                    resp = e.get_packet()
                else:
                    raise

            domains = []
            for entry in resp['ReferencedDomains']['Domains']:
                domains.append(entry['Name'])

            for entry in resp['TranslatedNames']['Names']:
                domain = domains[entry['DomainIndex']]
                domain_entry = self.ad.get_domain_by_name(domain)
                if domain_entry is not None:
                    domain = ADUtils.ldap2domain(domain_entry['attributes']['distinguishedName'])
                # TODO: what if it isn't? Should we fall back to LDAP?

                if entry['Name'] != '':
                    resolved_entry = ADUtils.resolve_sid_entry(entry, domain)
                    logging.debug('Resolved SID to name: %s', resolved_entry['principal'])
                    self.admins.append({'Name': resolved_entry['principal'],
                                        'Type': resolved_entry['type'].capitalize()})
                    # Add it to our cache
                    self.ad.sidcache.put(sid_string, resolved_entry)
                else:
                    logging.warning('Resolved name is empty [%s]', entry)

        dce.disconnect()
Exemple #8
0
 def getPolicyHandle(self):
     resp = lsat.hLsarOpenPolicy2(self.dce, MAXIMUM_ALLOWED | lsat.POLICY_LOOKUP_NAMES)
     return resp['PolicyHandle']
Exemple #9
0
    def rpc_resolve_sids(self):
        binding = r'ncacn_np:%s[\PIPE\lsarpc]' % self.addr

        dce = self.dce_rpc_connect(binding, lsat.MSRPC_UUID_LSAT)

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

        try:
            resp = lsat.hLsarOpenPolicy2(
                dce, lsat.POLICY_LOOKUP_NAMES | MAXIMUM_ALLOWED)
        except Exception as e:
            if str(e).find('Broken pipe') >= 0:
                return
            else:
                raise

        policyHandle = resp['PolicyHandle']

        try:
            resp = lsat.hLsarLookupSids(dce, policyHandle, self.sids,
                                        lsat.LSAP_LOOKUP_LEVEL.LsapLookupWksta)
        except DCERPCException as e:
            if str(e).find('STATUS_NONE_MAPPED') >= 0:
                logging.warning(
                    'SID lookup failed, return status: STATUS_NONE_MAPPED')
                raise
            elif str(e).find('STATUS_SOME_NOT_MAPPED') >= 0:
                # Not all could be resolved, work with the ones that could
                resp = e.get_packet()
            else:
                raise

        domains = []
        for entry in resp['ReferencedDomains']['Domains']:
            logging.debug('Found referenced domain: %s' % entry['Name'])
            domains.append(entry['Name'])

        i = 0
        for entry in resp['TranslatedNames']['Names']:
            domain = domains[entry['DomainIndex']]
            domainEntry = self.ad.get_domain_by_name(domain)
            if domainEntry is not None:
                domain = ADUtils.ldap2domain(
                    domainEntry['attributes']['distinguishedName'])

            if entry['Name'] != '':
                logging.debug('Resolved SID to name: %s@%s' %
                              (entry['Name'], domain))
                self.admins.append({
                    'computer':
                    self.hostname,
                    'name':
                    unicode(entry['Name']),
                    'use':
                    ADUtils.translateSidType(entry['Use']),
                    'domain':
                    domain,
                    'sid':
                    self.sids[i]
                })
                i = i + 1
            else:
                logging.warning('Resolved name is empty [%s]', entry)

        dce.disconnect()