From 1039e014c1ef5e9a924ac96fa5849f03dd454b01 Mon Sep 17 00:00:00 2001 From: citronneur Date: Wed, 4 Feb 2015 21:04:58 +0100 Subject: [PATCH 1/9] fix issue 14 --- rdpy/protocol/rdp/gcc.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rdpy/protocol/rdp/gcc.py b/rdpy/protocol/rdp/gcc.py index 6bbae3f..942c41b 100644 --- a/rdpy/protocol/rdp/gcc.py +++ b/rdpy/protocol/rdp/gcc.py @@ -278,7 +278,8 @@ class ServerCoreData(CompositeType): def __init__(self, readLen = None): CompositeType.__init__(self, readLen = readLen) self.rdpVersion = UInt32Le(Version.RDP_VERSION_5_PLUS) - self.clientRequestedProtocol = UInt32Le() + self.clientRequestedProtocol = UInt32Le(optional = True) + self.earlyCapabilityFlags = UInt32Le(optional = True) class ClientSecurityData(CompositeType): """ From 4c56f55266f874e9818c05d979a01c9b08290a39 Mon Sep 17 00:00:00 2001 From: citronneur Date: Wed, 4 Feb 2015 21:47:32 +0100 Subject: [PATCH 2/9] fix issue 14 --- rdpy/core/type.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/rdpy/core/type.py b/rdpy/core/type.py index 8090814..9e2ea9f 100644 --- a/rdpy/core/type.py +++ b/rdpy/core/type.py @@ -498,6 +498,9 @@ class CompositeType(Type): @summary: Call sizeof on each sub type @return: sum of sizeof of each Type attributes """ + if not self._readLen is None: + return self._readLen.value + size = 0 for name in self._typeName: size += sizeof(self.__dict__[name]) From a8ddaa77ffa681a1240847994f79e2a2899aaee5 Mon Sep 17 00:00:00 2001 From: speyrefitte Date: Thu, 5 Feb 2015 16:06:06 +0100 Subject: [PATCH 3/9] fix issue 14 on xp sp3 + server side effect for honeypot --- rdpy/core/type.py | 4 ++-- rdpy/protocol/rdp/lic.py | 28 ++++++++++++++-------------- rdpy/protocol/rdp/pdu/data.py | 7 +++++-- 3 files changed, 21 insertions(+), 18 deletions(-) diff --git a/rdpy/core/type.py b/rdpy/core/type.py index 9e2ea9f..deff9e1 100644 --- a/rdpy/core/type.py +++ b/rdpy/core/type.py @@ -257,7 +257,7 @@ class SimpleType(Type, CallableValue): @raise InvalidSize: if there is not enough data in stream """ if s.dataLen() < self._typeSize: - raise InvalidSize("Stream is too small to read expected Simple") + raise InvalidSize("Stream is too small to read expected SimpleType") self.value = struct.unpack(self._structFormat, s.read(self._typeSize))[0] def mask(self): @@ -498,7 +498,7 @@ class CompositeType(Type): @summary: Call sizeof on each sub type @return: sum of sizeof of each Type attributes """ - if not self._readLen is None: + if self._is_readed and not self._readLen is None: return self._readLen.value size = 0 diff --git a/rdpy/protocol/rdp/lic.py b/rdpy/protocol/rdp/lic.py index 44aac63..7d6e70f 100644 --- a/rdpy/protocol/rdp/lic.py +++ b/rdpy/protocol/rdp/lic.py @@ -97,8 +97,8 @@ class LicenseBinaryBlob(CompositeType): @summary: Blob use by license manager to exchange security data @see: http://msdn.microsoft.com/en-us/library/cc240481.aspx """ - def __init__(self, blobType = BinaryBlobType.BB_ANY_BLOB): - CompositeType.__init__(self) + def __init__(self, blobType = BinaryBlobType.BB_ANY_BLOB, optional = False): + CompositeType.__init__(self, optional = optional) self.wBlobType = UInt16Le(blobType, constant = True if blobType != BinaryBlobType.BB_ANY_BLOB else False) self.wBlobLen = UInt16Le(lambda:sizeof(self.blobData)) self.blobData = String(readLen = self.wBlobLen) @@ -110,11 +110,11 @@ class LicensingErrorMessage(CompositeType): """ _MESSAGE_TYPE_ = MessageType.ERROR_ALERT - def __init__(self): - CompositeType.__init__(self) + def __init__(self, readLen = None): + CompositeType.__init__(self, readLen = readLen) self.dwErrorCode = UInt32Le() self.dwStateTransition = UInt32Le() - self.blob = LicenseBinaryBlob(BinaryBlobType.BB_ERROR_BLOB) + self.blob = LicenseBinaryBlob(BinaryBlobType.BB_ANY_BLOB) class ProductInformation(CompositeType): """ @@ -159,8 +159,8 @@ class ServerLicenseRequest(CompositeType): """ _MESSAGE_TYPE_ = MessageType.LICENSE_REQUEST - def __init__(self): - CompositeType.__init__(self) + def __init__(self, readLen = None): + CompositeType.__init__(self, readLen = readLen) self.serverRandom = String("\x00" * 32, readLen = UInt8(32)) self.productInfo = ProductInformation() self.keyExchangeList = LicenseBinaryBlob(BinaryBlobType.BB_KEY_EXCHG_ALG_BLOB) @@ -175,8 +175,8 @@ class ClientNewLicenseRequest(CompositeType): """ _MESSAGE_TYPE_ = MessageType.NEW_LICENSE_REQUEST - def __init__(self): - CompositeType.__init__(self) + def __init__(self, readLen = None): + CompositeType.__init__(self, readLen = readLen) #RSA and must be only RSA self.preferredKeyExchangeAlg = UInt32Le(0x00000001, constant = True) #pure microsoft client ;-) @@ -194,8 +194,8 @@ class ServerPlatformChallenge(CompositeType): """ _MESSAGE_TYPE_ = MessageType.PLATFORM_CHALLENGE - def __init__(self): - CompositeType.__init__(self) + def __init__(self, readLen = None): + CompositeType.__init__(self, readLen = readLen) self.connectFlags = UInt32Le() self.encryptedPlatformChallenge = LicenseBinaryBlob(BinaryBlobType.BB_ANY_BLOB) self.MACData = String(readLen = UInt8(16)) @@ -207,8 +207,8 @@ class ClientPLatformChallengeResponse(CompositeType): """ _MESSAGE_TYPE_ = MessageType.PLATFORM_CHALLENGE_RESPONSE - def __init__(self): - CompositeType.__init__(self) + def __init__(self, readLen = None): + CompositeType.__init__(self, readLen = readLen) self.encryptedPlatformChallengeResponse = LicenseBinaryBlob(BinaryBlobType.BB_DATA_BLOB) self.encryptedHWID = LicenseBinaryBlob(BinaryBlobType.BB_DATA_BLOB) self.MACData = String(readLen = UInt8(16)) @@ -231,7 +231,7 @@ class LicPacket(CompositeType): """ for c in [LicensingErrorMessage, ServerLicenseRequest, ClientNewLicenseRequest, ServerPlatformChallenge, ClientPLatformChallengeResponse]: if self.bMsgtype.value == c._MESSAGE_TYPE_: - return c() + return c(readLen = self.wMsgSize - 4) log.debug("unknown license message : %s"%self.bMsgtype.value) return String() diff --git a/rdpy/protocol/rdp/pdu/data.py b/rdpy/protocol/rdp/pdu/data.py index 885941d..81765c9 100644 --- a/rdpy/protocol/rdp/pdu/data.py +++ b/rdpy/protocol/rdp/pdu/data.py @@ -429,7 +429,8 @@ class ShareControlHeader(CompositeType): #share control header self.totalLength = UInt16Le(totalLength) self.pduType = UInt16Le(pduType) - self.PDUSource = UInt16Le(userId) + #for xp sp3 and deactiveallpdu PDUSource may not be present + self.PDUSource = UInt16Le(userId, optional = True) class ShareDataHeader(CompositeType): """ @@ -519,7 +520,9 @@ class DeactiveAllPDU(CompositeType): _PDUTYPE_ = PDUType.PDUTYPE_DEACTIVATEALLPDU def __init__(self): - CompositeType.__init__(self) + #in old version this packet is empty i don't know + #and not specified + CompositeType.__init__(self, optional = True) self.shareId = UInt32Le() self.lengthSourceDescriptor = UInt16Le(lambda:sizeof(self.sourceDescriptor)) self.sourceDescriptor = String("rdpy", readLen = self.lengthSourceDescriptor) From 1d5b15a310e12fc38c0a54f627599dbf16d98fc5 Mon Sep 17 00:00:00 2001 From: speyrefitte Date: Fri, 6 Feb 2015 14:35:41 +0100 Subject: [PATCH 4/9] fix minor bug to work with rdesktop but finally there is a bug in rdesktop --- rdpy/core/type.py | 2 +- rdpy/protocol/rdp/gcc.py | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/rdpy/core/type.py b/rdpy/core/type.py index deff9e1..804ca5d 100644 --- a/rdpy/core/type.py +++ b/rdpy/core/type.py @@ -811,7 +811,7 @@ class String(Type, CallableValue): self.value = s.getvalue()[s.pos:] else: self.value = "" - while self.value[-len(self._until):] != self._until or s.dataLen() == 0: + while self.value[-len(self._until):] != self._until and s.dataLen() != 0: self.value += s.read(1) else: self.value = s.read(self._readLen.value) diff --git a/rdpy/protocol/rdp/gcc.py b/rdpy/protocol/rdp/gcc.py index 942c41b..9b5a5bc 100644 --- a/rdpy/protocol/rdp/gcc.py +++ b/rdpy/protocol/rdp/gcc.py @@ -256,17 +256,17 @@ class ClientCoreData(CompositeType): self.keyboardType = UInt32Le(KeyboardType.IBM_101_102_KEYS) self.keyboardSubType = UInt32Le(0) self.keyboardFnKeys = UInt32Le(12) - self.imeFileName = String("\x00"*64, readLen = UInt8(64)) - self.postBeta2ColorDepth = UInt16Le(ColorDepth.RNS_UD_COLOR_8BPP) - self.clientProductId = UInt16Le(1) - self.serialNumber = UInt32Le(0) - self.highColorDepth = UInt16Le(HighColor.HIGH_COLOR_24BPP) - self.supportedColorDepths = UInt16Le(Support.RNS_UD_15BPP_SUPPORT | Support.RNS_UD_16BPP_SUPPORT | Support.RNS_UD_24BPP_SUPPORT | Support.RNS_UD_32BPP_SUPPORT) - self.earlyCapabilityFlags = UInt16Le(CapabilityFlags.RNS_UD_CS_SUPPORT_ERRINFO_PDU) - self.clientDigProductId = String("\x00"*64, readLen = UInt8(64)) - self.connectionType = UInt8() - self.pad1octet = UInt8() - self.serverSelectedProtocol = UInt32Le() + self.imeFileName = String("\x00"*64, readLen = UInt8(64), optional = True) + self.postBeta2ColorDepth = UInt16Le(ColorDepth.RNS_UD_COLOR_8BPP, optional = True) + self.clientProductId = UInt16Le(1, optional = True) + self.serialNumber = UInt32Le(0, optional = True) + self.highColorDepth = UInt16Le(HighColor.HIGH_COLOR_24BPP, optional = True) + self.supportedColorDepths = UInt16Le(Support.RNS_UD_15BPP_SUPPORT | Support.RNS_UD_16BPP_SUPPORT | Support.RNS_UD_24BPP_SUPPORT | Support.RNS_UD_32BPP_SUPPORT, optional = True) + self.earlyCapabilityFlags = UInt16Le(CapabilityFlags.RNS_UD_CS_SUPPORT_ERRINFO_PDU, optional = True) + self.clientDigProductId = String("\x00"*64, readLen = UInt8(64), optional = True) + self.connectionType = UInt8(optional = True) + self.pad1octet = UInt8(optional = True) + self.serverSelectedProtocol = UInt32Le(optional = True) class ServerCoreData(CompositeType): """ From e9db7d720f6ee3c9b87d3a1228b3deda0dd1f11c Mon Sep 17 00:00:00 2001 From: speyrefitte Date: Fri, 6 Feb 2015 15:23:44 +0100 Subject: [PATCH 5/9] fix issue 16 --- rdpy/protocol/rdp/mcs.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/rdpy/protocol/rdp/mcs.py b/rdpy/protocol/rdp/mcs.py index a004dda..b108879 100644 --- a/rdpy/protocol/rdp/mcs.py +++ b/rdpy/protocol/rdp/mcs.py @@ -515,15 +515,16 @@ class Server(MCSLayer): self.readDomainParams(data) self.readDomainParams(data) self._clientSettings = gcc.readConferenceCreateRequest(Stream(ber.readOctetString(data))) - - i = 1 - for channelDef in self._clientSettings.getBlock(gcc.MessageType.CS_NET).channelDefArray._array: - self._serverSettings.getBlock(gcc.MessageType.SC_NET).channelIdArray._array.append(UInt16Le(i + Channel.MCS_GLOBAL_CHANNEL)) - #if channel can be handle by serve add it - for serverChannelDef, layer in self._virtualChannels: - if channelDef.name == serverChannelDef.name: - self._channels[i + Channel.MCS_GLOBAL_CHANNEL] = layer - i += 1 + + if not self._clientSettings.CS_NET is None: + i = 1 + for channelDef in self._clientSettings.CS_NET.channelDefArray._array: + self._serverSettings.SC_NET.channelIdArray._array.append(UInt16Le(i + Channel.MCS_GLOBAL_CHANNEL)) + #if channel can be handle by serve add it + for serverChannelDef, layer in self._virtualChannels: + if channelDef.name == serverChannelDef.name: + self._channels[i + Channel.MCS_GLOBAL_CHANNEL] = layer + i += 1 self.sendConnectResponse() self.setNextState(self.recvErectDomainRequest) From 82d77982557ab453a36434b0b754e4d799968bb9 Mon Sep 17 00:00:00 2001 From: speyrefitte Date: Fri, 6 Feb 2015 18:07:02 +0100 Subject: [PATCH 6/9] fix issue 16 --- rdpy/protocol/rdp/gcc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rdpy/protocol/rdp/gcc.py b/rdpy/protocol/rdp/gcc.py index 9b5a5bc..8f8fe35 100644 --- a/rdpy/protocol/rdp/gcc.py +++ b/rdpy/protocol/rdp/gcc.py @@ -608,6 +608,6 @@ def writeConferenceCreateResponse(serverData): return (per.writeChoice(0), per.writeObjectIdentifier(t124_02_98_oid), per.writeLength(len(serverDataStream.getvalue()) + 14), per.writeChoice(0x14), - per.writeInteger16(0x79F3, 1001), per.writeInteger(1), per.writeEnumerates(16), + per.writeInteger16(0x79F3, 1001), per.writeInteger(1), per.writeEnumerates(0), per.writeNumberOfSet(1), per.writeChoice(0xc0), per.writeOctetStream(h221_sc_key, 4), per.writeOctetStream(serverDataStream.getvalue())) \ No newline at end of file From 9e50c2292de1221427c872ef518a6bd59d72861d Mon Sep 17 00:00:00 2001 From: speyrefitte Date: Mon, 9 Feb 2015 15:43:19 +0100 Subject: [PATCH 7/9] fix certuficate signing --- rdpy/protocol/rdp/gcc.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rdpy/protocol/rdp/gcc.py b/rdpy/protocol/rdp/gcc.py index 8f8fe35..458a82a 100644 --- a/rdpy/protocol/rdp/gcc.py +++ b/rdpy/protocol/rdp/gcc.py @@ -354,8 +354,8 @@ class ProprietaryServerCertificate(CompositeType): self.wPublicKeyBlobLen = UInt16Le(lambda:sizeof(self.PublicKeyBlob)) self.PublicKeyBlob = RSAPublicKey(readLen = self.wPublicKeyBlobLen) self.wSignatureBlobType = UInt16Le(0x0008, constant = True) - self.wSignatureBlobLen = UInt16Le(lambda:(sizeof(self.SignatureBlob) - 8)) - self.SignatureBlob = String(readLen = self.wSignatureBlobLen) + self.wSignatureBlobLen = UInt16Le(lambda:(sizeof(self.SignatureBlob) + sizeof(self.padding))) + self.SignatureBlob = String(readLen = UInt16Le(lambda:(self.wSignatureBlobLen.value - sizeof(self.padding)))) self.padding = String(b"\x00" * 8, readLen = UInt8(8)) def getPublicKey(self): @@ -381,7 +381,7 @@ class ProprietaryServerCertificate(CompositeType): md5Digest = md5.new() md5Digest.update(s.getvalue()) - return md5Digest.digest() + "\x00" + "\xff" * 46 + "\x01" + return md5Digest.digest() + "\x00" + "\xff" * 45 + "\x01" def sign(self): """ From a01eb57cef68fc02401e0c88c91484fe46ac74d9 Mon Sep 17 00:00:00 2001 From: speyrefitte Date: Tue, 10 Feb 2015 11:39:26 +0100 Subject: [PATCH 8/9] Add support for salted mac generation, fix issue 17 --- rdpy/protocol/rdp/pdu/layer.py | 10 +++- rdpy/protocol/rdp/sec.py | 84 ++++++++++++++++++++++++++++------ 2 files changed, 77 insertions(+), 17 deletions(-) diff --git a/rdpy/protocol/rdp/pdu/layer.py b/rdpy/protocol/rdp/pdu/layer.py index 377d53b..cbaf0ae 100644 --- a/rdpy/protocol/rdp/pdu/layer.py +++ b/rdpy/protocol/rdp/pdu/layer.py @@ -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 diff --git a/rdpy/protocol/rdp/sec.py b/rdpy/protocol/rdp/sec.py index 5eca307..78c5d81 100644 --- a/rdpy/protocol/rdp/sec.py +++ b/rdpy/protocol/rdp/sec.py @@ -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 From 6c93ca17b0ce9a35eb261793c410f6e038cd4668 Mon Sep 17 00:00:00 2001 From: citronneur Date: Mon, 16 Feb 2015 11:35:01 +0100 Subject: [PATCH 9/9] release 1.2.2 --- setup.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/setup.py b/setup.py index 5256fbc..7295ea9 100644 --- a/setup.py +++ b/setup.py @@ -4,20 +4,20 @@ import setuptools from distutils.core import setup, Extension setup(name='rdpy', - version='1.2.1', + version='1.2.2', description='Remote Desktop Protocol in Python', long_description=""" RDPY is a pure Python implementation of the Microsoft RDP (Remote Desktop Protocol) protocol (Client and Server side). RDPY is built over the event driven network engine Twisted. RDPY provide RDP and VNC binaries : - \t-RDP Man In The Middle proxy which record session - \t-RDP Honeypot - \t-RDP screenshoter - \t-RDP client - \t-VNC client - \t-VNC screenshoter - \t-RSS Player + - RDP Man In The Middle proxy which record session + - RDP Honeypot + - RDP screenshoter + - RDP client + - VNC client + - VNC screenshoter + - RSS Player """, author='Sylvain Peyrefitte', author_email='citronneur@gmail.com',