Add support for salted mac generation, fix issue 17

This commit is contained in:
speyrefitte
2015-02-10 11:39:26 +01:00
parent 9e50c2292d
commit a01eb57cef
2 changed files with 77 additions and 17 deletions

View File

@@ -179,6 +179,9 @@ class Client(PDULayer):
for cap in pdu.pduMessage.capabilitySets._array:
self._serverCapabilities[cap.capabilitySetType] = cap
#secure checksum cap here maybe protocol (another) design error
self._transport._enableSecureCheckSum = bool(self._serverCapabilities[caps.CapsType.CAPSTYPE_GENERAL].capability.extraFlags & caps.GeneralExtraFlag.ENC_SALTED_CHECKSUM)
self.sendConfirmActivePDU()
#send synchronize
@@ -312,7 +315,7 @@ class Client(PDULayer):
generalCapability = self._clientCapabilities[caps.CapsType.CAPSTYPE_GENERAL].capability
generalCapability.osMajorType.value = caps.MajorType.OSMAJORTYPE_WINDOWS
generalCapability.osMinorType.value = caps.MinorType.OSMINORTYPE_WINDOWS_NT
generalCapability.extraFlags.value = caps.GeneralExtraFlag.LONG_CREDENTIALS_SUPPORTED | caps.GeneralExtraFlag.NO_BITMAP_COMPRESSION_HDR
generalCapability.extraFlags.value = caps.GeneralExtraFlag.LONG_CREDENTIALS_SUPPORTED | caps.GeneralExtraFlag.NO_BITMAP_COMPRESSION_HDR | caps.GeneralExtraFlag.ENC_SALTED_CHECKSUM
if not self._fastPathSender is None:
generalCapability.extraFlags.value |= caps.GeneralExtraFlag.FASTPATH_OUTPUT_SUPPORTED
@@ -413,6 +416,9 @@ class Server(PDULayer):
#find use full flag
self._clientFastPathSupported = bool(self._clientCapabilities[caps.CapsType.CAPSTYPE_GENERAL].capability.extraFlags.value & caps.GeneralExtraFlag.FASTPATH_OUTPUT_SUPPORTED)
#secure checksum cap here maybe protocol (another) design error
self._transport._enableSecureCheckSum = bool(self._clientCapabilities[caps.CapsType.CAPSTYPE_GENERAL].capability.extraFlags & caps.GeneralExtraFlag.ENC_SALTED_CHECKSUM)
self.setNextState(self.recvClientSynchronizePDU)
def recvClientSynchronizePDU(self, s):
@@ -525,7 +531,7 @@ class Server(PDULayer):
generalCapability = self._serverCapabilities[caps.CapsType.CAPSTYPE_GENERAL].capability
generalCapability.osMajorType.value = caps.MajorType.OSMAJORTYPE_WINDOWS
generalCapability.osMinorType.value = caps.MinorType.OSMINORTYPE_WINDOWS_NT
generalCapability.extraFlags.value = caps.GeneralExtraFlag.LONG_CREDENTIALS_SUPPORTED | caps.GeneralExtraFlag.NO_BITMAP_COMPRESSION_HDR | caps.GeneralExtraFlag.FASTPATH_OUTPUT_SUPPORTED
generalCapability.extraFlags.value = caps.GeneralExtraFlag.LONG_CREDENTIALS_SUPPORTED | caps.GeneralExtraFlag.NO_BITMAP_COMPRESSION_HDR | caps.GeneralExtraFlag.FASTPATH_OUTPUT_SUPPORTED | caps.GeneralExtraFlag.ENC_SALTED_CHECKSUM
inputCapability = self._serverCapabilities[caps.CapsType.CAPSTYPE_INPUT].capability
inputCapability.inputFlags.value = caps.InputFlags.INPUT_FLAG_SCANCODES | caps.InputFlags.INPUT_FLAG_MOUSEX

View File

