add rdp login packet

This commit is contained in:
speyrefitte
2013-12-05 18:03:44 +01:00
parent 9a4d5b059e
commit 65d1ef89f5
6 changed files with 232 additions and 105 deletions

View File

@@ -29,12 +29,18 @@ class Type(object):
'''
root type
'''
def __init__(self, write_if = lambda:True, read_if = lambda:True):
self._write_if = write_if
self._read_if = read_if
def write(self, s):
'''
interface definition of write function
@param s: Stream which will be written
'''
pass
if not self._write_if():
return
self.__write__(s)
def read(self, s):
'''
@@ -42,7 +48,9 @@ class Type(object):
@param s: Stream
@return: Type read from Stream s
'''
pass
if not self._read_if():
return
self.__read__(s)
def __sizeof__(self):
'''
@@ -50,34 +58,45 @@ class Type(object):
@return: size in byte of type
'''
pass
class SimpleType(Type):
class ValueType(Type):
'''
simple type
type that wrap an inner type
acces with value getter and setter
value can be a callable which is call
at each access of value
'''
def __init__(self, structFormat, typeSize, signed, value):
'''
constructor of simple type
@param structFormat: letter that represent type in struct package
@param typeSize: size in byte of type
@param signed: true if type represent a signed type
@param value: value record in this object
'''
self._typeSize = typeSize
self._structFormat = structFormat
self._signed = signed
def __init__(self, value, write_if = lambda:True, read_if = lambda:True):
Type.__init__(self, write_if = write_if, read_if = read_if)
self._value = None
self.value = value
def __getValue__(self):
'''
shortcut to access inner value
call lambda value
@return: inner value(python type value)
'''
return self._value()
def __setValue__(self, value):
'''
setter of value wrap in lambda value
@param value: new value encompass in valuetype object
'''
value_callable = lambda:value
if callable(value):
value_callable = value
self._value = value_callable
@property
def value(self):
'''
shortcut to access inner value
@return: inner value(python type value)
'''
if self._signed:
return self._value
else:
return self._value & self.mask()
return self.__getValue__()
@value.setter
def value(self, value):
@@ -86,9 +105,52 @@ class SimpleType(Type):
@param value: new value encompass in simpletype object
@raise InvalidValue: if value doesn't respect type range
'''
self.__setValue__(value)
class SimpleType(ValueType):
'''
simple type
'''
def __init__(self, structFormat, typeSize, signed, value, write_if = lambda:True, read_if = lambda:True):
'''
constructor of simple type
@param structFormat: letter that represent type in struct package
@param typeSize: size in byte of type
@param signed: true if type represent a signed type
@param value: value recorded in this object
'''
self._signed = signed
self._typeSize = typeSize
self._structFormat = structFormat
ValueType.__init__(self, value, write_if = write_if, read_if = read_if)
def __getValue__(self):
'''
shortcut to access inner value
@return: inner value(python type value)
@raise InvalidValue: if value doesn't respect type range
'''
value = ValueType.__getValue__(self)
if not self.isInRange(value):
raise InvalidValue("value is out of range for %s"%self.__class__)
self._value = value
if self._signed:
return value
else:
return value & self.mask()
def __setValue__(self, value):
'''
setter of value after check it
@param value: new value encompass in simpletype object
@raise InvalidValue: if value doesn't respect type range
'''
#check static value range
if not callable(value) and not self.isInRange(value):
raise InvalidValue("value is out of range for %s"%self.__class__)
ValueType.__setValue__(self, value)
def __cmp__(self, other):
'''
@@ -102,22 +164,21 @@ class SimpleType(Type):
other = self.__class__(other)
return self.value.__cmp__(other.value)
def write(self, s):
def __write__(self, s):
'''
write value in stream s
use struct package to pack value
@param s: Stream which will be written
'''
s.write(struct.pack(self._structFormat, self._value))
s.write(struct.pack(self._structFormat, self.value))
def read(self, s):
def __read__(self, s):
'''
read inner value from stream
use struct package
@param s: Stream
'''
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):
'''
@@ -154,7 +215,7 @@ class SimpleType(Type):
implement not operator
@return: __class__ value
'''
invert = ~self._value
invert = ~self.value
if not self._signed:
invert &= self.mask()
return self.__class__(invert)
@@ -230,7 +291,7 @@ class SimpleType(Type):
hash function to treat simple type in hash collection
@return: hash of inner value
'''
return hash(self._value)
return hash(self.value)
class CompositeType(Type):
@@ -238,10 +299,11 @@ class CompositeType(Type):
keep ordering declaration of simple type
in list and transparent for other type
'''
def __init__(self):
def __init__(self, write_if = lambda:True, read_if = lambda:True):
'''
init list of simple value
'''
Type.__init__(self, write_if = write_if, read_if = read_if)
#list of ordoned type
self._typeName = []
@@ -255,7 +317,7 @@ class CompositeType(Type):
self._typeName.append(name)
self.__dict__[name] = value
def read(self, s):
def __read__(self, s):
'''
call read on each ordered subtype
@param s: Stream
@@ -263,7 +325,7 @@ class CompositeType(Type):
for name in self._typeName:
s.readType(self.__dict__[name])
def write(self, s):
def __write__(self, s):
'''
call write on each ordered subtype
@param s: Stream
@@ -307,15 +369,15 @@ class UInt8(SimpleType):
'''
unsigned byte
'''
def __init__(self, value = 0):
SimpleType.__init__(self, "B", 1, False, value)
def __init__(self, value = 0, write_if = lambda:True, read_if = lambda:True):
SimpleType.__init__(self, "B", 1, False, value, write_if = write_if, read_if = read_if)
class SInt8(SimpleType):
'''
signed byte
'''
def __init__(self, value = 0):
SimpleType.__init__(self, "b", 1, True, value)
def __init__(self, value = 0, write_if = lambda:True, read_if = lambda:True):
SimpleType.__init__(self, "b", 1, True, value, write_if = write_if, read_if = read_if)
class UInt16Be(SimpleType):
@@ -324,8 +386,8 @@ class UInt16Be(SimpleType):
@attention: inner value is in machine representation
Big endian is just for read or write in stream
'''
def __init__(self, value = 0):
SimpleType.__init__(self, ">H", 2, False, value)
def __init__(self, value = 0, write_if = lambda:True, read_if = lambda:True):
SimpleType.__init__(self, ">H", 2, False, value, write_if = write_if, read_if = read_if)
class UInt16Le(SimpleType):
'''
@@ -333,8 +395,8 @@ class UInt16Le(SimpleType):
@attention: inner value is in machine representation
Big endian is just for read or write in stream
'''
def __init__(self, value = 0):
SimpleType.__init__(self, "<H", 2, False, value)
def __init__(self, value = 0, write_if = lambda:True, read_if = lambda:True):
SimpleType.__init__(self, "<H", 2, False, value, write_if = write_if, read_if = read_if)
class UInt32Be(SimpleType):
'''
@@ -342,8 +404,8 @@ class UInt32Be(SimpleType):
@attention: inner value is in machine representation
Big endian is just for read or write in stream
'''
def __init__(self, value = 0):
SimpleType.__init__(self, ">I", 4, False, value)
def __init__(self, value = 0, write_if = lambda:True, read_if = lambda:True):
SimpleType.__init__(self, ">I", 4, False, value, write_if = write_if, read_if = read_if)
class UInt32Le(SimpleType):
'''
@@ -351,8 +413,8 @@ class UInt32Le(SimpleType):
@attention: inner value is in machine representation
Big endian is just for read or write in stream
'''
def __init__(self, value = 0):
SimpleType.__init__(self, "<I", 4, False, value)
def __init__(self, value = 0, write_if = lambda:True, read_if = lambda:True):
SimpleType.__init__(self, "<I", 4, False, value, write_if = write_if, read_if = read_if)
class SInt32Le(SimpleType):
'''
@@ -360,8 +422,8 @@ class SInt32Le(SimpleType):
@attention: inner value is in machine representation
Big endian is just for read or write in stream
'''
def __init__(self, value = 0):
SimpleType.__init__(self, "<I", 4, True, value)
def __init__(self, value = 0, write_if = lambda:True, read_if = lambda:True):
SimpleType.__init__(self, "<I", 4, True, value, write_if = write_if, read_if = read_if)
class SInt32Be(SimpleType):
'''
@@ -369,8 +431,8 @@ class SInt32Be(SimpleType):
@attention: inner value is in machine representation
Big endian is just for read or write in stream
'''
def __init__(self, value = 0):
SimpleType.__init__(self, ">I", 4, True, value)
def __init__(self, value = 0, write_if = lambda:True, read_if = lambda:True):
SimpleType.__init__(self, ">I", 4, True, value, write_if = write_if, read_if = read_if)
class UInt24Be(SimpleType):
'''
@@ -378,14 +440,14 @@ class UInt24Be(SimpleType):
@attention: inner value is in machine representation
Big endian is just for read or write in stream
'''
def __init__(self, value = 0):
SimpleType.__init__(self, ">I", 3, False, value)
def __init__(self, value = 0, write_if = lambda:True, read_if = lambda:True):
SimpleType.__init__(self, ">I", 3, False, value, write_if = write_if, read_if = read_if)
def write(self, s):
def __write__(self, s):
'''
special write for a special type
'''
s.write(struct.pack(">I", self._value)[1:])
s.write(struct.pack(">I", self.value)[1:])
class UInt24Le(SimpleType):
'''
@@ -393,27 +455,27 @@ class UInt24Le(SimpleType):
@attention: inner value is in machine representation
Big endian is just for read or write in stream
'''
def __init__(self, value = 0):
SimpleType.__init__(self, "<I", 3, False, value)
def __init__(self, value = 0, write_if = lambda:True, read_if = lambda:True):
SimpleType.__init__(self, "<I", 3, False, value, write_if = write_if, read_if = read_if)
def write(self, s):
def __write__(self, s):
'''
special write for a special type
@param s: Stream
'''
#don't write first byte
s.write(struct.pack("<I", self._value)[1:])
s.write(struct.pack("<I", self.value)[1:])
class String(Type):
class String(ValueType):
'''
String network type
'''
def __init__(self, value = ""):
def __init__(self, value = "", write_if = lambda:True, read_if = lambda:True):
'''
constructor with new string
@param value: python string use for inner value
'''
self._value = value
ValueType.__init__(self, value, write_if = write_if, read_if = read_if)
def __eq__(self, other):
'''
@@ -421,46 +483,46 @@ class String(Type):
@param other: other String parameter
@return: if two inner value are equals
'''
return self._value == other._value
return self.value == other.value
def __hash__(self):
'''
hash function to treat simple type in hash collection
@return: hash of inner value
'''
return hash(self._value)
return hash(self.value)
def __str__(self):
'''
call when str function is call
@return: inner python string
'''
return self._value
return self.value
def write(self, s):
def __write__(self, s):
'''
write the entire raw value
@param s: Stream
'''
s.write(self._value)
s.write(self.value)
def read(self, s):
def __read__(self, s):
'''
read all stream if len of inner value is zero
else read the len of inner string
@param s: Stream
'''
if len(self._value) == 0:
self._value = s.getvalue()
if len(self.value) == 0:
self.value = s.getvalue()
else:
self._value = s.read(len(self._value))
self.value = s.read(len(self.value))
def __sizeof__(self):
'''
return len of string
@return: len of inner string
'''
return len(self._value)
return len(self.value)
class UniString(String):
'''
@@ -472,7 +534,7 @@ class UniString(String):
and end with double null char
@param s: Stream
'''
for c in self._value:
for c in self.value:
s.writeType(UInt8(ord(c)))
s.writeType(UInt8(0))
s.writeType(UInt16Le(0))
@@ -482,7 +544,7 @@ class UniString(String):
return len of uni string
@return: 2*len + 2
'''
return len(self._value) * 2 + 2
return len(self.value) * 2 + 2
class Stream(StringIO):

