def setup_crypto(self): if self.mode.upper() == 'SERVER': self.EncryptedRandomSessionKey = self.ntlmAuthenticate.EncryptedRandomSession print('self.EncryptedRandomSessionKey %s' % self.EncryptedRandomSessionKey) rc4 = RC4(self.KeyExchangeKey) self.RandomSessionKey = rc4.decrypt(self.EncryptedRandomSessionKey) else: if not self.RandomSessionKey: self.RandomSessionKey = os.urandom(16) if self.mode.upper() != 'MANUAL': #this check is here to provide the option to load the messages + the sessionbasekey manually #then you will be able to use the sign and seal functions provided by this class if self.settings.credential.is_guest == False: self.SessionBaseKey = self.ntlm_credentials.SessionBaseKey rc4 = RC4(self.KeyExchangeKey) self.EncryptedRandomSessionKey = rc4.encrypt( self.RandomSessionKey) self.calc_sealkey('Client') self.calc_sealkey('Server') self.calc_signkey('Client') self.calc_signkey('Server')
async def sign(self, data, message_no, direction=None, reset_cipher=False): """ Singing outgoing messages. The reset_cipher parameter is needed for calculating mechListMIC. """ #print('sign data : %s' % data) #print('sign message_no : %s' % message_no) #print('sign direction : %s' % direction) signature = self.MAC(self.crypthandle_client.encrypt, self.SignKey_client, message_no, data) if reset_cipher is True: self.crypthandle_client = RC4(self.SealKey_client) self.crypthandle_server = RC4(self.SealKey_server) self.seq_number += 1 return signature
def decrypt_lsa_key(self, data): logger.debug('[SECURITY] Decrypting LSA key...') if self.lsa_secret_key_vista_type is True: record = LSA_SECRET.from_bytes(data) key = SECURITY.sha256_multi(self.bootkey, record.data[:32]) secret_dec = b'' cipher = AES(key) n = 16 for block in [ record.data[32:][i:i + n] for i in range(0, len(record.data[32:]), n) ]: #terrible, terrible workaround if len(block) < n: block += b'\x00' * (n - len(block)) secret_dec += cipher.decrypt(block) record = LSA_SECRET_BLOB.from_bytes(secret_dec) self.lsa_key = record.secret[52:][:32] else: ctx = hashlib.md5(self.bootkey) for i in range(1000): ctx.update(data[60:76]) cipher = RC4(ctx.digest()) record = cipher.decrypt(data[12:60]) self.lsa_key = record[0x10:0x20] logger.debug('[SECURITY] LSA key value: %s' % self.lsa_key.hex()) return self.lsa_key
def decrypt_hash(self, rid, hashobj, constant): key1, key2 = SAM.rid_to_key(rid) des1 = DES(key1) des2 = DES(key2) if isinstance(hashobj, SAM_HASH): rc4key = hashlib.md5( self.hashed_bootkey[:0x10] + int(rid, 16).to_bytes(4, 'little', signed=False) + constant).digest() key = RC4(rc4key).encrypt(hashobj.hash) else: key = b'' cipher = AES(self.hashed_bootkey[:0x10], MODE_CBC, IV=hashobj.salt) n = 16 for block in [ hashobj.data[i:i + n] for i in range(0, len(hashobj.data), n) ]: #terrible, terrible workaround key += cipher.decrypt(block) key = key[:16] dec_hash = des1.decrypt(key[:8]) + des2.decrypt(key[8:]) return dec_hash
def calc_sealkey(self, mode='Client'): if NegotiateFlags.NEGOTIATE_EXTENDED_SESSIONSECURITY in self.ntlmChallenge.NegotiateFlags: if NegotiateFlags.NEGOTIATE_128 in self.ntlmChallenge.NegotiateFlags: sealkey = self.RandomSessionKey elif NegotiateFlags.NEGOTIATE_56 in self.ntlmChallenge.NegotiateFlags: sealkey = self.RandomSessionKey[:7] else: sealkey = self.RandomSessionKey[:5] if mode == 'Client': md5 = hashlib.new('md5') md5.update( sealkey + b'session key to client-to-server sealing key magic constant\x00' ) sealkey = md5.digest() else: md5 = hashlib.new('md5') md5.update( sealkey + b'session key to server-to-client sealing key magic constant\x00' ) sealkey = md5.digest() elif NegotiateFlags.NEGOTIATE_56 in self.ntlmChallenge.NegotiateFlags: sealkey = self.RandomSessionKey[:7] + b'\xa0' else: sealkey = self.RandomSessionKey[:5] + b'\xe5\x38\xb0' if mode == 'Client': self.SealKey_client = sealkey if sealkey is not None: self.crypthandle_client = RC4(self.SealKey_client) else: self.SealKey_server = sealkey if sealkey is not None: self.crypthandle_server = RC4(self.SealKey_server) return sealkey
def decrypt(self, encrypted): # TODO: NT version specific, move from here in subclasses. cleartext = b'' size = len(encrypted) if size: if (size % 8) != 0: ctx = RC4(self.random_key) cleartext = ctx.decrypt(encrypted) else: #print('Decryption not implemented!') cleartext = self.__desx_decrypt(encrypted) #raise Exception('Not implemented!') return cleartext
def setup_crypto(self): if not self.RandomSessionKey: self.RandomSessionKey = os.urandom(16) if self.mode.upper() != 'MANUAL': #this check is here to provide the option to load the messages + the sessionbasekey manually #then you will be able to use the sign and seal functions provided by this class self.SessionBaseKey = self.ntlm_credentials.SessionBaseKey rc4 = RC4(self.KeyExchangeKey) self.EncryptedRandomSessionKey = rc4.encrypt(self.RandomSessionKey) self.calc_sealkey('Client') self.calc_sealkey('Server') self.calc_signkey('Client') self.calc_signkey('Server')
def DecryptAttributeValue(sessionKey, attribute): encryptedPayload = ENCRYPTED_PAYLOAD(attribute) md5 = hashlib.new('md5') md5.update(sessionKey) md5.update(encryptedPayload['Salt']) finalMD5 = md5.digest() cipher = RC4(finalMD5) plainText = cipher.decrypt(attribute[16:]) #chkSum = (binascii.crc32(plainText[4:])) & 0xffffffff #if unpack('<L',plainText[:4])[0] != chkSum: # print "RECEIVED 0x%x" % unpack('<L',plainText[:4])[0] # print "CALCULATED 0x%x" % chkSum return plainText[4:]
def GSS_GetMIC(self, data, sequenceNumber, direction='init'): raise Exception('Not tested! Sure it needs some changes') GSS_GETMIC_HEADER = b'\x60\x23\x06\x09\x2a\x86\x48\x86\xf7\x12\x01\x02\x02' # Let's pad the data pad = (4 - (len(data) % 4)) & 0x3 padStr = bytes([pad]) * pad data += padStr mic = GSSMIC_RC4() if direction == 'init': mic.SND_SEQ = sequenceNumber.to_bytes(4, 'big', signed=False) + b'\x00' * 4 else: mic.SND_SEQ = sequenceNumber.to_bytes(4, 'big', signed=False) + b'\xff' * 4 Ksign_ctx = hmac.new(self.session_key.contents, digestmod='md5') Ksign_ctx.update(b'signaturekey\0') Ksign = Ksign_ctx.digest() id = 15 temp = md5( id.to_bytes(4, 'little', signed=False) + mic.to_bytes()[:8]).digest() chksum_ctx = hmac.new(Ksign, digestmod='md5') chksum_ctx.update(temp) mic.SGN_CKSUM = chksum_ctx.digest()[:8] id = 0 temp = hmac.new(self.session_key.contents, digestmod='md5') temp.update(id.to_bytes(4, 'little', signed=False)) Kseq_ctx = hmac.new(temp.digest(), digestmod='md5') Kseq_ctx.update(mic.SGN_CKSUM) Kseq = Kseq_ctx.digest() mic.SGN_CKSUM = RC4(Kseq).encrypt(mic.SND_SEQ) return GSS_GETMIC_HEADER + mic.to_bytes()
async def get_HBoot_key(self): logger.debug('SAM parsing hashed bootkey') QWERTY = b"!@#$%^&*()qwertyUIOPAzxcvbnmQQQQQQQQQQQQ)(*@&%\0" DIGITS = b"0123456789012345678901234567890123456789\0" F = await self.hive.get_value(r'SAM\Domains\Account\F') F = F[1] logger.log(1, '[SAM] F key value: %s' % F) domain_properties = DOMAIN_ACCOUNT_F.from_bytes(F) if isinstance(domain_properties.key_0, SAM_KEY_DATA): rc4_key = hashlib.md5(domain_properties.key_0.salt + QWERTY + self.bootkey + DIGITS).digest() self.hashed_bootkey = RC4(rc4_key).encrypt( domain_properties.key_0.key + domain_properties.key_0.checksum) checksum = hashlib.md5(self.hashed_bootkey[:16] + DIGITS + self.hashed_bootkey[:16] + QWERTY).digest() if checksum != self.hashed_bootkey[16:]: logger.error('[SAM] HBootkey checksum verification failed!') raise Exception('[SAM] HBootkey checksum verification failed!') elif isinstance(domain_properties.key_0, SAM_KEY_DATA_AES): self.hashed_bootkey = b'' cipher = AES(self.bootkey, MODE_CBC, IV=domain_properties.key_0.salt) n = 16 for block in [ domain_properties.key_0.data[i:i + n] for i in range(0, len(domain_properties.key_0.data), n) ]: #terrible, terrible workaround self.hashed_bootkey += cipher.decrypt(block) logger.debug('[SAM] HBootkey: %s' % self.hashed_bootkey.hex()) return self.hashed_bootkey
def dump_dcc(self): logger.debug('[SECURITY] dump_dcc invoked') cache_reg = self.hive.find_key('Cache', False) if cache_reg is None: logger.debug('[SECURITY] No DCC secrets found') return values = self.hive.list_values(cache_reg) if values == []: logger.debug('[SECURITY] No DCC secrets found') return if b'NL$Control' in values: values.remove(b'NL$Control') if b'NL$IterationCount' in values: logger.debug('[SECURITY] DCC Setting iteration count') values.remove(b'NL$IterationCount') record = self.hive.get_value('Cache\\NL$IterationCount')[1] if record > 10240: self.dcc_iteration_count = record & 0xfffffc00 else: self.dcc_iteration_count = record * 1024 self.get_lsa_key() self.get_NKLM_key() for value in values: logger.debug('[SECURITY] DCC Checking value: %s' % value) record_data = self.hive.get_value('Cache\\%s' % value.decode())[1] record = NL_RECORD.from_bytes(record_data) if record.IV != b'\x00' * 16: if record.Flags & 1 == 1: # Encrypted if self.lsa_secret_key_vista_type is True: plaintext = b'' cipher = AES(self.NKLM_key[16:32], MODE_CBC, IV=record.IV) n = 16 for block in [ record.EncryptedData[i:i + n] for i in range(0, len(record.EncryptedData), n) ]: #terrible, terrible workaround if len(block) < 16: block += b'\x00' * (16 - len(block)) plaintext += cipher.decrypt(block) else: key = hmac.new(self.NKLM_key, record.IV, digestmod='md5').digest() cipher = RC4(key) plaintext = cipher.decrypt(record.EncryptedData) else: # Plain! Until we figure out what this is, we skip it #plainText = record['EncryptedData'] logger.debug( '[SECURITY] DCC Skipping value %s, unknown formet' % value) continue dcc_hash = plaintext[:0x10] blob = io.BytesIO(plaintext[0x48:]) username = blob.read(record.UserLength).decode('utf-16-le') blob.seek( self.__pad(record.UserLength) + self.__pad(record.DomainNameLength)) domain = blob.read( record.DnsDomainNameLength).decode('utf-16-le') version = 2 if self.lsa_secret_key_vista_type is True else 1 secret = LSADCCSecret(version, domain, username, dcc_hash, iteration=self.dcc_iteration_count) self.dcc_hashes.append(secret) return self.dcc_hashes
def GSS_Wrap(self, data, seq_num, direction='init', encrypt=True, auth_data=None): GSS_WRAP_HEADER = b'\x60\x2b\x06\x09\x2a\x86\x48\x86\xf7\x12\x01\x02\x02' pad = (8 - (len(data) % 8)) & 0x7 padStr = bytes([pad]) * pad data += padStr token = GSSWRAP_RC4() token.SEAL_ALG = b'\x10\x00' if direction == 'init': token.SND_SEQ = seq_num.to_bytes(4, 'big', signed=False) + b'\x00' * 4 else: token.SND_SEQ = seq_num.to_bytes(4, 'big', signed=False) + b'\xff' * 4 token.Confounder = os.urandom(8) temp = hmac.new(self.session_key.contents, digestmod='md5') temp.update(b'signaturekey\0') Ksign = temp.digest() id = 13 Sgn_Cksum = md5( id.to_bytes(4, 'little', signed=False) + token.to_bytes()[:8] + token.Confounder + data).digest() temp = hmac.new(Ksign, digestmod='md5') temp.update(Sgn_Cksum) token.SGN_CKSUM = temp.digest()[:8] klocal = b'' for b in self.session_key.contents: klocal += bytes([b ^ 0xf0]) id = 0 temp = hmac.new(klocal, digestmod='md5') temp.update(id.to_bytes(4, 'little', signed=False)) temp = hmac.new(temp.digest(), digestmod='md5') temp.update(seq_num.to_bytes(4, 'big', signed=False)) Kcrypt = temp.digest() id = 0 temp = hmac.new(self.session_key.contents, digestmod='md5') temp.update(id.to_bytes(4, 'little', signed=False)) temp = hmac.new(temp.digest(), digestmod='md5') temp.update(token.SGN_CKSUM) Kseq = temp.digest() token.SND_SEQ = RC4(Kseq).encrypt(token.SND_SEQ) if auth_data is not None: wrap = GSSWRAP_RC4.from_bytes(auth_data[8 + len(GSS_WRAP_HEADER):]) id = 0 temp = hmac.new(self.session_key.contents, digestmod='md5') temp.update(id.to_bytes(4, 'little', signed=False)) temp = hmac.new(temp.digest(), digestmod='md5') temp.update(wrap.SGN_CKSUM) snd_seq = RC4(temp.digest()).encrypt(wrap.SND_SEQ) id = 0 temp = hmac.new(klocal, digestmod='md5') temp.update(id.to_bytes(4, 'little', signed=False)) temp = hmac.new(temp.digest(), digestmod='md5') temp.update(snd_seq[:4]) Kcrypt = temp.digest() rc4 = RC4(Kcrypt) cipherText = rc4.decrypt(token.Confounder + data)[8:] elif encrypt is True: rc4 = RC4(Kcrypt) token.Confounder = rc4.encrypt(token.Confounder) cipherText = rc4.encrypt(data) else: cipherText = data finalData = GSS_WRAP_HEADER + token.to_bytes() return cipherText, finalData
def GSS_Wrap(self, data, seq_num, direction='init', encrypt=True, cofounder=None): #direction = 'a' #seq_num = 0 #print('[GSS_Wrap] data: %s' % data) #print('[GSS_Wrap] seq_num: %s' % seq_num.to_bytes(4, 'big', signed = False).hex()) #print('[GSS_Wrap] direction: %s' % direction) #print('[GSS_Wrap] encrypt: %s' % encrypt) # #print('[GSS_Wrap] auth_data: %s' % auth_data) #pad = 0 if encrypt is True: data += b'\x01' #pad = (8 - (len(data) % 8)) & 0x7 #padStr = bytes([pad]) * pad #data += padStr # ##data += b'\x08' * 8 #print('[GSS_Wrap] pad: %s' % pad) #print('[GSS_Wrap] data padded: %s' % data) token = GSSWRAP_RC4() token.SEAL_ALG = b'\x10\x00' # RC4 if direction == 'init': token.SND_SEQ = seq_num.to_bytes(4, 'big', signed=False) + b'\x00' * 4 else: token.SND_SEQ = seq_num.to_bytes(4, 'big', signed=False) + b'\xff' * 4 token.Confounder = os.urandom(8) #if cofounder is not None: # token.Confounder = cofounder # #testing purposes only, pls remove temp = hmac.new(self.session_key.contents, digestmod='md5') temp.update(b'signaturekey\0') Ksign = temp.digest() id = 13 Sgn_Cksum = md5( id.to_bytes(4, 'little', signed=False) + token.to_bytes()[:8] + token.Confounder + data).digest() klocal = b'' for b in self.session_key.contents: klocal += bytes([b ^ 0xf0]) id = 0 temp = hmac.new(klocal, digestmod='md5') temp.update(id.to_bytes(4, 'little', signed=False)) temp = hmac.new(temp.digest(), digestmod='md5') temp.update(seq_num.to_bytes(4, 'big', signed=False)) Kcrypt = temp.digest() temp = hmac.new(Ksign, digestmod='md5') temp.update(Sgn_Cksum) token.SGN_CKSUM = temp.digest()[:8] id = 0 temp = hmac.new(self.session_key.contents, digestmod='md5') temp.update(id.to_bytes(4, 'little', signed=False)) temp = hmac.new(temp.digest(), digestmod='md5') temp.update(token.SGN_CKSUM) Kseq = temp.digest() token.SND_SEQ = RC4(Kseq).encrypt(token.SND_SEQ) #if auth_data is not None: if encrypt is False: #print('Unwrap sessionkey: %s' % self.session_key.contents.hex()) #print('Unwrap data : %s' % data.hex()) sspi_wrap = KRB5_MECH_INDEP_TOKEN.from_bytes(data) hdr = sspi_wrap.data[:32] data = sspi_wrap.data[32:] wrap = GSSWRAP_RC4.from_bytes(hdr) id = 0 temp = hmac.new(self.session_key.contents, digestmod='md5') temp.update(id.to_bytes(4, 'little', signed=False)) temp = hmac.new(temp.digest(), digestmod='md5') temp.update(wrap.SGN_CKSUM) Kseq = temp.digest() snd_seq = RC4(Kseq).encrypt(wrap.SND_SEQ) id = 0 temp = hmac.new(klocal, digestmod='md5') temp.update(id.to_bytes(4, 'little', signed=False)) temp = hmac.new(temp.digest(), digestmod='md5') temp.update(snd_seq[:4]) Kcrypt = temp.digest() rc4 = RC4(Kcrypt) dec_cofounder = rc4.decrypt(wrap.Confounder) dec_data = rc4.decrypt(data) id = 13 Sgn_Cksum_calc = md5( id.to_bytes(4, 'little', signed=False) + wrap.to_bytes()[:8] + dec_cofounder + dec_data).digest() temp = hmac.new(Ksign, digestmod='md5') temp.update(Sgn_Cksum_calc) Sgn_Cksum_calc = temp.digest()[:8] if wrap.SGN_CKSUM != Sgn_Cksum_calc[:8]: return None, Exception('Integrity verification failed') pad = 1 return dec_data[:-pad], None elif encrypt is True: rc4 = RC4(Kcrypt) token.Confounder = rc4.encrypt(token.Confounder) cipherText = rc4.encrypt(data) finalData, cipherText = KRB5_MECH_INDEP_TOKEN( token.to_bytes() + cipherText, '1.2.840.113554.1.2.2').to_bytes() #print('cipherText %s' % cipherText.hex()) #print('finalData %s' % finalData.hex()) #print('sessionkey %s' % self.session_key.contents.hex()) return cipherText, finalData
async def bind(self, iface_uuid, alter=0, bogus_binds=0, transfer_syntax=('8a885d04-1ceb-11c9-9fe8-08002b104860', '2.0')): """ Performs bind operation. Does authentication and sets up the keys for further communication """ try: bind = MSRPCBind() #item['TransferSyntax']['Version'] = 1 ctx = self.ctx for _ 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(transfer_syntax) bind.addCtxItem(item) self.ctx += 1 ctx += 1 # The true one :) item = CtxItem() item['AbstractSyntax'] = iface_uuid item['TransferSyntax'] = uuidtup_to_bin(transfer_syntax) item['ContextID'] = ctx item['TransItems'] = 1 bind.addCtxItem(item) packet = MSRPCHeader() packet['type'] = MSRPC_BIND packet['pduData'] = bind.getData() packet['call_id'] = self.callid if alter: packet['type'] = MSRPC_ALTERCTX if self.auth_level != RPC_C_AUTHN_LEVEL_NONE: #authentication required if self.auth_type == RPC_C_AUTHN_WINNT: #seal flag MUST be turned on in the handshake flags!!!!!!! #it is "signaled via the is_rpc variable" auth, res, err = await self.gssapi.ntlm.authenticate( None, is_rpc=True) if err is not None: return None, err elif self.auth_type == RPC_C_AUTHN_NETLOGON: return False, Exception( 'RPC_C_AUTHN_NETLOGON Not implemented!') elif self.auth_type == RPC_C_AUTHN_GSS_NEGOTIATE: auth, res, err = await self.gssapi.gssapi.authenticate( None, flags = GSSAPIFlags.GSS_C_CONF_FLAG |\ GSSAPIFlags.GSS_C_INTEG_FLAG | \ GSSAPIFlags.GSS_C_SEQUENCE_FLAG | \ GSSAPIFlags.GSS_C_REPLAY_FLAG | \ GSSAPIFlags.GSS_C_MUTUAL_FLAG | \ GSSAPIFlags.GSS_C_DCE_STYLE, seq_number = 0, is_rpc = True ) if err is not None: return None, err else: return None, Exception('Unsupported auth type!') 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'] += b'\xFF' * pad sec_trailer['auth_pad_len'] = pad packet['sec_trailer'] = sec_trailer packet['auth_data'] = auth _, err = await self.transport.send(packet.get_packet()) if err is not None: raise err data, err = await self.recv_one() if err is not None: raise err resp = MSRPCHeader(data) if resp['type'] == MSRPC_BINDACK or resp[ 'type'] == MSRPC_ALTERCTX_R: bindResp = MSRPCBindAck(resp.getData()) elif resp['type'] == MSRPC_BINDNAK or resp['type'] == MSRPC_FAULT: if resp['type'] == MSRPC_FAULT: resp = MSRPCRespHeader(resp.getData()) status_code = unpack('<L', resp['pduData'][:4])[0] else: resp = MSRPCBindNak(resp['pduData']) status_code = resp['RejectedReason'] if status_code in rpc_status_codes: return False, DCERPCException(error_code=status_code) elif status_code in rpc_provider_reason: return False, DCERPCException( "Bind context rejected: %s" % rpc_provider_reason[status_code]) else: return False, DCERPCException( 'Unknown DCE RPC fault status code: %.8x' % status_code) else: return False, DCERPCException( '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): ctxItems = bindResp.getCtxItem(ctx) if ctxItems['Result'] != 0: msg = "Bind context %d rejected: " % ctx msg += rpc_cont_def_result.get( ctxItems['Result'], 'Unknown DCE RPC context result code: %.4x' % ctxItems['Result']) msg += "; " reason = bindResp.getCtxItem(ctx)['Reason'] msg += rpc_provider_reason.get( reason, 'Unknown reason code: %.4x' % reason) if (ctxItems['Result'], reason) == ( 2, 1 ): # provider_rejection, abstract syntax not supported msg += " (this usually means the interface isn't listening on the given endpoint)" raise DCERPCException(msg) # Save the transfer syntax for later use self.transfer_syntax = ctxItems['TransferSyntax'] # The received transmit size becomes the client's receive size, and the received receive size becomes the client's transmit size. self.__max_xmit_size = bindResp['max_rfrag'] if self.auth_level != RPC_C_AUTHN_LEVEL_NONE: if self.auth_type == RPC_C_AUTHN_WINNT: response, res, err = await self.gssapi.ntlm.authenticate( bindResp['auth_data'], is_rpc=True) if err is not None: return None, err self.__sessionKey = self.gssapi.ntlm.get_session_key() elif self.auth_type == RPC_C_AUTHN_NETLOGON: response = None elif self.auth_type == RPC_C_AUTHN_GSS_NEGOTIATE: response, res, err = await self.gssapi.gssapi.authenticate( bindResp['auth_data'], is_rpc = True, flags = GSSAPIFlags.GSS_C_CONF_FLAG |\ GSSAPIFlags.GSS_C_INTEG_FLAG | \ GSSAPIFlags.GSS_C_SEQUENCE_FLAG | \ GSSAPIFlags.GSS_C_REPLAY_FLAG | \ GSSAPIFlags.GSS_C_MUTUAL_FLAG | \ GSSAPIFlags.GSS_C_DCE_STYLE ) if err is not None: return None, err self.__sessionKey = self.gssapi.gssapi.get_session_key() 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.gssapi.ntlm.is_extended_security() == True: self.__clientSigningKey = self.gssapi.ntlm.get_signkey( ) self.__serverSigningKey = self.gssapi.ntlm.get_signkey( 'Server') self.__clientSealingKey = self.gssapi.ntlm.get_sealkey( ) self.__serverSealingKey = self.gssapi.ntlm.get_sealkey( 'Server') cipher3 = RC4(self.__clientSealingKey) self.__clientSealingHandle = cipher3.encrypt cipher4 = RC4(self.__serverSealingKey) self.__serverSealingHandle = cipher4.encrypt else: # Same key for everything self.__clientSigningKey = self.gssapi.ntlm.get_session_key( ) self.__serverSigningKey = self.gssapi.ntlm.get_session_key( ) self.__clientSealingKey = self.gssapi.ntlm.get_session_key( ) self.__serverSealingKey = self.gssapi.ntlm.get_session_key( ) cipher = RC4(self.__clientSigningKey) self.__clientSealingHandle = cipher.encrypt self.__serverSealingHandle = cipher.encrypt elif self.auth_type == RPC_C_AUTHN_NETLOGON: raise Exception( 'RPC_C_AUTHN_NETLOGON is not implemented!') 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: if self.auth_type == RPC_C_AUTHN_GSS_NEGOTIATE: alter_ctx = MSRPCHeader() alter_ctx['type'] = MSRPC_ALTERCTX alter_ctx['pduData'] = bind.getData() alter_ctx['sec_trailer'] = sec_trailer alter_ctx['auth_data'] = response _, err = await self.transport.send( alter_ctx.get_packet(), forceWriteAndx=1) if err is not None: raise err self.__sequence = 0 data, err = await self.recv_one( ) #recieving the result of alter_context command if err is not None: raise err self.__sequence = self.gssapi.gssapi.selected_authentication_context.seq_number else: 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'] = b' ' * 4 #SkelSec: I have spent 3 hours to find this bug, that I caused by replacing spaces to tabs :( auth3['sec_trailer'] = sec_trailer #SkelSec auth3['auth_data'] = response.getData() auth3['auth_data'] = response # Use the same call_id self.callid = resp['call_id'] auth3['call_id'] = self.callid _, err = await self.transport.send(auth3.get_packet(), forceWriteAndx=1) if err is not None: raise err self.callid += 1 return resp, None # means packet is signed, if verifier is wrong it fails except Exception as e: return False, e