@@ -164,12 +164,12 @@ def macData(macSaltKey, data):
md5Digest = md5.new()
#encode length
s = Stream()
s.writeType(UInt32Le(len(data)))
dataLength = Stream()
dataLength.writeType(UInt32Le(len(data)))
sha1Digest.update(macSaltKey)
sha1Digest.update("\x36" * 40)
sha1Digest.update(s.getvalue())
sha1Digest.update(dataLength.getvalue())
sha1Digest.update(data)
sha1Sig = sha1Digest.digest()
@@ -180,6 +180,38 @@ def macData(macSaltKey, data):
return md5Digest.digest()
def macSaltedData(macSaltKey, data, encryptionCount):
"""
@see: https://msdn.microsoft.com/en-us/library/cc240789.aspx
@param macSaltKey: {str} mac key
@param data: {str} data to sign
@param encryptionCount: nb encrypted packet
@return: {str} signature
"""
sha1Digest = sha.new()
md5Digest = md5.new()
#encode length
dataLengthS = Stream()
dataLengthS.writeType(UInt32Le(len(data)))
encryptionCountS = Stream()
encryptionCountS.writeType(UInt32Le(encryptionCount))
sha1Digest.update(macSaltKey)
sha1Digest.update("\x36" * 40)
sha1Digest.update(dataLengthS.getvalue())
sha1Digest.update(data)
sha1Digest.update(encryptionCountS.getvalue())
sha1Sig = sha1Digest.digest()
md5Digest.update(macSaltKey)
md5Digest.update("\x5c" * 48)
md5Digest.update(sha1Sig)
return md5Digest.digest()
def tempKey(initialKey, currentKey):
"""
@see: http://msdn.microsoft.com/en-us/library/cc240792.aspx
@@ -342,6 +374,9 @@ class SecLayer(LayerAutomata, IStreamSender, tpkt.IFastPathListener, tpkt.IFastP
#True if classic encryption is enable
self._enableEncryption = False
#Enable Secure Mac generation
self._enableSecureCheckSum = False
#initialise decrypt and encrypt keys
self._macKey = None
self._initialDecrytKey = None
@@ -358,10 +393,11 @@ class SecLayer(LayerAutomata, IStreamSender, tpkt.IFastPathListener, tpkt.IFastP
self._encryptRc4 = None
def readEncryptedPayload(self, s):
def readEncryptedPayload(self, s, saltedMacGeneration):
"""
@summary: decrypt basic RDP security payload
@param s: {Stream} encrypted stream
@param saltedMacGeneration: {bool} use salted mac generation
@return: {Stream} decrypted
"""
#if update is needed
@@ -378,18 +414,22 @@ class SecLayer(LayerAutomata, IStreamSender, tpkt.IFastPathListener, tpkt.IFastP
decrypted = rc4.crypt(self._decryptRc4, encryptedPayload.value)
#ckeck signature
if macData(self._macKey, decrypted)[:8] != signature.value:
raise InvalidExpectedDataException("Bad packet signature")
if not saltedMacGeneration and macData(self._macKey, decrypted)[:8] != signature.value:
raise InvalidExpectedDataException("bad signature")
if saltedMacGeneration and macSaltedData(self._macKey, decrypted, self._nbDecryptedPacket)[:8] != signature.value:
raise InvalidExpectedDataException("bad signature")
#count
self._nbDecryptedPacket += 1
return Stream(decrypted)
def writeEncryptedPayload(self, data):
def writeEncryptedPayload(self, data, saltedMacGeneration):
"""
@summary: sign and crypt data
@param s: {Stream} raw stream
@param data: {Type} raw stream
@param saltedMacGeneration: {bool} use salted mac generation
@return: {Tuple} (signature, encryptedData)
"""
if self._nbEncryptedPacket == 4096:
@@ -400,9 +440,14 @@ class SecLayer(LayerAutomata, IStreamSender, tpkt.IFastPathListener, tpkt.IFastP
self._nbEncryptedPacket = 0
self._nbEncryptedPacket += 1
s = Stream()
s.writeType(data)
return (String(macData(self._macKey, s.getvalue())[:8]), String(rc4.crypt(self._encryptRc4, s.getvalue())))
if saltedMacGeneration:
return (String(macSaltedData(self._macKey, s.getvalue(), self._nbEncryptedPacket - 1)[:8]), String(rc4.crypt(self._encryptRc4, s.getvalue())))
else:
return (String(macData(self._macKey, s.getvalue())[:8]), String(rc4.crypt(self._encryptRc4, s.getvalue())))
def recv(self, data):
"""
@@ -419,7 +464,7 @@ class SecLayer(LayerAutomata, IStreamSender, tpkt.IFastPathListener, tpkt.IFastP
data.readType((securityFlag, securityFlagHi))
if securityFlag.value & SecurityFlag.SEC_ENCRYPT:
data = self.readEncryptedPayload(data)
data = self.readEncryptedPayload(data, securityFlag.value & SecurityFlag.SEC_SECURE_CHECKSUM)
self._presentation.recv(data)
@@ -433,7 +478,12 @@ class SecLayer(LayerAutomata, IStreamSender, tpkt.IFastPathListener, tpkt.IFastP
self._transport.send(data)
return
self.sendFlagged(SecurityFlag.SEC_ENCRYPT, data)
flag = SecurityFlag.SEC_ENCRYPT
if self._enableSecureCheckSum:
flag |= SecurityFlag.SEC_SECURE_CHECKSUM
self.sendFlagged(flag, data)
def sendFlagged(self, flag, data):
"""
@@ -444,7 +494,7 @@ class SecLayer(LayerAutomata, IStreamSender, tpkt.IFastPathListener, tpkt.IFastP
@param data: {Type | Tuple}
"""
if flag & SecurityFlag.SEC_ENCRYPT:
data = self.writeEncryptedPayload(data)
data = self.writeEncryptedPayload(data, flag & SecurityFlag.SEC_SECURE_CHECKSUM)
self._transport.send((UInt16Le(flag), UInt16Le(), data))
def recvFastPath(self, secFlag, fastPathS):
@@ -454,7 +504,7 @@ class SecLayer(LayerAutomata, IStreamSender, tpkt.IFastPathListener, tpkt.IFastP
@param fastPathS: {Stream}
"""
if self._enableEncryption and secFlag & tpkt.SecFlags.FASTPATH_OUTPUT_ENCRYPTED:
fastPathS = self.readEncryptedPayload(fastPathS)
fastPathS = self.readEncryptedPayload(fastPathS, secFlag & tpkt.SecFlags.FASTPATH_OUTPUT_SECURE_CHECKSUM)
self._fastPathPresentation.recvFastPath(secFlag, fastPathS)
@@ -472,7 +522,11 @@ class SecLayer(LayerAutomata, IStreamSender, tpkt.IFastPathListener, tpkt.IFastP
"""
if self._enableEncryption:
secFlag |= tpkt.SecFlags.FASTPATH_OUTPUT_ENCRYPTED
fastPathS = self.writeEncryptedPayload(fastPathS)
if self._enableSecureCheckSum:
secFlag |= tpkt.SecFlags.FASTPATH_OUTPUT_SECURE_CHECKSUM
fastPathS = self.writeEncryptedPayload(fastPathS, self._enableSecureCheckSum)
self._fastPathTransport.sendFastPath(secFlag, fastPathS)
@@ -661,7 +715,7 @@ class Server(SecLayer):
raise InvalidExpectedDataException("Waiting info packet")
if securityFlag.value & SecurityFlag.SEC_ENCRYPT:
s = self.readEncryptedPayload(s)
s = self.readEncryptedPayload(s, securityFlag.value & SecurityFlag.SEC_SECURE_CHECKSUM)
s.readType(self._info)
#next state send error license