implement gcc connect sequence

This commit is contained in:
speyrefitte
2013-10-22 18:28:32 +02:00
parent 67fbc75b3e
commit b0949e6f3c
7 changed files with 235 additions and 34 deletions

View File

@@ -7,7 +7,7 @@ import sys
from PyQt4 import QtGui
from rdpy.display.qt import adaptor, widget
from rdpy.protocol.rfb import rfb, factory
from rdpy.protocol.rdp import tpkt, tpdu
from rdpy.protocol.rdp import tpkt, tpdu, mcs
from twisted.internet import ssl
from OpenSSL import SSL
@@ -32,6 +32,6 @@ if __name__ == '__main__':
from twisted.internet import reactor
#reactor.connectTCP("127.0.0.1", 5901, factory.RfbFactory(protocol))
#reactor.connectTCP("192.168.135.160", 3389, factory.RfbFactory(tpkt.TPKT(tpdu.TPDU())))
reactor.connectTCP("192.168.122.184", 3389, factory.RfbFactory(tpkt.TPKT(tpdu.TPDU())))
reactor.connectTCP("192.168.56.1", 3389, factory.RfbFactory(tpkt.TPKT(tpdu.TPDU(mcs.MCS()))))
reactor.run()
sys.exit(app.exec_())

View File

@@ -121,7 +121,7 @@ def readApplicationTag(s, tag):
def writeApplicationTag(tag, size):
'''
return struct that represent ber application tag
@param tag: tag class attribute
@param tag: UINt8
@param size: size to rest of packet
'''
if tag > UInt8(30):
@@ -187,15 +187,15 @@ def readInteger(s):
def writeInteger(value):
'''
write integer value
@param param: UInt32Be
@param param: int or python long
@return ber interger structure
'''
if value < UInt32Be(0xff):
return (writeUniversalTag(Tag.BER_TAG_INTEGER, False), writeLength(1), UInt8(value.value))
elif value < UInt32Be(0xff80):
return (writeUniversalTag(Tag.BER_TAG_INTEGER, False), writeLength(2), UInt16Be(value.value))
if value < 0xff:
return (writeUniversalTag(Tag.BER_TAG_INTEGER, False), writeLength(1), UInt8(value))
elif value < 0xff80:
return (writeUniversalTag(Tag.BER_TAG_INTEGER, False), writeLength(2), UInt16Be(value))
else:
return (writeUniversalTag(Tag.BER_TAG_INTEGER, False), writeLength(4), UInt32Be(value.value))
return (writeUniversalTag(Tag.BER_TAG_INTEGER, False), writeLength(4), UInt32Be(value))
def readOctetString(s):
'''
@@ -211,10 +211,10 @@ def readOctetString(s):
def writeOctetstring(value):
'''
write string in ber representation
@param value: String
@param value: string
@return: string ber structure
'''
return (writeUniversalTag(Tag.BER_TAG_OCTET_STRING, False), writeLength(len(value.value)), value)
return (writeUniversalTag(Tag.BER_TAG_OCTET_STRING, False), writeLength(len(value)), String(value))
def readEnumerated(s):
'''

View File

