Skip to content

Commit

Permalink
ncchanges baby!
Browse files Browse the repository at this point in the history
  • Loading branch information
ShutdownRepo committed Mar 19, 2024
1 parent 41cbeb3 commit 9d321e9
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 42 deletions.
20 changes: 2 additions & 18 deletions impacket/krb5/crypto.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,6 @@
from Cryptodome.Util.number import GCD as gcd
from six import b, PY3, indexbytes, binary_type

from R2Log import logger
import hexdump


def get_random_bytes(lenBytes):
# We don't really need super strong randomness here to use PyCrypto.Random
return urandom(lenBytes)
Expand Down Expand Up @@ -226,13 +222,11 @@ def encrypt(cls, key, keyusage, plaintext, confounder, integrity_blob=None):
hmac = HMAC.new(ki.contents, integrity_blob, cls.hashmod).digest()
else:
hmac = HMAC.new(ki.contents, basic_plaintext, cls.hashmod).digest()
logger.info("full hmac in crypto encrypt")
hexdump.hexdump(hmac)
enc = cls.basic_encrypt(ke, basic_plaintext) + hmac[:cls.macsize]
return enc

@classmethod
def decrypt(cls, key, keyusage, ciphertext, ignore_integrity=False, dce_rpc_header=None, auth_data_header=None):
def decrypt(cls, key, keyusage, ciphertext, ignore_integrity=False, wrap_token_len=None, filler_len=None, dce_rpc_header=None, auth_data_header=None):
ki = cls.derive(key, pack('>IB', keyusage, 0x55))
ke = cls.derive(key, pack('>IB', keyusage, 0xAA))
if len(ciphertext) < cls.blocksize + cls.macsize:
Expand All @@ -248,21 +242,11 @@ def decrypt(cls, key, keyusage, ciphertext, ignore_integrity=False, dce_rpc_head
# = confounder + dce_rpc_header + data + auth_data_header + filler + wrap_token
# no need to implement, assuming the other client is legit
if dce_rpc_header is not None and auth_data_header is not None:
plaintext_data, plaintext_filler_and_wrap_token_header = plaintext[:-8-16], plaintext[-8-16:] # FIXME dynamically set the filler size
plaintext_data, plaintext_filler_and_wrap_token_header = plaintext[:-filler_len-wrap_token_len], plaintext[-filler_len-wrap_token_len:] # FIXME dynamically set the filler size
integrity_blob = confounder + dce_rpc_header + plaintext_data + auth_data_header + plaintext_filler_and_wrap_token_header
logger.info("integrity blob in crypto decrypt")
hexdump.hexdump(confounder)
hexdump.hexdump(dce_rpc_header)
hexdump.hexdump(plaintext_data)
hexdump.hexdump(auth_data_header)
hexdump.hexdump(plaintext_filler_and_wrap_token_header)
hmac = bytearray(HMAC.new(ki.contents, integrity_blob, SHA).digest())
logger.info("HMAC calculated")
hexdump.hexdump(hmac)
else:
hmac = bytearray(HMAC.new(ki.contents, basic_plaintext, SHA).digest())
logger.info("HMAC from packet")
hexdump.hexdump(mac)
expmac = hmac[:cls.macsize]
if not _mac_equal(mac, expmac) and not ignore_integrity:
raise InvalidChecksum('ciphertext integrity failure')
Expand Down
47 changes: 23 additions & 24 deletions impacket/krb5/gssapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@
import struct
import random
import string
import hexdump
from R2Log import logger

from six import b

Expand Down Expand Up @@ -249,32 +247,35 @@ def unrotate(self, data, numBytes):
numBytes %= len(data)
result = data[numBytes:] + data[:numBytes]
return result

def get_filler(self, data):
cipher = self.cipherType()
length = (cipher.blocksize - (len(data) % cipher.blocksize)) or 16
filler = b'\x00' * length
return filler


def GSS_Wrap(self, sessionKey, data, sequenceNumber, direction='init', encrypt=True, keyUsage=KG_USAGE_INITIATOR_SEAL, confounder=None, padding=None, dce_rpc_header=None, auth_data_header=None):
def GSS_Wrap(self, sessionKey, data, sequenceNumber, direction='init', encrypt=True, acceptorSubkey=False, keyUsage=KG_USAGE_INITIATOR_SEAL, confounder=None, dce_rpc_header=None, auth_data_header=None):
token = self.WRAP()

cipher = self.cipherType()

if confounder is None:
confounder = b(''.join([rand.choice(string.ascii_letters) for _ in range(16)]))

if padding:
padStr = padding
pad = len(padding)
else:
#Let's pad the data
pad = (cipher.blocksize - (len(data) % cipher.blocksize)) & 16
padStr = b'\x00' * pad

# 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'] = 0
if acceptorSubkey:
token['Flags'] |= 4 # AcceptorSubKey flag (0x00100)
if encrypt:
token['Flags'] |= 2 # Sealed flag (0x00010)
if direction != 'init':
token['Flags'] = 3
else:
token['Flags'] = 2
token['EC'] = pad
token['Flags'] |= 1 # SendByAcceptor flag (0x00001)

token['EC'] = len(self.get_filler(data))
# (RFC4121 section 4.2.4) the RRC field (as
# defined in section 4.2.5) in the to-be-encrypted header contains the
# hex value 00 00.
Expand All @@ -285,15 +286,9 @@ def GSS_Wrap(self, sessionKey, data, sequenceNumber, direction='init', encrypt=T
# This is undocumented, and was identified by reversing cryptodll.dll
integrity_blob = None
if dce_rpc_header is not None and auth_data_header is not None:
integrity_blob = confounder + dce_rpc_header + data + auth_data_header + padStr + token.getData()
logger.info("integrity blob in gssapi wrap")
hexdump.hexdump(confounder)
hexdump.hexdump(dce_rpc_header)
hexdump.hexdump(data)
hexdump.hexdump(auth_data_header)
hexdump.hexdump(padStr + token.getData())
integrity_blob = confounder + dce_rpc_header + data + auth_data_header + self.get_filler(data) + token.getData()

data += padStr
data += self.get_filler(data)

cipherText = cipher.encrypt(key=sessionKey, keyusage=keyUsage, plaintext=data + token.getData(), confounder=confounder, integrity_blob=integrity_blob)
token['RRC'] = rrc
Expand Down Expand Up @@ -321,7 +316,11 @@ def GSS_Unwrap(self, sessionKey, data, sequenceNumber, direction='init', encrypt
# For Kerberos SSP: blob for HMAC calculation is different from blob for encryption.
# This is undocumented, and was identified by reversing cryptodll.dll
# no need to implement, assuming the other client is legit
plainText, confounder = cipher.decrypt(sessionKey, keyUsage, cipherText, dce_rpc_header=dce_rpc_header, auth_data_header=auth_data_header, ignore_integrity=ignore_integrity)
plainText, confounder = cipher.decrypt(
sessionKey, keyUsage, cipherText,
dce_rpc_header=dce_rpc_header, auth_data_header=auth_data_header, ignore_integrity=ignore_integrity,
wrap_token_len=len(self.WRAP()), filler_len=token['EC']
)

encdata, enchdr = plainText[:-len(self.WRAP())], plainText[-len(self.WRAP()):]
encdata, filler = encdata[:-token['EC']], encdata[-token['EC']:]
Expand Down

0 comments on commit 9d321e9

Please sign in to comment.