def _transport_send(self, rpc_packet, forceWriteAndx=0, forceRecv=0): rpc_packet['ctx_id'] = self._ctx if self.__auth_level in [ ntlm.NTLM_AUTH_PKT_INTEGRITY, ntlm.NTLM_AUTH_PKT_PRIVACY ]: # Dummy verifier, just for the calculations verifier = ntlm.DCERPC_NTLMAuthVerifier() verifier['auth_pad_len'] = 0 pad = (8 - (len(rpc_packet.get_packet()) % 8)) % 8 if pad != 0: rpc_packet['pduData'] = rpc_packet['pduData'] + '\x00' * pad verifier['auth_pad_len'] = pad verifier['auth_level'] = self.__auth_level verifier['auth_ctx_id'] = self._ctx + 79231 verifier['data'] = ' ' * 12 rpc_packet['auth_data'] = str(verifier) plain_data = rpc_packet['pduData'] if self.__auth_level == ntlm.NTLM_AUTH_PKT_PRIVACY: if self.__flags & ntlm.NTLMSSP_NTLM2_KEY: # When NTLM2 is on, we sign the whole pdu, but encrypt just # the data, not the dcerpc header. Weird.. sealedMessage, signature = ntlm.SEAL( self.__flags, self.__clientSigningKey, self.__clientSealingKey, rpc_packet.get_packet()[:-16], plain_data, self.__sequence, self.__clientSealingHandle, isDCE=True) else: sealedMessage, signature = ntlm.SEAL( self.__flags, self.__clientSigningKey, self.__clientSealingKey, plain_data, plain_data, self.__sequence, self.__clientSealingHandle, isDCE=True) rpc_packet['pduData'] = sealedMessage else: if self.__flags & ntlm.NTLMSSP_NTLM2_KEY: # Interesting thing.. with NTLM2, what is is signed is the # whole PDU, not just the data signature = ntlm.SIGN(self.__flags, self.__clientSigningKey, rpc_packet.get_packet()[:-16], self.__sequence, self.__clientSealingHandle, isDCE=True) else: signature = ntlm.SIGN(self.__flags, self.__clientSigningKey, plain_data, self.__sequence, self.__clientSealingHandle, isDCE=True) signature['auth_level'] = self.__auth_level signature['auth_ctx_id'] = verifier['auth_ctx_id'] signature['auth_pad_len'] = pad rpc_packet['auth_data'] = str(signature) self.__sequence += 1 self._transport.send(rpc_packet.get_packet(), forceWriteAndx=forceWriteAndx, forceRecv=forceRecv)
def recv(self): finished = False forceRecv = 0 retAnswer = '' while not finished: # At least give me the MSRPCRespHeader, especially important for TCP/UDP Transports self.response_data = self._transport.recv( forceRecv, count=MSRPCRespHeader._SIZE) self.response_header = MSRPCRespHeader(self.response_data) # Ok, there might be situation, especially with large packets, that the transport layer didn't send us the full packet's contents # So we gotta check we received it all while (len(self.response_data) < self.response_header['frag_len']): self.response_data += self._transport.recv( forceRecv, count=(self.response_header['frag_len'] - len(self.response_data))) off = self.response_header.get_header_size() if self.response_header[ 'type'] == MSRPC_FAULT and self.response_header[ 'frag_len'] >= off + 4: status_code = unpack("<L", self.response_data[off:off + 4])[0] if rpc_status_codes.has_key(status_code): raise Exception(rpc_status_codes[status_code]) else: raise Exception('Unknown DCE RPC fault status code: %.8x' % status_code) if self.response_header['flags'] & MSRPC_LASTFRAG: # No need to reassembly DCERPC finished = True else: # Forcing Read Recv, we need more packets! forceRecv = 1 answer = self.response_data[off:] auth_len = self.response_header['auth_len'] if auth_len: auth_len += 8 auth_data = answer[-auth_len:] ntlmssp = ntlm.DCERPC_NTLMAuthHeader(data=auth_data) answer = answer[:-auth_len] if ntlmssp['auth_level'] == ntlm.NTLM_AUTH_PKT_PRIVACY: if self.__flags & ntlm.NTLMSSP_NTLM2_KEY: # TODO: FIX THIS, it's not calculating the signature well # Since I'm not testing it we don't care... yet answer, signature = ntlm.SEAL( self.__flags, self.__serverSigningKey, self.__serverSealingKey, answer, answer, self.__sequence, self.__serverSealingHandle, isDCE=True) else: answer, signature = ntlm.SEAL( self.__flags, self.__serverSigningKey, self.__serverSealingKey, answer, answer, self.__sequence, self.__serverSealingHandle, isDCE=True) self.__sequence += 1 else: ntlmssp = ntlm.DCERPC_NTLMAuthVerifier(data=auth_data) if self.__flags & ntlm.NTLMSSP_NTLM2_KEY: signature = ntlm.SIGN(self.__flags, self.__serverSigningKey, answer, self.__sequence, self.__serverSealingHandle, isDCE=True) else: signature = ntlm.SIGN(self.__flags, self.__serverSigningKey, ntlmssp['data'], self.__sequence, self.__serverSealingHandle, isDCE=True) # Yes.. NTLM2 doesn't increment sequence when receiving # the packet :P self.__sequence += 1 if ntlmssp['auth_pad_len']: answer = answer[:-ntlmssp['auth_pad_len']] retAnswer += answer return retAnswer
def _transport_send(self, rpc_packet, forceWriteAndx = 0, forceRecv = 0): rpc_packet['ctx_id'] = self._ctx if self.__auth_level in [RPC_C_AUTHN_LEVEL_PKT_INTEGRITY, RPC_C_AUTHN_LEVEL_PKT_PRIVACY]: # Dummy verifier, just for the calculations sec_trailer = SEC_TRAILER() sec_trailer['auth_type'] = self.__auth_type sec_trailer['auth_level'] = self.__auth_level sec_trailer['auth_pad_len'] = 0 sec_trailer['auth_ctx_id'] = self._ctx + 79231 pad = (4 - (len(rpc_packet.get_packet()) % 4)) % 4 if pad != 0: rpc_packet['pduData'] = rpc_packet['pduData'] + '\xBB'*pad sec_trailer['auth_pad_len']=pad rpc_packet['sec_trailer'] = str(sec_trailer) rpc_packet['auth_data'] = ' '*16 plain_data = rpc_packet['pduData'] if self.__auth_level == RPC_C_AUTHN_LEVEL_PKT_PRIVACY: if self.__auth_type == RPC_C_AUTHN_WINNT: if self.__flags & ntlm.NTLMSSP_NTLM2_KEY: # When NTLM2 is on, we sign the whole pdu, but encrypt just # the data, not the dcerpc header. Weird.. sealedMessage, signature = ntlm.SEAL(self.__flags, self.__clientSigningKey, self.__clientSealingKey, rpc_packet.get_packet()[:-16], plain_data, self.__sequence, self.__clientSealingHandle) else: sealedMessage, signature = ntlm.SEAL(self.__flags, self.__clientSigningKey, self.__clientSealingKey, plain_data, plain_data, self.__sequence, self.__clientSealingHandle) rpc_packet['pduData'] = sealedMessage else: if self.__auth_type == RPC_C_AUTHN_WINNT: if self.__flags & ntlm.NTLMSSP_NTLM2_KEY: # Interesting thing.. with NTLM2, what is is signed is the # whole PDU, not just the data signature = ntlm.SIGN(self.__flags, self.__clientSigningKey, rpc_packet.get_packet()[:-16], self.__sequence, self.__clientSealingHandle) else: signature = ntlm.SIGN(self.__flags, self.__clientSigningKey, plain_data, self.__sequence, self.__clientSealingHandle) elif self.__auth_type == RPC_C_AUTHN_NETLOGON: from impacket.dcerpc import netlogon signature = netlogon.SIGN(rpc_packet.get_packet()[:-16], self.__sequence, '', self.__sessionKey) rpc_packet['sec_trailer'] = str(sec_trailer) rpc_packet['auth_data'] = str(signature) self.__sequence += 1 self._transport.send(rpc_packet.get_packet(), forceWriteAndx = forceWriteAndx, forceRecv = forceRecv)