@@ -1,9 +1,11 @@
'''
@author sylvain
@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 UInt32Le, UInt16Le, String, CompositeType
from rdpy.protocol.network.type import UInt8, UInt32Le, UInt16Le, String, Stream, CompositeType, sizeof
import per
@ConstAttributes
@@ -32,15 +34,60 @@ class ColorDepth(object):
RNS_UD_COLOR_16BPP_555 = UInt16Le(0xCA02)
RNS_UD_COLOR_16BPP_565 = UInt16Le(0xCA03)
RNS_UD_COLOR_24BPP = UInt16Le(0xCA04)
@ConstAttributes
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)
RNS_UD_24BPP_SUPPORT = 0x0001
RNS_UD_16BPP_SUPPORT = 0x0002
RNS_UD_15BPP_SUPPORT = 0x0004
RNS_UD_32BPP_SUPPORT = 0x0008
@ConstAttributes
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_SAS_DEL = 0xAA03
@ConstAttributes
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
@ConstAttributes
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)
@ConstAttributes
class Version(object):
@@ -63,17 +110,22 @@ class ClientCoreSettings(CompositeType):
self.padding1 = (UInt16Le(), UInt16Le())
self.kbdLayout = UInt32Le(0x409)
self.clientBuild = UInt32Le(2100)
self.clientName = "rdpy"
self.clientName = String("\x00"*64)
self.padding2 = UInt16Le()
self.keyboardType = UInt32Le(4)
self.keyboardSubType = UInt32Le(0)
self.keyboardFnKeys = UInt32Le(12)
self.padding3 = String("\x00"*64)
self.postBeta2ColorDepth = ColorDepth.RNS_UD_COLOR_24BPP
self.padding4 = (UInt16Le(), UInt32Le())
self.highColorDepth = UInt16Le(24)
self.padding5 = (UInt16Le(), UInt16Le())
self.padding3 = String("\x00"*64)
self.clientProductId = UInt16Le()
self.serialNumber = UInt32Le()
self.highColorDepth = HighColor.HIGH_COLOR_24BPP
self.supportedColorDepths = Support.RNS_UD_32BPP_SUPPORT
self.earlyCapabilityFlags = UInt16Le()
self.clientDigProductId = String("\x00"*64)
self.connectionType = UInt8()
self.pad1octet = UInt8()
self.serverSelectedProtocol = UInt32Le()
class ServerCoreSettings(CompositeType):
'''
@@ -81,4 +133,82 @@ class ServerCoreSettings(CompositeType):
'''
def __init__(self):
CompositeType.__init__(self)
self.rdpVersion = Version.RDP_VERSION_5_PLUS
self.rdpVersion = Version.RDP_VERSION_5_PLUS
class Channel(object):
'''
channels structure share between
client and server
'''
def __init__(self):
#name of channel
self.name = ""
#unknown
self.options = 0
#id of channel
self.channelId = 0
#True if channel is connect
self.connect = False
class ClientSettings(object):
'''
class which group all client settings supported by RDPY
'''
def __init__(self):
self.core = ClientCoreSettings()
#list of Channel read network gcc packet
self.networkChannels = []
t124_02_98_oid = ( 0, 0, 20, 124, 0, 1 )
h221_cs_key = "Duca";
h221_sc_key = "McDn";
def writeConferenceCreateRequest(settings):
'''
write conference create request structure
@param settings: ClientSettings
@return: struct that represent
'''
userData = writeClientDataBlocks(settings)
userDataStream = Stream()
userDataStream.writeType(userData)
return (per.writeChoice(0), per.writeObjectIdentifier(t124_02_98_oid),
per.writeLength(len(userDataStream.getvalue()) + 14), per.writeChoice(0),
per.writeSelection(0x08), per.writeNumericString("1", 1), per.writePadding(1),
per.writeNumberOfSet(1), per.writeChoice(0xc0),
per.writeOctetStream(h221_cs_key, 4), per.writeOctetStream(userDataStream.getvalue()))
def writeClientDataBlocks(settings):
'''
write all blocks for client
and return gcc valid structure
@param settings: ClientSettings
'''
return (writeClientCoreData(settings.core), writeClientNetworkData(settings.networkChannels))
def writeClientCoreData(core):
'''
write client settings in GCC language
@param settings: ClientSettings structure
@return: structure that represent client data blocks
'''
return (ClientToServerMessage.CS_CORE, UInt16Le(sizeof(core) + 4), core)
def writeClientNetworkData(channels):
'''
write network packet whith channels infos
@param channels: list of Channel
@return: gcc network packet
'''
if len(channels) == 0:
return ()
result = []
result.append(UInt32Le(len(channels)))
for channel in channels:
result.append((String(channel.name[0:8]), UInt32Le(channel.options)))
resultPacket = tuple(result)
return (ClientToServerMessage.CS_NET, UInt16Le(sizeof(resultPacket) + 4), resultPacket)

View File

@@ -2,7 +2,32 @@
@author: sylvain
'''
from rdpy.utils.const import ConstAttributes
from rdpy.protocol.network.layer import LayerAutomata
from rdpy.protocol.network.type import sizeof, Stream, UInt8
from rdpy.protocol.rdp.ber import writeLength
import ber, gcc
@ConstAttributes
class Message(object):
'''
message type
'''
MCS_TYPE_CONNECT_INITIAL = UInt8(0x65)
MCS_TYPE_CONNECT_RESPONSE = UInt8(0x66)
MCS_EDRQ = UInt8(1)
MCS_DPUM = UInt8(8)
MCS_AURQ = UInt8(10)
MCS_AUCF = UInt8(11)
MCS_CJRQ = UInt8(14)
MCS_CJCF = UInt8(15)
MCS_SDRQ = UInt8(25)
MCS_SDIN = UInt8(26)
class Channel:
MCS_GLOBAL_CHANNEL = 1003
MCS_USERCHANNEL_BASE = 1001
class MCS(LayerAutomata):
'''
@@ -14,13 +39,46 @@ class MCS(LayerAutomata):
def __init__(self, presentation = None):
'''
ctor call base class ctor
@param presentation: presentation layer
'''
LayerAutomata.__init__(self, presentation)
self._clientSettings = gcc.ClientSettings()
def connect(self):
'''
connection send for client mode
a write connect initial packet
'''
self._clientSettings.core.serverSelectedProtocol = self._transport._protocol
self.sendConnectInitial()
def sendConnectInitial(self):
'''
send connect initial packet
'''
ccReq = gcc.writeConferenceCreateRequest(self._clientSettings)
ccReqStream = Stream()
ccReqStream.writeType(ccReq)
tmp = (ber.writeOctetstring("\x01"), ber.writeOctetstring("\x01"), ber.writeBoolean(True),
self.writeDomainParams(34, 2, 0, 0xffff),
self.writeDomainParams(0xffff, 0xfc17, 0xffff, 0xffff),
ber.writeOctetstring(ccReqStream.getvalue()))
self._transport.send((ber.writeApplicationTag(Message.MCS_TYPE_CONNECT_INITIAL, sizeof(tmp)), tmp))
def writeDomainParams(self, maxChannels, maxUsers, maxTokens, maxPduSize):
'''
write a special domain param structure
use in connection sequence
@param maxChannels: number of mcs channel use
@param maxUsers: number of mcs user used (1)
@param maxTokens: unknown
@param maxPduSize: unknown
@return: domain param structure
'''
domainParam = (ber.writeInteger(maxChannels), ber.writeInteger(maxUsers), ber.writeInteger(maxTokens),
ber.writeInteger(1), ber.writeInteger(0), ber.writeInteger(1),
ber.writeInteger(maxPduSize), ber.writeInteger(2))
return (ber.writeUniversalTag(ber.Tag.BER_TAG_SEQUENCE, True), writeLength(sizeof(domainParam)), domainParam)

View File

@@ -209,9 +209,9 @@ def writeNumericString(nStr, minValue):
result = []
for i in range(0, length, 2):
c1 = ord(str[i])
c1 = ord(nStr[i])
if i + 1 < length:
c2 = ord(str[i + 1])
c2 = ord(nStr[i + 1])
else:
c2 = 0x30
c1 = (c1 - 0x30) % 10
@@ -258,7 +258,7 @@ def readOctetStream(s, octetStream, minValue):
return True
def writeOctetStream(oStr, minValue):
def writeOctetStream(oStr, minValue = 0):
'''
write string as octet stream with per header
@param oStr: octet stream to convert

