From 1b102e5d6d133daa88a09149583672f5e3f085cd Mon Sep 17 00:00:00 2001 From: MrAle98 Date: Fri, 23 Feb 2024 23:54:20 +0100 Subject: [PATCH] added testing stuff --- impacket/krb5/crypto.py | 23 +++++++++++++++++++++-- impacket/krb5/gssapi.py | 28 ++++++++++++++++++---------- impacket/krb5/kerberosv5.py | 6 +++--- 3 files changed, 42 insertions(+), 15 deletions(-) diff --git a/impacket/krb5/crypto.py b/impacket/krb5/crypto.py index 673554bf9..d428cd83c 100644 --- a/impacket/krb5/crypto.py +++ b/impacket/krb5/crypto.py @@ -228,13 +228,32 @@ def decrypt(cls, key, keyusage, ciphertext): basic_ctext, mac = bytearray(ciphertext[:-cls.macsize]), bytearray(ciphertext[-cls.macsize:]) if len(basic_ctext) % cls.padsize != 0: raise ValueError('ciphertext does not meet padding requirement') + print(len(basic_ctext)) + for i in basic_ctext: + print(f"{hex(i)},", end="") + print("") + print(len(mac)) + for i in mac: + print(f"{hex(i)},", end="") + print("") + print(len(ciphertext)) + for i in ciphertext: + print(f"{hex(i)},", end="") basic_plaintext = cls.basic_decrypt(ke, bytes(basic_ctext)) + tmp = basic_plaintext[cls.blocksize:] + padding = tmp[-16-16:-16] + basic_plaintext = basic_plaintext.replace(padding,b"\xff"*len(padding)) hmac = bytearray(HMAC.new(ki.contents, basic_plaintext, cls.hashmod).digest()) expmac = hmac[:cls.macsize] + print(hmac) + print(expmac) + print(mac) if not _mac_equal(mac, expmac): - raise InvalidChecksum('ciphertext integrity failure') + print('ciphertext integrity failure') + else: + print('ciphertext integrity correct') # Discard the confounder. - return bytes(basic_plaintext[cls.blocksize:]) + return bytes(basic_plaintext[cls.blocksize:]),bytes(basic_plaintext[:cls.blocksize]) @classmethod def prf(cls, key, string): diff --git a/impacket/krb5/gssapi.py b/impacket/krb5/gssapi.py index f30060acf..9b63296ca 100644 --- a/impacket/krb5/gssapi.py +++ b/impacket/krb5/gssapi.py @@ -226,7 +226,7 @@ def GSS_GetMIC(self, sessionKey, data, sequenceNumber, direction = 'init'): # Let's pad the data pad = (4 - (len(data) % 4)) & 0x3 padStr = chr(pad) * pad - data += padStr + data += padStr.encode() checkSumProfile = self.checkSumProfile() @@ -247,26 +247,28 @@ def unrotate(self, data, numBytes): result = data[numBytes:] + data[:numBytes] return result - def GSS_Wrap(self, sessionKey, data, sequenceNumber, direction = 'init', encrypt=True): + def GSS_Wrap(self, sessionKey, data, sequenceNumber, direction = 'init', encrypt=True,keyUsage=KG_USAGE_INITIATOR_SEAL,confounder=None): token = self.WRAP() cipher = self.cipherType() # Let's pad the data - pad = (cipher.blocksize - (len(data) % cipher.blocksize)) & 15 + pad = (cipher.blocksize - (len(data) % cipher.blocksize)) & 16 padStr = b'\xFF' * pad data += padStr # The RRC field ([RFC4121] section 4.2.5) is 12 if no encryption is requested or 28 if encryption # is requested. The RRC field is chosen such that all the data can be encrypted in place. rrc = 28 - - token['Flags'] = 6 + if direction != 'init': + token['Flags'] = 7 + else: + token['Flags'] = 6 token['EC'] = pad token['RRC'] = 0 token['SND_SEQ'] = struct.pack('>Q',sequenceNumber) - cipherText = cipher.encrypt(sessionKey, KG_USAGE_INITIATOR_SEAL, data + token.getData(), None) + cipherText = cipher.encrypt(sessionKey, keyUsage, data + token.getData(), confounder) token['RRC'] = rrc cipherText = self.rotate(cipherText, token['RRC'] + token['EC']) @@ -277,18 +279,24 @@ def GSS_Wrap(self, sessionKey, data, sequenceNumber, direction = 'init', encrypt return ret1, ret2 - def GSS_Unwrap(self, sessionKey, data, sequenceNumber, direction = 'init', encrypt=True, authData=None): + def GSS_Unwrap(self, sessionKey, data, sequenceNumber, direction = 'init', encrypt=True, authData=None,keyUsage=KG_USAGE_ACCEPTOR_SEAL): from impacket.dcerpc.v5.rpcrt import SEC_TRAILER cipher = self.cipherType() token = self.WRAP(authData[len(SEC_TRAILER()):]) rotated = authData[len(self.WRAP())+len(SEC_TRAILER()):] + data - + cipherText = self.unrotate(rotated, token['RRC'] + token['EC']) - plainText = cipher.decrypt(sessionKey, KG_USAGE_ACCEPTOR_SEAL, cipherText) - return plainText[:-(token['EC']+len(self.WRAP()))], None + # rotated = authData[len(self.WRAP())+len(SEC_TRAILER()):] + # cipherText = data + self.unrotate(rotated, token['RRC'] + token['EC']) + print(f"\ncipherText len={len(cipherText)}") + for i in cipherText: + print(f"{hex(i)},", end="") + plainText, confounder = cipher.decrypt(sessionKey, keyUsage, cipherText) + + return plainText[:-(token['EC']+len(self.WRAP()))], confounder class GSSAPI_AES256(GSSAPI_AES): checkSumProfile = crypto._SHA1AES256 diff --git a/impacket/krb5/kerberosv5.py b/impacket/krb5/kerberosv5.py index d81af8590..c2e22a908 100644 --- a/impacket/krb5/kerberosv5.py +++ b/impacket/krb5/kerberosv5.py @@ -189,7 +189,7 @@ def getKerberosTGT(clientName, password, domain, lmhash, nthash, aesKey='', kdcH except KerberosError as e: if e.getErrorCode() == constants.ErrorCodes.KDC_ERR_ETYPE_NOSUPP.value: if supportedCiphers[0] in (constants.EncryptionTypes.aes128_cts_hmac_sha1_96.value, constants.EncryptionTypes.aes256_cts_hmac_sha1_96.value) and aesKey == b'': - supportedCiphers = (int(constants.EncryptionTypes.rc4_hmac.value),) + supportedCiphers = (int(constants.EncryptionTypes.aes256_cts_hmac_sha1_96.value),) seq_set_iter(reqBody, 'etype', supportedCiphers) message = encoder.encode(asReq) r = sendReceive(message, domain, kdcHost) @@ -439,10 +439,10 @@ def getKerberosTGS(serverName, domain, kdcHost, tgt, cipher, sessionKey): reqBody['nonce'] = rand.getrandbits(31) seq_set_iter(reqBody, 'etype', ( + int(cipher.enctype), int(constants.EncryptionTypes.rc4_hmac.value), int(constants.EncryptionTypes.des3_cbc_sha1_kd.value), - int(constants.EncryptionTypes.des_cbc_md5.value), - int(cipher.enctype) + int(constants.EncryptionTypes.des_cbc_md5.value) ) )