Esempio n. 1
0
    def process_computer(self, hostname, samname, objectsid, results_q):
        """
            Processes a single computer, pushes the results of the computer to the given Queue.
        """
        logging.debug('Querying computer: %s', hostname)
        c = ADComputer(hostname=hostname,
                       samname=samname,
                       ad=self.addomain,
                       objectsid=objectsid)
        if c.try_connect() == True:
            # Maybe try connection reuse?
            try:
                if 'session' in self.collect:
                    sessions = c.rpc_get_sessions()
                else:
                    sessions = []
                if 'localadmin' in self.collect:
                    c.rpc_get_local_admins()
                    c.rpc_resolve_sids()
                c.rpc_close()
                # c.rpc_get_domain_trusts()

                results_q.put(('computer', c.get_bloodhound_data()))

                if sessions is None:
                    sessions = []

                for ses in sessions:
                    # For every session, resolve the SAM name in the GC if needed
                    domain = self.addomain.domain
                    if self.addomain.num_domains > 1 and self.do_gc_lookup:
                        try:
                            users = self.addomain.samcache.get(samname)
                        except KeyError:
                            # Look up the SAM name in the GC
                            users = self.addomain.objectresolver.gc_sam_lookup(
                                ses['user'])
                            if users is None:
                                # Unknown user
                                continue
                            self.addomain.samcache.put(samname, users)
                    else:
                        users = [((u'%s@%s' % (ses['user'], domain)).upper(),
                                  2)]

                    # Resolve the IP to obtain the host the session is from
                    try:
                        target = self.addomain.dnscache.get(ses['source'])
                    except KeyError:
                        target = ADUtils.ip2host(ses['source'],
                                                 self.addomain.dnsresolver,
                                                 self.addomain.dns_tcp)
                        # Even if the result is the IP (aka could not resolve PTR) we still cache
                        # it since this result is unlikely to change during this run
                        self.addomain.dnscache.put_single(
                            ses['source'], target)
                    if ':' in target:
                        # IPv6 address, not very useful
                        continue
                    if '.' not in target:
                        logging.debug(
                            'Resolved target does not look like an IP or domain. Assuming hostname: %s',
                            target)
                        target = '%s.%s' % (target, domain)
                    # Put the result on the results queue.
                    for user in users:
                        results_q.put(('session', {
                            'UserName': user[0].upper(),
                            'ComputerName': target.upper(),
                            'Weight': user[1]
                        }))

            except DCERPCException:
                logging.warning('Querying computer failed: %s' % hostname)
            except Exception as e:
                logging.error('Unhandled exception in computer processing: %s',
                              str(e))
                logging.info(traceback.format_exc())