View File

@@ -60,12 +60,13 @@ class Negotiation(CompositeType):
class TPDU(LayerAutomata):
'''
classdocs
TPDU layer management
there is an connection automata
'''
def __init__(self, presentation = None):
'''
Constructor
@param presentation: MCS layer
'''
LayerAutomata.__init__(self, presentation)
@@ -83,6 +84,9 @@ class TPDU(LayerAutomata):
def recvConnectionConfirm(self, data):
'''
recv connection confirm message
next state is recvData
call connect on presentation layer if all is good
@param data: Stream that contain connection confirm
'''
header = TPDUConnectHeader()
data.readType(header)
@@ -91,13 +95,23 @@ class TPDU(LayerAutomata):
#check presence of negotiation response
if data.dataLen() == 8:
self.readNeg(data)
else:
raise NegotiationFailure("server doesn't support SSL negotiation on RDP")
self.setNextState(self.recvData)
#connection is done send to presentation
LayerAutomata.connect(self)
def recvData(self, data):
print "TPDU data"
def sendConnectionRequest(self):
'''
write connection request message
next state is recvConnectionConfirm
'''
neqReq = Negotiation(self._protocol)
self._transport.send((TPDUConnectHeader(MessageType.X224_TPDU_CONNECTION_REQUEST, sizeof(neqReq)), NegociationType.TYPE_RDP_NEG_REQ, neqReq))
neqReq = (NegociationType.TYPE_RDP_NEG_REQ, Negotiation(self._protocol))
self._transport.send((TPDUConnectHeader(MessageType.X224_TPDU_CONNECTION_REQUEST, sizeof(neqReq)), neqReq))
self.setNextState(self.recvConnectionConfirm)
def send(self, message):
@@ -109,7 +123,7 @@ class TPDU(LayerAutomata):
def readNeg(self, data):
'''
read neagotiation response
read negotiation response
'''
code = UInt8()
data.readType(code)

View File

@@ -4,8 +4,7 @@
from rdpy.protocol.network.type import String, UInt8, UInt16Be, UInt32Be
from rdpy.protocol.network.layer import RawLayer
from message import ServerInit, PixelFormat, FrameBufferUpdateRequest, Rectangle, KeyEvent, PointerEvent, ClientCutText
from message import ProtocolVersion, SecurityType, Encoding, ClientToServerMessages
from message import *
class Rfb(RawLayer):
'''