def __init__(self, transport): dcerpc.DCERPC.__init__(self, transport) self.__activity_uuid = uuid.generate() self.__seq_num = 0 self._bind = 0 # Don't attempt binding unless it explicitly requested. self.set_idempotent(0)
def bind(self, uuid, alter=0, bogus_binds=0): bind = MSRPCBind() # Standard NDR Representation NDRSyntax = ('8a885d04-1ceb-11c9-9fe8-08002b104860', '2.0') # NDR 64 NDR64Syntax = ('71710533-BEBA-4937-8319-B5DBEF9CCC36', '1.0') #item['TransferSyntax']['Version'] = 1 ctx = self._ctx for i in range(bogus_binds): item = CtxItem() item['ContextID'] = ctx item['TransItems'] = 1 item['ContextID'] = ctx # We generate random UUIDs for bogus binds item['AbstractSyntax'] = generate() + stringver_to_bin('2.0') item['TransferSyntax'] = uuidtup_to_bin(NDRSyntax) bind.addCtxItem(item) self._ctx += 1 ctx += 1 # The true one :) item = CtxItem() item['AbstractSyntax'] = uuid item['TransferSyntax'] = uuidtup_to_bin(NDRSyntax) item['ContextID'] = ctx item['TransItems'] = 1 bind.addCtxItem(item) packet = MSRPCHeader() packet['type'] = MSRPC_BIND packet['pduData'] = str(bind) packet['call_id'] = self.__callid if alter: packet['type'] = MSRPC_ALTERCTX if (self.__auth_level != RPC_C_AUTHN_LEVEL_NONE): if (self.__username is None) or (self.__password is None): self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash, self.__aesKey, self.__TGT, self.__TGS = self._transport.get_credentials( ) if self.__auth_type == RPC_C_AUTHN_WINNT: auth = ntlm.getNTLMSSPType1( '', self.__domain, signingRequired=True, use_ntlmv2=self._transport.doesSupportNTLMv2()) elif self.__auth_type == RPC_C_AUTHN_NETLOGON: from mitmflib.impacket.dcerpc import netlogon auth = netlogon.getSSPType1(self.__username[:-1], self.__domain, signingRequired=True) sec_trailer = SEC_TRAILER() sec_trailer['auth_type'] = self.__auth_type sec_trailer['auth_level'] = self.__auth_level sec_trailer['auth_ctx_id'] = self._ctx + 79231 pad = (4 - (len(packet.get_packet()) % 4)) % 4 if pad != 0: packet['pduData'] = packet['pduData'] + '\xFF' * pad sec_trailer['auth_pad_len'] = pad packet['sec_trailer'] = sec_trailer packet['auth_data'] = str(auth) self._transport.send(packet.get_packet()) s = self._transport.recv() if s != 0: resp = MSRPCHeader(s) else: return 0 #mmm why not None? if resp['type'] == MSRPC_BINDACK or resp['type'] == MSRPC_ALTERCTX_R: bindResp = MSRPCBindAck(str(resp)) elif resp['type'] == MSRPC_BINDNAK: resp = MSRPCBindNak(resp['pduData']) status_code = resp['RejectedReason'] if rpc_status_codes.has_key(status_code): raise Exception(rpc_status_codes[status_code], resp) elif rpc_provider_reason.has_key(status_code): raise Exception("Bind context rejected: %s" % rpc_provider_reason[status_code]) else: raise Exception( 'Unknown DCE RPC fault status code: %.8x' % status_code, resp) else: raise Exception('Unknown DCE RPC packet type received: %d' % resp['type']) # check ack results for each context, except for the bogus ones for ctx in range(bogus_binds + 1, bindResp['ctx_num'] + 1): result = bindResp.getCtxItem(ctx)['Result'] if result != 0: msg = "Bind context %d rejected: " % ctx msg += rpc_cont_def_result.get( result, 'Unknown DCE RPC context result code: %.4x' % result) msg += "; " reason = bindResp.getCtxItem(ctx)['Reason'] msg += rpc_provider_reason.get( reason, 'Unknown reason code: %.4x' % reason) if (result, reason) == ( 2, 1 ): # provider_rejection, abstract syntax not supported msg += " (this usually means the interface isn't listening on the given endpoint)" raise Exception(msg, resp) self.__max_xmit_size = bindResp['max_tfrag'] if self.__auth_level != RPC_C_AUTHN_LEVEL_NONE: if self.__auth_type == RPC_C_AUTHN_WINNT: response, randomSessionKey = ntlm.getNTLMSSPType3( auth, bindResp['auth_data'], self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash, use_ntlmv2=self._transport.doesSupportNTLMv2()) self.__flags = response['flags'] elif self.__auth_type == RPC_C_AUTHN_NETLOGON: response = None self.__sequence = 0 if self.__auth_level in (RPC_C_AUTHN_LEVEL_CONNECT, RPC_C_AUTHN_LEVEL_PKT_INTEGRITY, RPC_C_AUTHN_LEVEL_PKT_PRIVACY): if self.__auth_type == RPC_C_AUTHN_WINNT: if self.__flags & ntlm.NTLMSSP_NTLM2_KEY: self.__clientSigningKey = ntlm.SIGNKEY( self.__flags, randomSessionKey) self.__serverSigningKey = ntlm.SIGNKEY( self.__flags, randomSessionKey, "Server") self.__clientSealingKey = ntlm.SEALKEY( self.__flags, randomSessionKey) self.__serverSealingKey = ntlm.SEALKEY( self.__flags, randomSessionKey, "Server") # Preparing the keys handle states cipher3 = ARC4.new(self.__clientSealingKey) self.__clientSealingHandle = cipher3.encrypt cipher4 = ARC4.new(self.__serverSealingKey) self.__serverSealingHandle = cipher4.encrypt else: # Same key for everything self.__clientSigningKey = randomSessionKey self.__serverSigningKey = randomSessionKey self.__clientSealingKey = randomSessionKey self.__serverSealingKey = randomSessionKey cipher = ARC4.new(self.__clientSigningKey) self.__clientSealingHandle = cipher.encrypt self.__serverSealingHandle = cipher.encrypt elif self.__auth_type == RPC_C_AUTHN_NETLOGON: pass sec_trailer = SEC_TRAILER() sec_trailer['auth_type'] = self.__auth_type sec_trailer['auth_level'] = self.__auth_level sec_trailer['auth_ctx_id'] = self._ctx + 79231 if response is not None: auth3 = MSRPCHeader() auth3['type'] = MSRPC_AUTH3 # pad (4 bytes): Can be set to any arbitrary value when set and MUST be # ignored on receipt. The pad field MUST be immediately followed by a # sec_trailer structure whose layout, location, and alignment are as # specified in section 2.2.2.11 auth3['pduData'] = ' ' auth3['sec_trailer'] = sec_trailer auth3['auth_data'] = str(response) # Use the same call_id self.__callid = resp['call_id'] auth3['call_id'] = self.__callid self._transport.send(auth3.get_packet(), forceWriteAndx=1) self.__callid += 1 return resp # means packet is signed, if verifier is wrong it fails
def bind(self, uuid, alter = 0, bogus_binds = 0): bind = MSRPCBind() # Standard NDR Representation NDRSyntax = ('8a885d04-1ceb-11c9-9fe8-08002b104860', '2.0') # NDR 64 NDR64Syntax = ('71710533-BEBA-4937-8319-B5DBEF9CCC36', '1.0') #item['TransferSyntax']['Version'] = 1 ctx = self._ctx for i in range(bogus_binds): item = CtxItem() item['ContextID'] = ctx item['TransItems'] = 1 item['ContextID'] = ctx # We generate random UUIDs for bogus binds item['AbstractSyntax'] = generate() + stringver_to_bin('2.0') item['TransferSyntax'] = uuidtup_to_bin(NDRSyntax) bind.addCtxItem(item) self._ctx += 1 ctx += 1 # The true one :) item = CtxItem() item['AbstractSyntax'] = uuid item['TransferSyntax'] = uuidtup_to_bin(NDRSyntax) item['ContextID'] = ctx item['TransItems'] = 1 bind.addCtxItem(item) packet = MSRPCHeader() packet['type'] = MSRPC_BIND packet['pduData'] = str(bind) packet['call_id'] = self.__callid if alter: packet['type'] = MSRPC_ALTERCTX if (self.__auth_level != RPC_C_AUTHN_LEVEL_NONE): if (self.__username is None) or (self.__password is None): self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash, self.__aesKey, self.__TGT, self.__TGS = self._transport.get_credentials() if self.__auth_type == RPC_C_AUTHN_WINNT: auth = ntlm.getNTLMSSPType1('', self.__domain, signingRequired = True, use_ntlmv2 = self._transport.doesSupportNTLMv2()) elif self.__auth_type == RPC_C_AUTHN_NETLOGON: from mitmflib.impacket.dcerpc import netlogon auth = netlogon.getSSPType1(self.__username[:-1], self.__domain, signingRequired = True) sec_trailer = SEC_TRAILER() sec_trailer['auth_type'] = self.__auth_type sec_trailer['auth_level'] = self.__auth_level sec_trailer['auth_ctx_id'] = self._ctx + 79231 pad = (4 - (len(packet.get_packet()) % 4)) % 4 if pad != 0: packet['pduData'] = packet['pduData'] + '\xFF'*pad sec_trailer['auth_pad_len']=pad packet['sec_trailer'] = sec_trailer packet['auth_data'] = str(auth) self._transport.send(packet.get_packet()) s = self._transport.recv() if s != 0: resp = MSRPCHeader(s) else: return 0 #mmm why not None? if resp['type'] == MSRPC_BINDACK or resp['type'] == MSRPC_ALTERCTX_R: bindResp = MSRPCBindAck(str(resp)) elif resp['type'] == MSRPC_BINDNAK: resp = MSRPCBindNak(resp['pduData']) status_code = resp['RejectedReason'] if rpc_status_codes.has_key(status_code): raise Exception(rpc_status_codes[status_code], resp) elif rpc_provider_reason.has_key(status_code): raise Exception("Bind context rejected: %s" % rpc_provider_reason[status_code]) else: raise Exception('Unknown DCE RPC fault status code: %.8x' % status_code, resp) else: raise Exception('Unknown DCE RPC packet type received: %d' % resp['type']) # check ack results for each context, except for the bogus ones for ctx in range(bogus_binds+1,bindResp['ctx_num']+1): result = bindResp.getCtxItem(ctx)['Result'] if result != 0: msg = "Bind context %d rejected: " % ctx msg += rpc_cont_def_result.get(result, 'Unknown DCE RPC context result code: %.4x' % result) msg += "; " reason = bindResp.getCtxItem(ctx)['Reason'] msg += rpc_provider_reason.get(reason, 'Unknown reason code: %.4x' % reason) if (result, reason) == (2, 1): # provider_rejection, abstract syntax not supported msg += " (this usually means the interface isn't listening on the given endpoint)" raise Exception(msg, resp) self.__max_xmit_size = bindResp['max_tfrag'] if self.__auth_level != RPC_C_AUTHN_LEVEL_NONE: if self.__auth_type == RPC_C_AUTHN_WINNT: response, randomSessionKey = ntlm.getNTLMSSPType3(auth, bindResp['auth_data'], self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash, use_ntlmv2 = self._transport.doesSupportNTLMv2()) self.__flags = response['flags'] elif self.__auth_type == RPC_C_AUTHN_NETLOGON: response = None self.__sequence = 0 if self.__auth_level in (RPC_C_AUTHN_LEVEL_CONNECT, RPC_C_AUTHN_LEVEL_PKT_INTEGRITY, RPC_C_AUTHN_LEVEL_PKT_PRIVACY): if self.__auth_type == RPC_C_AUTHN_WINNT: if self.__flags & ntlm.NTLMSSP_NTLM2_KEY: self.__clientSigningKey = ntlm.SIGNKEY(self.__flags, randomSessionKey) self.__serverSigningKey = ntlm.SIGNKEY(self.__flags, randomSessionKey,"Server") self.__clientSealingKey = ntlm.SEALKEY(self.__flags, randomSessionKey) self.__serverSealingKey = ntlm.SEALKEY(self.__flags, randomSessionKey,"Server") # Preparing the keys handle states cipher3 = ARC4.new(self.__clientSealingKey) self.__clientSealingHandle = cipher3.encrypt cipher4 = ARC4.new(self.__serverSealingKey) self.__serverSealingHandle = cipher4.encrypt else: # Same key for everything self.__clientSigningKey = randomSessionKey self.__serverSigningKey = randomSessionKey self.__clientSealingKey = randomSessionKey self.__serverSealingKey = randomSessionKey cipher = ARC4.new(self.__clientSigningKey) self.__clientSealingHandle = cipher.encrypt self.__serverSealingHandle = cipher.encrypt elif self.__auth_type == RPC_C_AUTHN_NETLOGON: pass sec_trailer = SEC_TRAILER() sec_trailer['auth_type'] = self.__auth_type sec_trailer['auth_level'] = self.__auth_level sec_trailer['auth_ctx_id'] = self._ctx + 79231 if response is not None: auth3 = MSRPCHeader() auth3['type'] = MSRPC_AUTH3 # pad (4 bytes): Can be set to any arbitrary value when set and MUST be # ignored on receipt. The pad field MUST be immediately followed by a # sec_trailer structure whose layout, location, and alignment are as # specified in section 2.2.2.11 auth3['pduData'] = ' ' auth3['sec_trailer'] = sec_trailer auth3['auth_data'] = str(response) # Use the same call_id self.__callid = resp['call_id'] auth3['call_id'] = self.__callid self._transport.send(auth3.get_packet(), forceWriteAndx = 1) self.__callid += 1 return resp # means packet is signed, if verifier is wrong it fails