View File

@@ -230,7 +230,7 @@ class ClientSettings(object):
def __init__(self):
self.core = ClientCoreSettings()
#list of ClientRequestedChannel read network gcc packet
self.networkChannels = [ClientRequestedChannel("rdpdr", ChannelOptions.CHANNEL_OPTION_INITIALIZED)]
self.networkChannels = []
self.security = ClientSecuritySettings()
class ServerSettings(object):

View File

@@ -3,35 +3,82 @@
'''
from rdpy.protocol.network.layer import LayerAutomata
from rdpy.protocol.network.type import CompositeType, UInt8, UniString, UInt16Le, UInt32Le
from rdpy.protocol.network.type import CompositeType, UniString, UInt16Le, UInt16Be, UInt32Le, sizeof
from rdpy.utils.const import ConstAttributes, TypeAttributes
from rdpy.protocol.network.error import InvalidExpectedDataException
@ConstAttributes
@TypeAttributes(UInt16Le)
class SecurityFlag(object):
SEC_INFO_PKT = 0x0040
SEC_LICENSE_PKT = 0x0080
@ConstAttributes
@TypeAttributes(UInt32Le)
class InfoFlag(object):
INFO_MOUSE = 0x00000001
INFO_DISABLECTRLALTDEL = 0x00000002
INFO_AUTOLOGON = 0x00000008
INFO_UNICODE = 0x00000010
INFO_MAXIMIZESHELL = 0x00000020
INFO_LOGONNOTIFY = 0x00000040
INFO_COMPRESSION = 0x00000080
INFO_ENABLEWINDOWSKEY = 0x00000100
INFO_REMOTECONSOLEAUDIO = 0x00002000
INFO_FORCE_ENCRYPTED_CS_PDU = 0x00004000
INFO_RAIL = 0x00008000
INFO_LOGONERRORS = 0x00010000
INFO_MOUSE_HAS_WHEEL = 0x00020000
INFO_PASSWORD_IS_SC_PIN = 0x00040000
INFO_NOAUDIOPLAYBACK = 0x00080000
INFO_USING_SAVED_CREDS = 0x00100000
INFO_AUDIOCAPTURE = 0x00200000
INFO_VIDEO_DISABLE = 0x00400000
INFO_CompressionTypeMask = 0x00001E00
@ConstAttributes
@TypeAttributes(UInt32Le)
class PerfFlag(object):
PERF_DISABLE_WALLPAPER = 0x00000001
PERF_DISABLE_FULLWINDOWDRAG = 0x00000002
PERF_DISABLE_MENUANIMATIONS = 0x00000004
PERF_DISABLE_THEMING = 0x00000008
PERF_DISABLE_CURSOR_SHADOW = 0x00000020
PERF_DISABLE_CURSORSETTINGS = 0x00000040
PERF_ENABLE_FONT_SMOOTHING = 0x00000080
PERF_ENABLE_DESKTOP_COMPOSITION = 0x00000100
@ConstAttributes
@TypeAttributes(UInt16Le)
class AfInet(object):
AF_INET = 0x00002
AF_INET6 = 0x0017
class RDPInfo(CompositeType):
def __init__(self):
CompositeType.__init__(self)
self.audioCapture = UInt8()
self.audioPlayback = UInt8()
self.autoLogon = UInt8()
self.remoteApp = UInt8()
self.consoleAudio = UInt8()
self.compression = UInt8()
self.domain = UniString()
self.username = UniString()
self.password = UniString()
self.codePage = UInt32Le()
self.flag = InfoFlag.INFO_MOUSE | InfoFlag.INFO_UNICODE | InfoFlag.INFO_LOGONERRORS | InfoFlag.INFO_LOGONNOTIFY | InfoFlag.INFO_ENABLEWINDOWSKEY | InfoFlag.INFO_DISABLECTRLALTDEL
self.cbDomain = UInt16Le(lambda:sizeof(self.domain) - 2)
self.cbUserName = UInt16Le(lambda:sizeof(self.userName) - 2)
self.cbPassword = UInt16Le(lambda:sizeof(self.password) - 2)
self.cbAlternateShell = UInt16Le(lambda:sizeof(self.alternateShell) - 2)
self.cbWorkingDir = UInt16Le(lambda:sizeof(self.workingDir) - 2)
self.domain = UniString("coco")
self.userName = UniString("lolo")
self.password = UniString("toto")
self.alternateShell = UniString()
self.workingDir = UniString()
class RDPExtendedInfo(CompositeType):
def __init__(self):
CompositeType.__init__(self)
self.ipv6 = UInt8()
self.adress = UniString()
self.clientDir = UniString()
self.performanceFlags = UInt32Le()
self.clientAddressFamily = AfInet.AF_INET
self.cbClientAddress = UInt16Le(lambda:sizeof(self.clientAddress))
self.clientAddress = UniString("192.168.135.10")
self.cbClientDir = UInt16Le(lambda:sizeof(self.clientDir))
self.clientDir = UniString("c:\\")
#self.performanceFlags = PerfFlag.PERF_DISABLE_WALLPAPER | PerfFlag.PERF_DISABLE_MENUANIMATIONS | PerfFlag.PERF_DISABLE_CURSOR_SHADOW
class GDL(LayerAutomata):
'''
@@ -44,9 +91,32 @@ class GDL(LayerAutomata):
Constructor
'''
LayerAutomata.__init__(self, None)
#set by mcs layer channel init
self._channelId = UInt16Be()
#logon info send from client to server
self._info = RDPInfo()
self._extendedInfo = RDPExtendedInfo()
def connect(self):
'''
connect event in client mode send logon info
nextstate recv licence pdu
'''
self.sendInfoPkt()
#next state is licence info PDU
self.setNextState(self.recvLicenceInfo)
def sendInfoPkt(self):
self._transport.send(self, (SecurityFlag.SEC_INFO_PKT, UInt16Le(), RDPInfo(), RDPExtendedInfo()))
'''
send a logon info packet for RDP version 5 protocol
'''
#always send extended info because rdpy only accept rdp version 5 and more
self._transport.send(self._channelId, (SecurityFlag.SEC_INFO_PKT, UInt16Le(), self._info, self._extendedInfo))
def recvLicenceInfo(self, data):
securityFlag = UInt16Le()
securityFlagHi = UInt16Le()
data.readType((securityFlag, securityFlagHi))
if securityFlag & SecurityFlag.SEC_LICENSE_PKT != SecurityFlag.SEC_LICENSE_PKT:
raise InvalidExpectedDataException("waiting license packet")

View File

@@ -46,18 +46,18 @@ class MCS(LayerAutomata):
the main layer of RDP protocol
is why he can do everything and more!
'''
def __init__(self):
def __init__(self, presentation):
'''
ctor call base class ctor
@param presentation: presentation layer
'''
LayerAutomata.__init__(self, None)
LayerAutomata.__init__(self, presentation)
self._clientSettings = gcc.ClientSettings()
self._serverSettings = gcc.ServerSettings()
#default user Id
self._userId = UInt16Be(1)
#list of channel use in this layer and connection state
self._channelIds = {Channel.MCS_GLOBAL_CHANNEL: None}
self._channelIds = {Channel.MCS_GLOBAL_CHANNEL: presentation}
#use to record already requested channel
self._channelIdsRequest = {}
@@ -86,6 +86,7 @@ class MCS(LayerAutomata):
for (channelId, layer) in self._channelIds.iteritems():
if self._channelIdsRequest[channelId] and not layer is None:
layer._transport = self
layer._channelId = channelId
layer.connect()
def sendConnectInitial(self):
@@ -195,8 +196,7 @@ class MCS(LayerAutomata):
@param data: Stream
'''
opcode = UInt8()
confirm = UInt8()
data.readType((opcode, confirm))
data.readType(opcode)
if self.readMCSPDUHeader(opcode, DomainMCSPDU.DISCONNECT_PROVIDER_ULTIMATUM):
print "receive DISCONNECT_PROVIDER_ULTIMATUM"
@@ -215,7 +215,7 @@ class MCS(LayerAutomata):
if length & UInt8(0x80) == UInt8(0x80):
lengthP2 = UInt8()
data.readType(lengthP2)
length = (UInt16Be(length.value) << 8) | lengthP2
length = UInt16Be(length.value & 0x7f << 8 | lengthP2.value)
#channel id doesn't match a requested layer
if not self._channelIdsRequest.has_key(channelId):
@@ -229,13 +229,11 @@ class MCS(LayerAutomata):
self._channelIds[channelId].recv(data)
def send(self, fromLayer, data):
#retrieve channel id
channelId = None
for (channelIdTmp, layer) in self._channelIds.iteritems():
if layer == fromLayer:
channelId = channelIdTmp
break
def send(self, channelId, data):
'''
specific send function for channelId
@param data: message to send
'''
self._transport.send((self.writeMCSPDUHeader(DomainMCSPDU.SEND_DATA_REQUEST), self._userId, channelId, UInt8(0x70), UInt16Be(sizeof(data)) | UInt16Be(0x8000), data))

View File

@@ -8,10 +8,7 @@ class Factory(protocol.Factory):
Factory of RDP protocol
'''
def __init__(self):
mcsLayer = mcs.MCS()
#set global channel to graphic layer
mcsLayer._channelIds[mcs.Channel.MCS_GLOBAL_CHANNEL] = gdl.GDL()
self._protocol = tpkt.TPKT(tpdu.TPDU(mcsLayer))
self._protocol = tpkt.TPKT(tpdu.TPDU(mcs.MCS(gdl.GDL())))
def buildProtocol(self, addr):
return self._protocol;

View File

@@ -11,5 +11,5 @@ 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.50", 3389, rdp.Factory())
reactor.connectTCP("192.168.135.71", 3389, rdp.Factory())
reactor.run()