Merge branch 'dev' of https://github.com/citronneur/rdpy into dev
This commit is contained in:
@@ -257,7 +257,7 @@ class SimpleType(Type, CallableValue):
|
|||||||
@raise InvalidSize: if there is not enough data in stream
|
@raise InvalidSize: if there is not enough data in stream
|
||||||
"""
|
"""
|
||||||
if s.dataLen() < self._typeSize:
|
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]
|
self.value = struct.unpack(self._structFormat, s.read(self._typeSize))[0]
|
||||||
|
|
||||||
def mask(self):
|
def mask(self):
|
||||||
@@ -498,6 +498,9 @@ class CompositeType(Type):
|
|||||||
@summary: Call sizeof on each sub type
|
@summary: Call sizeof on each sub type
|
||||||
@return: sum of sizeof of each Type attributes
|
@return: sum of sizeof of each Type attributes
|
||||||
"""
|
"""
|
||||||
|
if self._is_readed and not self._readLen is None:
|
||||||
|
return self._readLen.value
|
||||||
|
|
||||||
size = 0
|
size = 0
|
||||||
for name in self._typeName:
|
for name in self._typeName:
|
||||||
size += sizeof(self.__dict__[name])
|
size += sizeof(self.__dict__[name])
|
||||||
@@ -808,7 +811,7 @@ class String(Type, CallableValue):
|
|||||||
self.value = s.getvalue()[s.pos:]
|
self.value = s.getvalue()[s.pos:]
|
||||||
else:
|
else:
|
||||||
self.value = ""
|
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)
|
self.value += s.read(1)
|
||||||
else:
|
else:
|
||||||
self.value = s.read(self._readLen.value)
|
self.value = s.read(self._readLen.value)
|
||||||
|
|||||||
@@ -256,17 +256,17 @@ class ClientCoreData(CompositeType):
|
|||||||
self.keyboardType = UInt32Le(KeyboardType.IBM_101_102_KEYS)
|
self.keyboardType = UInt32Le(KeyboardType.IBM_101_102_KEYS)
|
||||||
self.keyboardSubType = UInt32Le(0)
|
self.keyboardSubType = UInt32Le(0)
|
||||||
self.keyboardFnKeys = UInt32Le(12)
|
self.keyboardFnKeys = UInt32Le(12)
|
||||||
self.imeFileName = String("\x00"*64, readLen = UInt8(64))
|
self.imeFileName = String("\x00"*64, readLen = UInt8(64), optional = True)
|
||||||
self.postBeta2ColorDepth = UInt16Le(ColorDepth.RNS_UD_COLOR_8BPP)
|
self.postBeta2ColorDepth = UInt16Le(ColorDepth.RNS_UD_COLOR_8BPP, optional = True)
|
||||||
self.clientProductId = UInt16Le(1)
|
self.clientProductId = UInt16Le(1, optional = True)
|
||||||
self.serialNumber = UInt32Le(0)
|
self.serialNumber = UInt32Le(0, optional = True)
|
||||||
self.highColorDepth = UInt16Le(HighColor.HIGH_COLOR_24BPP)
|
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)
|
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)
|
self.earlyCapabilityFlags = UInt16Le(CapabilityFlags.RNS_UD_CS_SUPPORT_ERRINFO_PDU, optional = True)
|
||||||
self.clientDigProductId = String("\x00"*64, readLen = UInt8(64))
|
self.clientDigProductId = String("\x00"*64, readLen = UInt8(64), optional = True)
|
||||||
self.connectionType = UInt8()
|
self.connectionType = UInt8(optional = True)
|
||||||
self.pad1octet = UInt8()
|
self.pad1octet = UInt8(optional = True)
|
||||||
self.serverSelectedProtocol = UInt32Le()
|
self.serverSelectedProtocol = UInt32Le(optional = True)
|
||||||
|
|
||||||
class ServerCoreData(CompositeType):
|
class ServerCoreData(CompositeType):
|
||||||
"""
|
"""
|
||||||
@@ -278,7 +278,8 @@ class ServerCoreData(CompositeType):
|
|||||||
def __init__(self, readLen = None):
|
def __init__(self, readLen = None):
|
||||||
CompositeType.__init__(self, readLen = readLen)
|
CompositeType.__init__(self, readLen = readLen)
|
||||||
self.rdpVersion = UInt32Le(Version.RDP_VERSION_5_PLUS)
|
self.rdpVersion = UInt32Le(Version.RDP_VERSION_5_PLUS)
|
||||||
self.clientRequestedProtocol = UInt32Le()
|
self.clientRequestedProtocol = UInt32Le(optional = True)
|
||||||
|
self.earlyCapabilityFlags = UInt32Le(optional = True)
|
||||||
|
|
||||||
class ClientSecurityData(CompositeType):
|
class ClientSecurityData(CompositeType):
|
||||||
"""
|
"""
|
||||||
@@ -353,8 +354,8 @@ class ProprietaryServerCertificate(CompositeType):
|
|||||||
self.wPublicKeyBlobLen = UInt16Le(lambda:sizeof(self.PublicKeyBlob))
|
self.wPublicKeyBlobLen = UInt16Le(lambda:sizeof(self.PublicKeyBlob))
|
||||||
self.PublicKeyBlob = RSAPublicKey(readLen = self.wPublicKeyBlobLen)
|
self.PublicKeyBlob = RSAPublicKey(readLen = self.wPublicKeyBlobLen)
|
||||||
self.wSignatureBlobType = UInt16Le(0x0008, constant = True)
|
self.wSignatureBlobType = UInt16Le(0x0008, constant = True)
|
||||||
self.wSignatureBlobLen = UInt16Le(lambda:(sizeof(self.SignatureBlob) - 8))
|
self.wSignatureBlobLen = UInt16Le(lambda:(sizeof(self.SignatureBlob) + sizeof(self.padding)))
|
||||||
self.SignatureBlob = String(readLen = self.wSignatureBlobLen)
|
self.SignatureBlob = String(readLen = UInt16Le(lambda:(self.wSignatureBlobLen.value - sizeof(self.padding))))
|
||||||
self.padding = String(b"\x00" * 8, readLen = UInt8(8))
|
self.padding = String(b"\x00" * 8, readLen = UInt8(8))
|
||||||
|
|
||||||
def getPublicKey(self):
|
def getPublicKey(self):
|
||||||
@@ -380,7 +381,7 @@ class ProprietaryServerCertificate(CompositeType):
|
|||||||
md5Digest = md5.new()
|
md5Digest = md5.new()
|
||||||
md5Digest.update(s.getvalue())
|
md5Digest.update(s.getvalue())
|
||||||
|
|
||||||
return md5Digest.digest() + "\x00" + "\xff" * 46 + "\x01"
|
return md5Digest.digest() + "\x00" + "\xff" * 45 + "\x01"
|
||||||
|
|
||||||
def sign(self):
|
def sign(self):
|
||||||
"""
|
"""
|
||||||
@@ -607,6 +608,6 @@ def writeConferenceCreateResponse(serverData):
|
|||||||
|
|
||||||
return (per.writeChoice(0), per.writeObjectIdentifier(t124_02_98_oid),
|
return (per.writeChoice(0), per.writeObjectIdentifier(t124_02_98_oid),
|
||||||
per.writeLength(len(serverDataStream.getvalue()) + 14), per.writeChoice(0x14),
|
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.writeNumberOfSet(1), per.writeChoice(0xc0),
|
||||||
per.writeOctetStream(h221_sc_key, 4), per.writeOctetStream(serverDataStream.getvalue()))
|
per.writeOctetStream(h221_sc_key, 4), per.writeOctetStream(serverDataStream.getvalue()))
|
||||||
@@ -97,8 +97,8 @@ class LicenseBinaryBlob(CompositeType):
|
|||||||
@summary: Blob use by license manager to exchange security data
|
@summary: Blob use by license manager to exchange security data
|
||||||
@see: http://msdn.microsoft.com/en-us/library/cc240481.aspx
|
@see: http://msdn.microsoft.com/en-us/library/cc240481.aspx
|
||||||
"""
|
"""
|
||||||
def __init__(self, blobType = BinaryBlobType.BB_ANY_BLOB):
|
def __init__(self, blobType = BinaryBlobType.BB_ANY_BLOB, optional = False):
|
||||||
CompositeType.__init__(self)
|
CompositeType.__init__(self, optional = optional)
|
||||||
self.wBlobType = UInt16Le(blobType, constant = True if blobType != BinaryBlobType.BB_ANY_BLOB else False)
|
self.wBlobType = UInt16Le(blobType, constant = True if blobType != BinaryBlobType.BB_ANY_BLOB else False)
|
||||||
self.wBlobLen = UInt16Le(lambda:sizeof(self.blobData))
|
self.wBlobLen = UInt16Le(lambda:sizeof(self.blobData))
|
||||||
self.blobData = String(readLen = self.wBlobLen)
|
self.blobData = String(readLen = self.wBlobLen)
|
||||||
@@ -110,11 +110,11 @@ class LicensingErrorMessage(CompositeType):
|
|||||||
"""
|
"""
|
||||||
_MESSAGE_TYPE_ = MessageType.ERROR_ALERT
|
_MESSAGE_TYPE_ = MessageType.ERROR_ALERT
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self, readLen = None):
|
||||||
CompositeType.__init__(self)
|
CompositeType.__init__(self, readLen = readLen)
|
||||||
self.dwErrorCode = UInt32Le()
|
self.dwErrorCode = UInt32Le()
|
||||||
self.dwStateTransition = UInt32Le()
|
self.dwStateTransition = UInt32Le()
|
||||||
self.blob = LicenseBinaryBlob(BinaryBlobType.BB_ERROR_BLOB)
|
self.blob = LicenseBinaryBlob(BinaryBlobType.BB_ANY_BLOB)
|
||||||
|
|
||||||
class ProductInformation(CompositeType):
|
class ProductInformation(CompositeType):
|
||||||
"""
|
"""
|
||||||
@@ -159,8 +159,8 @@ class ServerLicenseRequest(CompositeType):
|
|||||||
"""
|
"""
|
||||||
_MESSAGE_TYPE_ = MessageType.LICENSE_REQUEST
|
_MESSAGE_TYPE_ = MessageType.LICENSE_REQUEST
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self, readLen = None):
|
||||||
CompositeType.__init__(self)
|
CompositeType.__init__(self, readLen = readLen)
|
||||||
self.serverRandom = String("\x00" * 32, readLen = UInt8(32))
|
self.serverRandom = String("\x00" * 32, readLen = UInt8(32))
|
||||||
self.productInfo = ProductInformation()
|
self.productInfo = ProductInformation()
|
||||||
self.keyExchangeList = LicenseBinaryBlob(BinaryBlobType.BB_KEY_EXCHG_ALG_BLOB)
|
self.keyExchangeList = LicenseBinaryBlob(BinaryBlobType.BB_KEY_EXCHG_ALG_BLOB)
|
||||||
@@ -175,8 +175,8 @@ class ClientNewLicenseRequest(CompositeType):
|
|||||||
"""
|
"""
|
||||||
_MESSAGE_TYPE_ = MessageType.NEW_LICENSE_REQUEST
|
_MESSAGE_TYPE_ = MessageType.NEW_LICENSE_REQUEST
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self, readLen = None):
|
||||||
CompositeType.__init__(self)
|
CompositeType.__init__(self, readLen = readLen)
|
||||||
#RSA and must be only RSA
|
#RSA and must be only RSA
|
||||||
self.preferredKeyExchangeAlg = UInt32Le(0x00000001, constant = True)
|
self.preferredKeyExchangeAlg = UInt32Le(0x00000001, constant = True)
|
||||||
#pure microsoft client ;-)
|
#pure microsoft client ;-)
|
||||||
@@ -194,8 +194,8 @@ class ServerPlatformChallenge(CompositeType):
|
|||||||
"""
|
"""
|
||||||
_MESSAGE_TYPE_ = MessageType.PLATFORM_CHALLENGE
|
_MESSAGE_TYPE_ = MessageType.PLATFORM_CHALLENGE
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self, readLen = None):
|
||||||
CompositeType.__init__(self)
|
CompositeType.__init__(self, readLen = readLen)
|
||||||
self.connectFlags = UInt32Le()
|
self.connectFlags = UInt32Le()
|
||||||
self.encryptedPlatformChallenge = LicenseBinaryBlob(BinaryBlobType.BB_ANY_BLOB)
|
self.encryptedPlatformChallenge = LicenseBinaryBlob(BinaryBlobType.BB_ANY_BLOB)
|
||||||
self.MACData = String(readLen = UInt8(16))
|
self.MACData = String(readLen = UInt8(16))
|
||||||
@@ -207,8 +207,8 @@ class ClientPLatformChallengeResponse(CompositeType):
|
|||||||
"""
|
"""
|
||||||
_MESSAGE_TYPE_ = MessageType.PLATFORM_CHALLENGE_RESPONSE
|
_MESSAGE_TYPE_ = MessageType.PLATFORM_CHALLENGE_RESPONSE
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self, readLen = None):
|
||||||
CompositeType.__init__(self)
|
CompositeType.__init__(self, readLen = readLen)
|
||||||
self.encryptedPlatformChallengeResponse = LicenseBinaryBlob(BinaryBlobType.BB_DATA_BLOB)
|
self.encryptedPlatformChallengeResponse = LicenseBinaryBlob(BinaryBlobType.BB_DATA_BLOB)
|
||||||
self.encryptedHWID = LicenseBinaryBlob(BinaryBlobType.BB_DATA_BLOB)
|
self.encryptedHWID = LicenseBinaryBlob(BinaryBlobType.BB_DATA_BLOB)
|
||||||
self.MACData = String(readLen = UInt8(16))
|
self.MACData = String(readLen = UInt8(16))
|
||||||
@@ -231,7 +231,7 @@ class LicPacket(CompositeType):
|
|||||||
"""
|
"""
|
||||||
for c in [LicensingErrorMessage, ServerLicenseRequest, ClientNewLicenseRequest, ServerPlatformChallenge, ClientPLatformChallengeResponse]:
|
for c in [LicensingErrorMessage, ServerLicenseRequest, ClientNewLicenseRequest, ServerPlatformChallenge, ClientPLatformChallengeResponse]:
|
||||||
if self.bMsgtype.value == c._MESSAGE_TYPE_:
|
if self.bMsgtype.value == c._MESSAGE_TYPE_:
|
||||||
return c()
|
return c(readLen = self.wMsgSize - 4)
|
||||||
log.debug("unknown license message : %s"%self.bMsgtype.value)
|
log.debug("unknown license message : %s"%self.bMsgtype.value)
|
||||||
return String()
|
return String()
|
||||||
|
|
||||||
|
|||||||
@@ -515,15 +515,16 @@ class Server(MCSLayer):
|
|||||||
self.readDomainParams(data)
|
self.readDomainParams(data)
|
||||||
self.readDomainParams(data)
|
self.readDomainParams(data)
|
||||||
self._clientSettings = gcc.readConferenceCreateRequest(Stream(ber.readOctetString(data)))
|
self._clientSettings = gcc.readConferenceCreateRequest(Stream(ber.readOctetString(data)))
|
||||||
|
|
||||||
i = 1
|
if not self._clientSettings.CS_NET is None:
|
||||||
for channelDef in self._clientSettings.getBlock(gcc.MessageType.CS_NET).channelDefArray._array:
|
i = 1
|
||||||
self._serverSettings.getBlock(gcc.MessageType.SC_NET).channelIdArray._array.append(UInt16Le(i + Channel.MCS_GLOBAL_CHANNEL))
|
for channelDef in self._clientSettings.CS_NET.channelDefArray._array:
|
||||||
#if channel can be handle by serve add it
|
self._serverSettings.SC_NET.channelIdArray._array.append(UInt16Le(i + Channel.MCS_GLOBAL_CHANNEL))
|
||||||
for serverChannelDef, layer in self._virtualChannels:
|
#if channel can be handle by serve add it
|
||||||
if channelDef.name == serverChannelDef.name:
|
for serverChannelDef, layer in self._virtualChannels:
|
||||||
self._channels[i + Channel.MCS_GLOBAL_CHANNEL] = layer
|
if channelDef.name == serverChannelDef.name:
|
||||||
i += 1
|
self._channels[i + Channel.MCS_GLOBAL_CHANNEL] = layer
|
||||||
|
i += 1
|
||||||
|
|
||||||
self.sendConnectResponse()
|
self.sendConnectResponse()
|
||||||
self.setNextState(self.recvErectDomainRequest)
|
self.setNextState(self.recvErectDomainRequest)
|
||||||
|
|||||||
@@ -429,7 +429,8 @@ class ShareControlHeader(CompositeType):
|
|||||||
#share control header
|
#share control header
|
||||||
self.totalLength = UInt16Le(totalLength)
|
self.totalLength = UInt16Le(totalLength)
|
||||||
self.pduType = UInt16Le(pduType)
|
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):
|
class ShareDataHeader(CompositeType):
|
||||||
"""
|
"""
|
||||||
@@ -519,7 +520,9 @@ class DeactiveAllPDU(CompositeType):
|
|||||||
_PDUTYPE_ = PDUType.PDUTYPE_DEACTIVATEALLPDU
|
_PDUTYPE_ = PDUType.PDUTYPE_DEACTIVATEALLPDU
|
||||||
|
|
||||||
def __init__(self):
|
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.shareId = UInt32Le()
|
||||||
self.lengthSourceDescriptor = UInt16Le(lambda:sizeof(self.sourceDescriptor))
|
self.lengthSourceDescriptor = UInt16Le(lambda:sizeof(self.sourceDescriptor))
|
||||||
self.sourceDescriptor = String("rdpy", readLen = self.lengthSourceDescriptor)
|
self.sourceDescriptor = String("rdpy", readLen = self.lengthSourceDescriptor)
|
||||||
|
|||||||
@@ -179,6 +179,9 @@ class Client(PDULayer):
|
|||||||
|
|
||||||
for cap in pdu.pduMessage.capabilitySets._array:
|
for cap in pdu.pduMessage.capabilitySets._array:
|
||||||
self._serverCapabilities[cap.capabilitySetType] = cap
|
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()
|
self.sendConfirmActivePDU()
|
||||||
#send synchronize
|
#send synchronize
|
||||||
@@ -312,7 +315,7 @@ class Client(PDULayer):
|
|||||||
generalCapability = self._clientCapabilities[caps.CapsType.CAPSTYPE_GENERAL].capability
|
generalCapability = self._clientCapabilities[caps.CapsType.CAPSTYPE_GENERAL].capability
|
||||||
generalCapability.osMajorType.value = caps.MajorType.OSMAJORTYPE_WINDOWS
|
generalCapability.osMajorType.value = caps.MajorType.OSMAJORTYPE_WINDOWS
|
||||||
generalCapability.osMinorType.value = caps.MinorType.OSMINORTYPE_WINDOWS_NT
|
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:
|
if not self._fastPathSender is None:
|
||||||
generalCapability.extraFlags.value |= caps.GeneralExtraFlag.FASTPATH_OUTPUT_SUPPORTED
|
generalCapability.extraFlags.value |= caps.GeneralExtraFlag.FASTPATH_OUTPUT_SUPPORTED
|
||||||
|
|
||||||
@@ -413,6 +416,9 @@ class Server(PDULayer):
|
|||||||
#find use full flag
|
#find use full flag
|
||||||
self._clientFastPathSupported = bool(self._clientCapabilities[caps.CapsType.CAPSTYPE_GENERAL].capability.extraFlags.value & caps.GeneralExtraFlag.FASTPATH_OUTPUT_SUPPORTED)
|
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)
|
self.setNextState(self.recvClientSynchronizePDU)
|
||||||
|
|
||||||
def recvClientSynchronizePDU(self, s):
|
def recvClientSynchronizePDU(self, s):
|
||||||
@@ -525,7 +531,7 @@ class Server(PDULayer):
|
|||||||
generalCapability = self._serverCapabilities[caps.CapsType.CAPSTYPE_GENERAL].capability
|
generalCapability = self._serverCapabilities[caps.CapsType.CAPSTYPE_GENERAL].capability
|
||||||
generalCapability.osMajorType.value = caps.MajorType.OSMAJORTYPE_WINDOWS
|
generalCapability.osMajorType.value = caps.MajorType.OSMAJORTYPE_WINDOWS
|
||||||
generalCapability.osMinorType.value = caps.MinorType.OSMINORTYPE_WINDOWS_NT
|
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 = self._serverCapabilities[caps.CapsType.CAPSTYPE_INPUT].capability
|
||||||
inputCapability.inputFlags.value = caps.InputFlags.INPUT_FLAG_SCANCODES | caps.InputFlags.INPUT_FLAG_MOUSEX
|
inputCapability.inputFlags.value = caps.InputFlags.INPUT_FLAG_SCANCODES | caps.InputFlags.INPUT_FLAG_MOUSEX
|
||||||
|
|||||||
@@ -164,12 +164,12 @@ def macData(macSaltKey, data):
|
|||||||
md5Digest = md5.new()
|
md5Digest = md5.new()
|
||||||
|
|
||||||
#encode length
|
#encode length
|
||||||
s = Stream()
|
dataLength = Stream()
|
||||||
s.writeType(UInt32Le(len(data)))
|
dataLength.writeType(UInt32Le(len(data)))
|
||||||
|
|
||||||
sha1Digest.update(macSaltKey)
|
sha1Digest.update(macSaltKey)
|
||||||
sha1Digest.update("\x36" * 40)
|
sha1Digest.update("\x36" * 40)
|
||||||
sha1Digest.update(s.getvalue())
|
sha1Digest.update(dataLength.getvalue())
|
||||||
sha1Digest.update(data)
|
sha1Digest.update(data)
|
||||||
|
|
||||||
sha1Sig = sha1Digest.digest()
|
sha1Sig = sha1Digest.digest()
|
||||||
@@ -180,6 +180,38 @@ def macData(macSaltKey, data):
|
|||||||
|
|
||||||
return md5Digest.digest()
|
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):
|
def tempKey(initialKey, currentKey):
|
||||||
"""
|
"""
|
||||||
@see: http://msdn.microsoft.com/en-us/library/cc240792.aspx
|
@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
|
#True if classic encryption is enable
|
||||||
self._enableEncryption = False
|
self._enableEncryption = False
|
||||||
|
|
||||||
|
#Enable Secure Mac generation
|
||||||
|
self._enableSecureCheckSum = False
|
||||||
|
|
||||||
#initialise decrypt and encrypt keys
|
#initialise decrypt and encrypt keys
|
||||||
self._macKey = None
|
self._macKey = None
|
||||||
self._initialDecrytKey = None
|
self._initialDecrytKey = None
|
||||||
@@ -358,10 +393,11 @@ class SecLayer(LayerAutomata, IStreamSender, tpkt.IFastPathListener, tpkt.IFastP
|
|||||||
self._encryptRc4 = None
|
self._encryptRc4 = None
|
||||||
|
|
||||||
|
|
||||||
def readEncryptedPayload(self, s):
|
def readEncryptedPayload(self, s, saltedMacGeneration):
|
||||||
"""
|
"""
|
||||||
@summary: decrypt basic RDP security payload
|
@summary: decrypt basic RDP security payload
|
||||||
@param s: {Stream} encrypted stream
|
@param s: {Stream} encrypted stream
|
||||||
|
@param saltedMacGeneration: {bool} use salted mac generation
|
||||||
@return: {Stream} decrypted
|
@return: {Stream} decrypted
|
||||||
"""
|
"""
|
||||||
#if update is needed
|
#if update is needed
|
||||||
@@ -378,18 +414,22 @@ class SecLayer(LayerAutomata, IStreamSender, tpkt.IFastPathListener, tpkt.IFastP
|
|||||||
decrypted = rc4.crypt(self._decryptRc4, encryptedPayload.value)
|
decrypted = rc4.crypt(self._decryptRc4, encryptedPayload.value)
|
||||||
|
|
||||||
#ckeck signature
|
#ckeck signature
|
||||||
if macData(self._macKey, decrypted)[:8] != signature.value:
|
if not saltedMacGeneration and macData(self._macKey, decrypted)[:8] != signature.value:
|
||||||
raise InvalidExpectedDataException("Bad packet signature")
|
raise InvalidExpectedDataException("bad signature")
|
||||||
|
|
||||||
|
if saltedMacGeneration and macSaltedData(self._macKey, decrypted, self._nbDecryptedPacket)[:8] != signature.value:
|
||||||
|
raise InvalidExpectedDataException("bad signature")
|
||||||
|
|
||||||
#count
|
#count
|
||||||
self._nbDecryptedPacket += 1
|
self._nbDecryptedPacket += 1
|
||||||
|
|
||||||
return Stream(decrypted)
|
return Stream(decrypted)
|
||||||
|
|
||||||
def writeEncryptedPayload(self, data):
|
def writeEncryptedPayload(self, data, saltedMacGeneration):
|
||||||
"""
|
"""
|
||||||
@summary: sign and crypt data
|
@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)
|
@return: {Tuple} (signature, encryptedData)
|
||||||
"""
|
"""
|
||||||
if self._nbEncryptedPacket == 4096:
|
if self._nbEncryptedPacket == 4096:
|
||||||
@@ -400,9 +440,14 @@ class SecLayer(LayerAutomata, IStreamSender, tpkt.IFastPathListener, tpkt.IFastP
|
|||||||
self._nbEncryptedPacket = 0
|
self._nbEncryptedPacket = 0
|
||||||
|
|
||||||
self._nbEncryptedPacket += 1
|
self._nbEncryptedPacket += 1
|
||||||
|
|
||||||
s = Stream()
|
s = Stream()
|
||||||
s.writeType(data)
|
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):
|
def recv(self, data):
|
||||||
"""
|
"""
|
||||||
@@ -419,7 +464,7 @@ class SecLayer(LayerAutomata, IStreamSender, tpkt.IFastPathListener, tpkt.IFastP
|
|||||||
data.readType((securityFlag, securityFlagHi))
|
data.readType((securityFlag, securityFlagHi))
|
||||||
|
|
||||||
if securityFlag.value & SecurityFlag.SEC_ENCRYPT:
|
if securityFlag.value & SecurityFlag.SEC_ENCRYPT:
|
||||||
data = self.readEncryptedPayload(data)
|
data = self.readEncryptedPayload(data, securityFlag.value & SecurityFlag.SEC_SECURE_CHECKSUM)
|
||||||
|
|
||||||
self._presentation.recv(data)
|
self._presentation.recv(data)
|
||||||
|
|
||||||
@@ -433,7 +478,12 @@ class SecLayer(LayerAutomata, IStreamSender, tpkt.IFastPathListener, tpkt.IFastP
|
|||||||
self._transport.send(data)
|
self._transport.send(data)
|
||||||
return
|
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):
|
def sendFlagged(self, flag, data):
|
||||||
"""
|
"""
|
||||||
@@ -444,7 +494,7 @@ class SecLayer(LayerAutomata, IStreamSender, tpkt.IFastPathListener, tpkt.IFastP
|
|||||||
@param data: {Type | Tuple}
|
@param data: {Type | Tuple}
|
||||||
"""
|
"""
|
||||||
if flag & SecurityFlag.SEC_ENCRYPT:
|
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))
|
self._transport.send((UInt16Le(flag), UInt16Le(), data))
|
||||||
|
|
||||||
def recvFastPath(self, secFlag, fastPathS):
|
def recvFastPath(self, secFlag, fastPathS):
|
||||||
@@ -454,7 +504,7 @@ class SecLayer(LayerAutomata, IStreamSender, tpkt.IFastPathListener, tpkt.IFastP
|
|||||||
@param fastPathS: {Stream}
|
@param fastPathS: {Stream}
|
||||||
"""
|
"""
|
||||||
if self._enableEncryption and secFlag & tpkt.SecFlags.FASTPATH_OUTPUT_ENCRYPTED:
|
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)
|
self._fastPathPresentation.recvFastPath(secFlag, fastPathS)
|
||||||
|
|
||||||
@@ -472,7 +522,11 @@ class SecLayer(LayerAutomata, IStreamSender, tpkt.IFastPathListener, tpkt.IFastP
|
|||||||
"""
|
"""
|
||||||
if self._enableEncryption:
|
if self._enableEncryption:
|
||||||
secFlag |= tpkt.SecFlags.FASTPATH_OUTPUT_ENCRYPTED
|
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)
|
self._fastPathTransport.sendFastPath(secFlag, fastPathS)
|
||||||
|
|
||||||
@@ -661,7 +715,7 @@ class Server(SecLayer):
|
|||||||
raise InvalidExpectedDataException("Waiting info packet")
|
raise InvalidExpectedDataException("Waiting info packet")
|
||||||
|
|
||||||
if securityFlag.value & SecurityFlag.SEC_ENCRYPT:
|
if securityFlag.value & SecurityFlag.SEC_ENCRYPT:
|
||||||
s = self.readEncryptedPayload(s)
|
s = self.readEncryptedPayload(s, securityFlag.value & SecurityFlag.SEC_SECURE_CHECKSUM)
|
||||||
|
|
||||||
s.readType(self._info)
|
s.readType(self._info)
|
||||||
#next state send error license
|
#next state send error license
|
||||||
|
|||||||
16
setup.py
16
setup.py
@@ -4,20 +4,20 @@ import setuptools
|
|||||||
from distutils.core import setup, Extension
|
from distutils.core import setup, Extension
|
||||||
|
|
||||||
setup(name='rdpy',
|
setup(name='rdpy',
|
||||||
version='1.2.1',
|
version='1.2.2',
|
||||||
description='Remote Desktop Protocol in Python',
|
description='Remote Desktop Protocol in Python',
|
||||||
long_description="""
|
long_description="""
|
||||||
RDPY is a pure Python implementation of the Microsoft RDP (Remote Desktop Protocol) protocol (Client and Server side).
|
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 is built over the event driven network engine Twisted.
|
||||||
|
|
||||||
RDPY provide RDP and VNC binaries :
|
RDPY provide RDP and VNC binaries :
|
||||||
\t-RDP Man In The Middle proxy which record session
|
- RDP Man In The Middle proxy which record session
|
||||||
\t-RDP Honeypot
|
- RDP Honeypot
|
||||||
\t-RDP screenshoter
|
- RDP screenshoter
|
||||||
\t-RDP client
|
- RDP client
|
||||||
\t-VNC client
|
- VNC client
|
||||||
\t-VNC screenshoter
|
- VNC screenshoter
|
||||||
\t-RSS Player
|
- RSS Player
|
||||||
""",
|
""",
|
||||||
author='Sylvain Peyrefitte',
|
author='Sylvain Peyrefitte',
|
||||||
author_email='citronneur@gmail.com',
|
author_email='citronneur@gmail.com',
|
||||||
|
|||||||
Reference in New Issue
Block a user