class BloodHound(object): def __init__(self, ad): self.ad = ad self.ldap = None self.pdc = None self.sessions = [] def connect(self): if len(self.ad.dcs()) == 0: logging.error( 'Could not find a domain controller. Consider specifying a domain and/or DNS server.' ) sys.exit(1) pdc = self.ad.dcs()[0] logging.debug('Using LDAP server: %s', pdc) logging.debug('Using base DN: %s', self.ad.baseDN) if len(self.ad.kdcs()) > 0: kdc = self.ad.kdcs()[0] logging.debug('Using kerberos KDC: %s', kdc) logging.debug('Using kerberos realm: %s', self.ad.realm()) # Create a domain controller object self.pdc = ADDC(pdc, self.ad) # Create an object resolver self.ad.create_objectresolver(self.pdc) # self.pdc.ldap_connect(self.ad.auth.username, self.ad.auth.password, kdc) def run(self, collect, num_workers=10): if 'group' in collect: # Fetch domains/computers for later self.pdc.prefetch_info() # Initialize enumerator membership_enum = MembershipEnumerator(self.ad, self.pdc) membership_enum.enumerate_memberships() elif 'localadmin' in collect or 'session' in collect: # We need to know which computers to query regardless # We also need the domains to have a mapping from NETBIOS -> FQDN for local admins self.pdc.prefetch_info() elif 'trusts' in collect: # Prefetch domains self.pdc.get_domains() if 'trusts' in collect: trusts_enum = TrustsEnumerator(self.ad, self.pdc) trusts_enum.dump_trusts() if 'localadmin' in collect or 'session' in collect: # If we don't have a GC server, don't use it for deconflictation have_gc = len(self.ad.gcs()) > 0 computer_enum = ComputerEnumerator(self.ad, collect, do_gc_lookup=have_gc) computer_enum.enumerate_computers(self.ad.computers, num_workers=num_workers) logging.info('Done')
class BloodHound(object): def __init__(self, ad): self.ad = ad self.ldap = None self.pdc = None self.sessions = [] def connect(self): if len(self.ad.dcs()) == 0: logging.error( 'Could not find a domain controller. Consider specifying a domain and/or DNS server.' ) sys.exit(1) if not self.ad.baseDN: logging.error( 'Could not figure out the domain to query. Please specify this manualy with -d' ) sys.exit(1) pdc = self.ad.dcs()[0] logging.debug('Using LDAP server: %s', pdc) logging.debug('Using base DN: %s', self.ad.baseDN) if len(self.ad.kdcs()) > 0: kdc = self.ad.kdcs()[0] logging.debug('Using kerberos KDC: %s', kdc) logging.debug('Using kerberos realm: %s', self.ad.realm()) # Create a domain controller object self.pdc = ADDC(pdc, self.ad) # Create an object resolver self.ad.create_objectresolver(self.pdc) # self.pdc.ldap_connect(self.ad.auth.username, self.ad.auth.password, kdc) def run(self, collect, num_workers=10, disable_pooling=False): start_time = time.time() if 'group' in collect or 'objectprops' in collect or 'acl' in collect: # Fetch domains/computers for later self.pdc.prefetch_info('objectprops' in collect, 'acl' in collect) # Initialize enumerator membership_enum = MembershipEnumerator(self.ad, self.pdc, collect, disable_pooling) membership_enum.enumerate_memberships() elif any(method in collect for method in [ 'localadmin', 'session', 'loggedon', 'experimental', 'rdp', 'dcom', 'psremote' ]): # We need to know which computers to query regardless # We also need the domains to have a mapping from NETBIOS -> FQDN for local admins self.pdc.prefetch_info('objectprops' in collect, 'acl' in collect) elif 'trusts' in collect: # Prefetch domains self.pdc.get_domains('acl' in collect) if 'trusts' in collect or 'acl' in collect or 'objectprops' in collect: trusts_enum = DomainEnumerator(self.ad, self.pdc) trusts_enum.dump_domain(collect) if 'localadmin' in collect or 'session' in collect or 'loggedon' in collect or 'experimental' in collect: # If we don't have a GC server, don't use it for deconflictation have_gc = len(self.ad.gcs()) > 0 computer_enum = ComputerEnumerator(self.ad, self.pdc, collect, do_gc_lookup=have_gc) computer_enum.enumerate_computers(self.ad.computers, num_workers=num_workers) end_time = time.time() minutes, seconds = divmod(int(end_time - start_time), 60) logging.info('Done in %02dM %02dS' % (minutes, seconds))