From d7cbf887e5534c47d20a352a2f61f6fffcf84f4f Mon Sep 17 00:00:00 2001 From: speyrefitte Date: Mon, 28 Oct 2013 17:04:38 +0100 Subject: [PATCH] add connect response reading --- rdpy/main.py | 2 +- rdpy/protocol/network/type.py | 7 ++ rdpy/protocol/rdp/ber.py | 48 +++++----- rdpy/protocol/rdp/gcc.py | 175 ++++++++++++++++++++++++---------- rdpy/protocol/rdp/mcs.py | 33 ++++--- rdpy/protocol/rdp/per.py | 8 +- 6 files changed, 179 insertions(+), 94 deletions(-) diff --git a/rdpy/main.py b/rdpy/main.py index 98a443a..9556be8 100644 --- a/rdpy/main.py +++ b/rdpy/main.py @@ -24,6 +24,6 @@ if __name__ == '__main__': from twisted.internet import reactor #reactor.connectTCP("127.0.0.1", 5901, factory.RfbFactory(protocol)) #reactor.connectTCP("192.168.1.90", 3389, factory.RfbFactory(tpkt.TPKT(tpdu.TPDU(mcs.MCS())))) - reactor.connectTCP("192.168.135.73", 3389, factory.RfbFactory(tpkt.TPKT(tpdu.TPDU(mcs.MCS())))) + reactor.connectTCP("192.168.135.50", 3389, factory.RfbFactory(tpkt.TPKT(tpdu.TPDU(mcs.MCS())))) reactor.run() #sys.exit(app.exec_()) \ No newline at end of file diff --git a/rdpy/protocol/network/type.py b/rdpy/protocol/network/type.py index a2ea388..6c3d92b 100644 --- a/rdpy/protocol/network/type.py +++ b/rdpy/protocol/network/type.py @@ -450,6 +450,13 @@ class Stream(StringIO): ''' return self.len - self.pos + def readLen(self): + ''' + compute already read size + @return: read size of stream + ''' + return self.pos + def readType(self, value): ''' call specific read on type object diff --git a/rdpy/protocol/rdp/ber.py b/rdpy/protocol/rdp/ber.py index bf1d016..30fea04 100644 --- a/rdpy/protocol/rdp/ber.py +++ b/rdpy/protocol/rdp/ber.py @@ -2,35 +2,37 @@ @author: sylvain ''' from rdpy.protocol.network.type import UInt8, UInt16Be, UInt32Be, String -from rdpy.utils.const import ConstAttributes -from rdpy.protocol.network.error import InvalidExpectedDataException,\ - InvalidSize +from rdpy.utils.const import ConstAttributes, TypeAttributes +from rdpy.protocol.network.error import InvalidExpectedDataException, InvalidSize @ConstAttributes +@TypeAttributes(UInt8) class BerPc(object): - BER_PC_MASK = UInt8(0x20) - BER_PRIMITIVE = UInt8(0x00) - BER_CONSTRUCT = UInt8(0x20) + BER_PC_MASK = 0x20 + BER_PRIMITIVE = 0x00 + BER_CONSTRUCT = 0x20 -@ConstAttributes +@ConstAttributes +@TypeAttributes(UInt8) class Class(object): - BER_CLASS_MASK = UInt8(0xC0) - BER_CLASS_UNIV = UInt8(0x00) - BER_CLASS_APPL = UInt8(0x40) - BER_CLASS_CTXT = UInt8(0x80) - BER_CLASS_PRIV = UInt8(0xC0) + BER_CLASS_MASK = 0xC0 + BER_CLASS_UNIV = 0x00 + BER_CLASS_APPL = 0x40 + BER_CLASS_CTXT = 0x80 + BER_CLASS_PRIV = 0xC0 -@ConstAttributes +@ConstAttributes +@TypeAttributes(UInt8) class Tag(object): - BER_TAG_MASK = UInt8(0x1F) - BER_TAG_BOOLEAN = UInt8(0x01) - BER_TAG_INTEGER = UInt8(0x02) - BER_TAG_BIT_STRING = UInt8(0x03) - BER_TAG_OCTET_STRING = UInt8(0x04) - BER_TAG_OBJECT_IDENFIER = UInt8(0x06) - BER_TAG_ENUMERATED = UInt8(0x0A) - BER_TAG_SEQUENCE = UInt8(0x10) - BER_TAG_SEQUENCE_OF = UInt8(0x10) + BER_TAG_MASK = 0x1F + BER_TAG_BOOLEAN = 0x01 + BER_TAG_INTEGER = 0x02 + BER_TAG_BIT_STRING = 0x03 + BER_TAG_OCTET_STRING = 0x04 + BER_TAG_OBJECT_IDENFIER = 0x06 + BER_TAG_ENUMERATED = 0x0A + BER_TAG_SEQUENCE = 0x10 + BER_TAG_SEQUENCE_OF = 0x10 def berPC(pc): ''' @@ -222,7 +224,7 @@ def writeOctetstring(value): return (writeUniversalTag(Tag.BER_TAG_OCTET_STRING, False), writeLength(len(value)), String(value)) def readEnumerated(s): - '''rt-successful + ''' read enumerated structure @param s: Stream @return: int or long diff --git a/rdpy/protocol/rdp/gcc.py b/rdpy/protocol/rdp/gcc.py index 48c87e5..c3989ba 100644 --- a/rdpy/protocol/rdp/gcc.py +++ b/rdpy/protocol/rdp/gcc.py @@ -3,117 +3,133 @@ @summary gcc language @contact: http://msdn.microsoft.com/en-us/library/cc240510.aspx ''' -from rdpy.utils.const import ConstAttributes -from rdpy.protocol.network.type import * +from rdpy.utils.const import ConstAttributes, TypeAttributes +from rdpy.protocol.network.type import UInt8, UInt16Le, UInt32Le, CompositeType, String, UniString, Stream, sizeof import per +from rdpy.protocol.network.error import InvalidExpectedDataException t124_02_98_oid = ( 0, 0, 20, 124, 0, 1 ) h221_cs_key = "Duca"; h221_sc_key = "McDn"; @ConstAttributes +@TypeAttributes(UInt16Le) class ServerToClientMessage(object): - SC_CORE = UInt16Le(0x0C01) - SC_SECURITY = UInt16Le(0x0C02) - SC_NET = UInt16Le(0x0C03) + ''' + Server to Client block + gcc conference messages + ''' + SC_CORE = 0x0C01 + SC_SECURITY = 0x0C02 + SC_NET = 0x0C03 @ConstAttributes +@TypeAttributes(UInt16Le) class ClientToServerMessage(object): ''' - Client to Server message + Client to Server block + gcc conference messages ''' - CS_CORE = UInt16Le(0xC001) - CS_SECURITY = UInt16Le(0xC002) - CS_NET = UInt16Le(0xC003) - CS_CLUSTER = UInt16Le(0xC004) - CS_MONITOR = UInt16Le(0xC005) + CS_CORE = 0xC001 + CS_SECURITY = 0xC002 + CS_NET = 0xC003 + CS_CLUSTER = 0xC004 + CS_MONITOR = 0xC005 @ConstAttributes +@TypeAttributes(UInt16Le) class ColorDepth(object): ''' depth color ''' - RNS_UD_COLOR_8BPP = UInt16Le(0xCA01) - RNS_UD_COLOR_16BPP_555 = UInt16Le(0xCA02) - RNS_UD_COLOR_16BPP_565 = UInt16Le(0xCA03) - RNS_UD_COLOR_24BPP = UInt16Le(0xCA04) + RNS_UD_COLOR_8BPP = 0xCA01 + RNS_UD_COLOR_16BPP_555 = 0xCA02 + RNS_UD_COLOR_16BPP_565 = 0xCA03 + RNS_UD_COLOR_24BPP = 0xCA04 @ConstAttributes +@TypeAttributes(UInt16Le) class HighColor(object): ''' high color of client ''' - HIGH_COLOR_4BPP = UInt16Le(0x0004) - HIGH_COLOR_8BPP = UInt16Le(0x0008) - HIGH_COLOR_15BPP = UInt16Le(0x000f) - HIGH_COLOR_16BPP = UInt16Le(0x0010) - HIGH_COLOR_24BPP = UInt16Le(0x0018) + HIGH_COLOR_4BPP = 0x0004 + HIGH_COLOR_8BPP = 0x0008 + HIGH_COLOR_15BPP = 0x000f + HIGH_COLOR_16BPP = 0x0010 + HIGH_COLOR_24BPP = 0x0018 @ConstAttributes +@TypeAttributes(UInt16Le) class Support(object): ''' support depth flag ''' - RNS_UD_24BPP_SUPPORT = UInt16Le(0x0001) - RNS_UD_16BPP_SUPPORT = UInt16Le(0x0002) - RNS_UD_15BPP_SUPPORT = UInt16Le(0x0004) - RNS_UD_32BPP_SUPPORT = UInt16Le(0x0008) + RNS_UD_24BPP_SUPPORT = 0x0001 + RNS_UD_16BPP_SUPPORT = 0x0002 + RNS_UD_15BPP_SUPPORT = 0x0004 + RNS_UD_32BPP_SUPPORT = 0x0008 @ConstAttributes +@TypeAttributes(UInt16Le) class CapabilityFlags(object): ''' @contact: http://msdn.microsoft.com/en-us/library/cc240510.aspx for more details on each flags click above ''' - RNS_UD_CS_SUPPORT_ERRINFO_PDU = UInt16Le(0x0001) - RNS_UD_CS_WANT_32BPP_SESSION = UInt16Le(0x0002) - RNS_UD_CS_SUPPORT_STATUSINFO_PDU = UInt16Le(0x0004) - RNS_UD_CS_STRONG_ASYMMETRIC_KEYS = UInt16Le(0x0008) - RN_UD_CS_UNUSED = UInt16Le(0x0010) - RNS_UD_CS_VALID_CONNECTION_TYPE = UInt16Le(0x0020) - RNS_UD_CS_SUPPORT_MONITOR_LAYOUT_PDU = UInt16Le(0x0040) - RNS_UD_CS_SUPPORT_NETCHAR_AUTODETECT = UInt16Le(0x0080) - RNS_UD_CS_SUPPORT_DYNVC_GFX_PROTOCOL = UInt16Le(0x0100) - RNS_UD_CS_SUPPORT_DYNAMIC_TIME_ZONE = UInt16Le(0x0200) - RNS_UD_CS_SUPPORT_HEARTBEAT_PDU = UInt16Le(0x0400) + RNS_UD_CS_SUPPORT_ERRINFO_PDU = 0x0001 + RNS_UD_CS_WANT_32BPP_SESSION = 0x0002 + RNS_UD_CS_SUPPORT_STATUSINFO_PDU = 0x0004 + RNS_UD_CS_STRONG_ASYMMETRIC_KEYS = 0x0008 + RN_UD_CS_UNUSED = 0x0010 + RNS_UD_CS_VALID_CONNECTION_TYPE = 0x0020 + RNS_UD_CS_SUPPORT_MONITOR_LAYOUT_PDU = 0x0040 + RNS_UD_CS_SUPPORT_NETCHAR_AUTODETECT = 0x0080 + RNS_UD_CS_SUPPORT_DYNVC_GFX_PROTOCOL = 0x0100 + RNS_UD_CS_SUPPORT_DYNAMIC_TIME_ZONE = 0x0200 + RNS_UD_CS_SUPPORT_HEARTBEAT_PDU = 0x0400 @ConstAttributes +@TypeAttributes(UInt8) class ConnectionType(object): ''' this information is correct if RNS_UD_CS_VALID_CONNECTION_TYPE flag is set on capabilityFlag @contact: http://msdn.microsoft.com/en-us/library/cc240510.aspx ''' - CONNECTION_TYPE_MODEM = UInt8(0x01) - CONNECTION_TYPE_BROADBAND_LOW = UInt8(0x02) - CONNECTION_TYPE_SATELLITE = UInt8(0x03) - CONNECTION_TYPE_BROADBAND_HIGH = UInt8(0x04) - CONNECTION_TYPE_WAN = UInt8(0x05) - CONNECTION_TYPE_LAN = UInt8(0x06) - CONNECTION_TYPE_AUTODETECT = UInt8(0x07) + CONNECTION_TYPE_MODEM = 0x01 + CONNECTION_TYPE_BROADBAND_LOW = 0x02 + CONNECTION_TYPE_SATELLITE = 0x03 + CONNECTION_TYPE_BROADBAND_HIGH = 0x04 + CONNECTION_TYPE_WAN = 0x05 + CONNECTION_TYPE_LAN = 0x06 + CONNECTION_TYPE_AUTODETECT = 0x07 @ConstAttributes +@TypeAttributes(UInt32Le) class Version(object): ''' supported version of RDP ''' - RDP_VERSION_4 = UInt32Le(0x00080001) - RDP_VERSION_5_PLUS = UInt32Le(0x00080004) + RDP_VERSION_4 = 0x00080001 + RDP_VERSION_5_PLUS = 0x00080004 @ConstAttributes +@TypeAttributes(UInt16Le) class Sequence(object): - RNS_UD_SAS_DEL = UInt16Le(0xAA03) + RNS_UD_SAS_DEL = 0xAA03 -@ConstAttributes +@ConstAttributes +@TypeAttributes(UInt32Le) class Encryption(object): ''' encryption method supported @deprecated: because rdpy use ssl but need to send to server... ''' - ENCRYPTION_FLAG_40BIT = UInt32Le(0x00000001) - ENCRYPTION_FLAG_128BIT = UInt32Le(0x00000002) - ENCRYPTION_FLAG_56BIT = UInt32Le(0x00000008) - FIPS_ENCRYPTION_FLAG = UInt32Le(0x00000010) + ENCRYPTION_FLAG_40BIT = 0x00000001 + ENCRYPTION_FLAG_128BIT = 0x00000002 + ENCRYPTION_FLAG_56BIT = 0x00000008 + FIPS_ENCRYPTION_FLAG = 0x00000010 class ClientCoreSettings(CompositeType): @@ -152,6 +168,7 @@ class ServerCoreSettings(CompositeType): def __init__(self): CompositeType.__init__(self) self.rdpVersion = Version.RDP_VERSION_5_PLUS + self.clientRequestedProtocol = UInt32Le() class ClientSecuritySettings(CompositeType): ''' @@ -160,7 +177,7 @@ class ClientSecuritySettings(CompositeType): ''' def __init__(self): CompositeType.__init__(self) - self.encryptionMethods = UInt32Le()#Encryption.ENCRYPTION_FLAG_128BIT | Encryption.ENCRYPTION_FLAG_40BIT | Encryption.ENCRYPTION_FLAG_56BIT | Encryption.FIPS_ENCRYPTION_FLAG + self.encryptionMethods = UInt32Le() self.extEncryptionMethods = UInt32Le() class Channel(object): @@ -188,6 +205,14 @@ class ClientSettings(object): self.networkChannels = [] self.security = ClientSecuritySettings() +class ServerSettings(object): + ''' + server settings + ''' + def __init__(self): + #core settings of server + self.core = ServerCoreSettings() + def writeConferenceCreateRequest(settings): ''' write conference create request structure @@ -204,6 +229,26 @@ def writeConferenceCreateRequest(settings): per.writeNumberOfSet(1), per.writeChoice(0xc0), per.writeOctetStream(h221_cs_key, 4), per.writeOctetStream(userDataStream.getvalue())) +def readConferenceCreateResponse(s): + ''' + read response from server + and return server settings read from this response + @param s: Stream + @return: ServerSettings + ''' + per.readChoice(s) + per.readObjectIdentifier(s, t124_02_98_oid) + per.readLength(s) + per.readChoice(s) + per.readInteger16(s, 1001) + per.readInteger(s) + per.readEnumerates(s) + per.readNumberOfSet(s) + per.readChoice(s) + if not per.readOctetStream(s, h221_sc_key, 4): + raise InvalidExpectedDataException("cannot read h221_sc_key") + return readServerDataBlocks(s) + def writeClientDataBlocks(settings): ''' @@ -212,8 +257,34 @@ def writeClientDataBlocks(settings): @param settings: ClientSettings ''' return (writeClientCoreData(settings.core), - #writeClientNetworkData(settings.networkChannels), + writeClientNetworkData(settings.networkChannels), writeClientSecurityData(settings.security)) + +def readServerDataBlocks(s): + ''' + read gcc server data blocks + and return result in Server Settings object + @param s: Stream + @return: ServerSettings + ''' + settings = ServerSettings() + length = per.readLength(s) + while length > 0: + marker = s.readLen() + blockType = UInt16Le() + blockLength = UInt16Le() + s.readType((blockType, blockLength)) + if blockType == ServerToClientMessage.SC_CORE: + s.readType(settings.core) + elif blockType == ServerToClientMessage.SC_NET: + pass + elif blockType == ServerToClientMessage.SC_SECURITY: + pass + else: + print "Unknow server block %s"%hex(type) + length -= blockLength.value + s.seek(marker + blockLength.value) + def writeClientCoreData(core): ''' diff --git a/rdpy/protocol/rdp/mcs.py b/rdpy/protocol/rdp/mcs.py index ba57e47..e489608 100644 --- a/rdpy/protocol/rdp/mcs.py +++ b/rdpy/protocol/rdp/mcs.py @@ -70,6 +70,22 @@ class MCS(LayerAutomata): self._transport.send((ber.writeApplicationTag(Message.MCS_TYPE_CONNECT_INITIAL, sizeof(tmp)), tmp)) #we must receive a connect response self.setNextState(self.recvConnectResponse) + + def recvConnectResponse(self, data): + ''' + receive mcs connect response from server + @param data: Stream + ''' + ber.readApplicationTag(data, Message.MCS_TYPE_CONNECT_RESPONSE) + ber.readEnumerated(data) + ber.readInteger(data) + self.readDomainParams(data) + if not ber.readUniversalTag(data, ber.Tag.BER_TAG_OCTET_STRING, False): + raise InvalidExpectedDataException("invalid expected tag") + gccRequestLength = ber.readLength(data) + if data.dataLen() != gccRequestLength: + raise InvalidSize("bad size of gcc request") + gcc.readConferenceCreateResponse(data) def writeDomainParams(self, maxChannels, maxUsers, maxTokens, maxPduSize): ''' @@ -89,10 +105,11 @@ class MCS(LayerAutomata): def readDomainParams(self, s): ''' read domain params structure + @return: (max_channels, max_users, max_tokens, max_pdu_size) ''' if not ber.readUniversalTag(s, ber.Tag.BER_TAG_SEQUENCE, True): raise InvalidValue("bad BER tags") - length = ber.readLength(s) + ber.readLength(s)#length max_channels = ber.readInteger(s) max_users = ber.readInteger(s) max_tokens = ber.readInteger(s) @@ -101,18 +118,6 @@ class MCS(LayerAutomata): ber.readInteger(s) max_pdu_size = ber.readInteger(s) ber.readInteger(s) - - def recvConnectResponse(self, data): - ber.readApplicationTag(data, Message.MCS_TYPE_CONNECT_RESPONSE) - ber.readEnumerated(data) - ber.readInteger(data) - self.readDomainParams(data) - if not ber.readUniversalTag(data, ber.Tag.BER_TAG_OCTET_STRING, False): - raise InvalidExpectedDataException("invalid expected tag") - gccRequestLength = ber.readLength(data) - if data.dataLen() != gccRequestLength: - raise InvalidSize("gcc request have ") - from rdpy.protocol.network.type import hexDump - hexDump(data.getvalue()) + return (max_channels, max_users, max_tokens, max_pdu_size) \ No newline at end of file diff --git a/rdpy/protocol/rdp/per.py b/rdpy/protocol/rdp/per.py index e140497..90044ae 100644 --- a/rdpy/protocol/rdp/per.py +++ b/rdpy/protocol/rdp/per.py @@ -169,21 +169,21 @@ def readObjectIdentifier(s, oid): size = readLength(s) if size != 5: raise InvalidValue("size of stream oid is wrong %d != 5"%size) - a_oid = (0, 0, 0, 0, 0, 0) + a_oid = [0, 0, 0, 0, 0, 0] t12 = UInt8() s.readType(t12) a_oid[0] = t12.value >> 4 a_oid[1] = t12.value & 0x0f s.readType(t12) + a_oid[2] = t12.value + s.readType(t12) a_oid[3] = t12.value s.readType(t12) a_oid[4] = t12.value s.readType(t12) a_oid[5] = t12.value - s.readType(t12) - a_oid[6] = t12.value - if oid != a_oid: + if list(oid) != a_oid: raise InvalidExpectedDataException("invalid object identifier") def writeObjectIdentifier(oid):