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())
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())