From 30cf5419d5a811d1d9294d48f1ec91723089fda4 Mon Sep 17 00:00:00 2001 From: MrAle98 Date: Thu, 29 Feb 2024 23:31:14 +0100 Subject: [PATCH] test.py now has a working example. Take encrypted DsBindResponse from dcshadow wireshark decrypt it, and produces again same encrypted stuff with same signature by taking the padding bytes and the confounder from the encrypted message --- impacket/krb5/crypto.py | 9 ++++++++- impacket/krb5/gssapi.py | 14 ++++++++++---- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/impacket/krb5/crypto.py b/impacket/krb5/crypto.py index 744355c62..bd4605633 100644 --- a/impacket/krb5/crypto.py +++ b/impacket/krb5/crypto.py @@ -221,11 +221,13 @@ def encrypt(cls, key, keyusage, plaintext, confounder): print(f"confounder len={len(confounder)}") hexdump.hexdump(confounder) print(f"cls.padsize = {cls.padsize}") + print(f"cls.macsize = {cls.macsize}") basic_plaintext = confounder + _zeropad(plaintext, cls.padsize) print(f"basic_plaintext len={len(basic_plaintext)}") hexdump.hexdump(basic_plaintext) hmac = HMAC.new(ki.contents, basic_plaintext, cls.hashmod).digest() print(f"hmac len={len(hmac)}") + hexdump.hexdump(hmac) enc = cls.basic_encrypt(ke, basic_plaintext) + hmac[:cls.macsize] print("returning from encrypt") return enc @@ -237,7 +239,12 @@ def decrypt(cls, key, keyusage, ciphertext): print("in decrypt") print(f"ciphertext len={len(ciphertext)}") - hexdump.hexdump(ciphertext) + dumpciphertext = None + if type(ciphertext) != type(bytearray) and type(ciphertext) != type(bytes): + dumpciphertext = bytes(ciphertext) + else: + dumpciphertext = ciphertext + hexdump.hexdump(dumpciphertext) if len(ciphertext) < cls.blocksize + cls.macsize: raise ValueError('ciphertext too short') diff --git a/impacket/krb5/gssapi.py b/impacket/krb5/gssapi.py index d3caf8441..7c907e716 100644 --- a/impacket/krb5/gssapi.py +++ b/impacket/krb5/gssapi.py @@ -253,13 +253,16 @@ def GSS_Wrap(self, sessionKey, data, sequenceNumber, direction = 'init', encrypt token = self.WRAP() print("in GSS_Wrap") cipher = self.cipherType() + print(f"data len={len(data)}") + if padding: - pad = len(padding) padStr = padding + pad = len(padding) data += padStr + else: #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 @@ -267,7 +270,7 @@ def GSS_Wrap(self, sessionKey, data, sequenceNumber, direction = 'init', encrypt print(f"cipher.blocksize: {cipher.blocksize}") print(f"len(data) % cipher.blocksize): {len(data) % cipher.blocksize}") print(f"padding") - hexdump.hexdump(padding) + hexdump.hexdump(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 @@ -285,7 +288,7 @@ def GSS_Wrap(self, sessionKey, data, sequenceNumber, direction = 'init', encrypt hexdump.hexdump(data) cipherText = cipher.encrypt(sessionKey, keyUsage, data + token.getData(), confounder) print(f"cipherText len={len(cipherText)}") - + hexdump.hexdump(cipherText) token['RRC'] = rrc cipherText = self.rotate(cipherText, token['RRC'] + token['EC']) @@ -316,6 +319,9 @@ def GSS_Unwrap(self, sessionKey, data, sequenceNumber, direction = 'init', encry print("again in GSS_Unwrap") print(f"plaintText before unpadding {len(plainText)}") hexdump.hexdump(plainText) + signedtoken = self.WRAP(plainText[-16:]) + print(signedtoken.fields) + print(f"SND_SEQ: {int.from_bytes(signedtoken['SND_SEQ'])}") print(f"final plainText after unpadding {len(plainText[:-(token['EC']+len(self.WRAP()))])}") hexdump.hexdump(plainText[:-(token['EC']+len(self.WRAP()))])