Esempio n. 2
0
    def process_computer(self, hostname, samname, objectsid, entry, results_q):
        """
            Processes a single computer, pushes the results of the computer to the given Queue.
        """
        logging.debug('Querying computer: %s', hostname)
        c = ADComputer(hostname=hostname,
                       samname=samname,
                       ad=self.addomain,
                       objectsid=objectsid)
        c.primarygroup = self.get_primary_membership(entry)
        if c.try_connect() == True:
            try:

                if 'session' in self.collect:
                    sessions = c.rpc_get_sessions()
                else:
                    sessions = []
                if 'localadmin' in self.collect:
                    c.rpc_get_local_admins()
                    c.rpc_resolve_sids()
                if 'loggedon' in self.collect:
                    loggedon = c.rpc_get_loggedon()
                else:
                    loggedon = []
                if 'experimental' in self.collect:
                    services = c.rpc_get_services()
                    tasks = c.rpc_get_schtasks()
                else:
                    services = []
                    tasks = []

                c.rpc_close()
                # c.rpc_get_domain_trusts()

                results_q.put(
                    ('computer', c.get_bloodhound_data(entry, self.collect)))

                if sessions is None:
                    sessions = []

                # Process found sessions
                for ses in sessions:
                    # For every session, resolve the SAM name in the GC if needed
                    domain = self.addomain.domain
                    if self.addomain.num_domains > 1 and self.do_gc_lookup:
                        try:
                            users = self.addomain.samcache.get(samname)
                        except KeyError:
                            # Look up the SAM name in the GC
                            users = self.addomain.objectresolver.gc_sam_lookup(
                                ses['user'])
                            if users is None:
                                # Unknown user
                                continue
                            self.addomain.samcache.put(samname, users)
                    else:
                        users = [((u'%s@%s' % (ses['user'], domain)).upper(),
                                  2)]

                    # Resolve the IP to obtain the host the session is from
                    try:
                        target = self.addomain.dnscache.get(ses['source'])
                    except KeyError:
                        target = ADUtils.ip2host(ses['source'],
                                                 self.addomain.dnsresolver,
                                                 self.addomain.dns_tcp)
                        # Even if the result is the IP (aka could not resolve PTR) we still cache
                        # it since this result is unlikely to change during this run
                        self.addomain.dnscache.put_single(
                            ses['source'], target)
                    if ':' in target:
                        # IPv6 address, not very useful
                        continue
                    if '.' not in target:
                        logging.debug(
                            'Resolved target does not look like an IP or domain. Assuming hostname: %s',
                            target)
                        target = '%s.%s' % (target, domain)
                    # Put the result on the results queue.
                    for user in users:
                        results_q.put(('session', {
                            'UserName': user[0].upper(),
                            'ComputerName': target.upper(),
                            'Weight': user[1]
                        }))
                if loggedon is None:
                    loggedon = []

                # Put the logged on users on the queue too
                for user in loggedon:
                    results_q.put(('session', {
                        'UserName': ('%s@%s' % user).upper(),
                        'ComputerName': hostname.upper(),
                        'Weight': 1
                    }))

                # Process Tasks
                for taskuser in tasks:
                    try:
                        user = self.addomain.sidcache.get(taskuser)
                    except KeyError:
                        # Resolve SID in GC
                        userentry = self.addomain.objectresolver.resolve_sid(
                            taskuser)
                        # Resolve it to an entry and store in the cache
                        user = ADUtils.resolve_ad_entry(userentry)
                        self.addomain.sidcache.put(taskuser, user)
                    logging.debug('Resolved TASK SID to username: %s',
                                  user['principal'])
                    # Use sessions for now
                    results_q.put(('session', {
                        'UserName': user['principal'].upper(),
                        'ComputerName': hostname.upper(),
                        'Weight': 2
                    }))

                # Process Services
                for serviceuser in services:
                    # Todo: use own cache
                    try:
                        user = self.addomain.sidcache.get(serviceuser)
                    except KeyError:
                        # Resolve UPN in GC
                        userentry = self.addomain.objectresolver.resolve_upn(
                            serviceuser)
                        # Resolve it to an entry and store in the cache
                        user = ADUtils.resolve_ad_entry(userentry)
                        self.addomain.sidcache.put(serviceuser, user)
                    logging.debug('Resolved Service UPN to username: %s',
                                  user['principal'])
                    # Use sessions for now
                    results_q.put(('session', {
                        'UserName': user['principal'].upper(),
                        'ComputerName': hostname.upper(),
                        'Weight': 2
                    }))

            except DCERPCException:
                logging.warning('Querying computer failed: %s' % hostname)
            except Exception as e:
                logging.error(
                    'Unhandled exception in computer %s processing: %s',
                    hostname, str(e))
                logging.info(traceback.format_exc())
        else:
            # Write the info we have to the file regardless
            try:
                results_q.put(
                    ('computer', c.get_bloodhound_data(entry, self.collect)))
            except Exception as e:
                logging.error(
                    'Unhandled exception in computer %s processing: %s',
                    hostname, str(e))
                logging.info(traceback.format_exc())