finish 128 bit basic rdp security layer
This commit is contained in:
@@ -34,7 +34,7 @@ h221_sc_key = "McDn";
|
|||||||
|
|
||||||
class MessageType(object):
|
class MessageType(object):
|
||||||
"""
|
"""
|
||||||
Server to Client block
|
@summary: Server to Client block
|
||||||
GCC conference messages
|
GCC conference messages
|
||||||
@see: http://msdn.microsoft.com/en-us/library/cc240509.aspx
|
@see: http://msdn.microsoft.com/en-us/library/cc240509.aspx
|
||||||
"""
|
"""
|
||||||
@@ -52,7 +52,7 @@ class MessageType(object):
|
|||||||
|
|
||||||
class ColorDepth(object):
|
class ColorDepth(object):
|
||||||
"""
|
"""
|
||||||
Depth color
|
@summary: Depth color
|
||||||
@see: http://msdn.microsoft.com/en-us/library/cc240510.aspx
|
@see: http://msdn.microsoft.com/en-us/library/cc240510.aspx
|
||||||
"""
|
"""
|
||||||
RNS_UD_COLOR_8BPP = 0xCA01
|
RNS_UD_COLOR_8BPP = 0xCA01
|
||||||
@@ -62,7 +62,7 @@ class ColorDepth(object):
|
|||||||
|
|
||||||
class HighColor(object):
|
class HighColor(object):
|
||||||
"""
|
"""
|
||||||
High color of client
|
@summary: High color of client
|
||||||
@see: http://msdn.microsoft.com/en-us/library/cc240510.aspx
|
@see: http://msdn.microsoft.com/en-us/library/cc240510.aspx
|
||||||
"""
|
"""
|
||||||
HIGH_COLOR_4BPP = 0x0004
|
HIGH_COLOR_4BPP = 0x0004
|
||||||
@@ -73,7 +73,7 @@ class HighColor(object):
|
|||||||
|
|
||||||
class Support(object):
|
class Support(object):
|
||||||
"""
|
"""
|
||||||
Supported depth flag
|
@summary: Supported depth flag
|
||||||
@see: http://msdn.microsoft.com/en-us/library/cc240510.aspx
|
@see: http://msdn.microsoft.com/en-us/library/cc240510.aspx
|
||||||
"""
|
"""
|
||||||
RNS_UD_24BPP_SUPPORT = 0x0001
|
RNS_UD_24BPP_SUPPORT = 0x0001
|
||||||
@@ -83,7 +83,7 @@ class Support(object):
|
|||||||
|
|
||||||
class CapabilityFlags(object):
|
class CapabilityFlags(object):
|
||||||
"""
|
"""
|
||||||
For more details on each flags click above
|
@summary: For more details on each flags click above
|
||||||
@see: http://msdn.microsoft.com/en-us/library/cc240510.aspx
|
@see: http://msdn.microsoft.com/en-us/library/cc240510.aspx
|
||||||
"""
|
"""
|
||||||
RNS_UD_CS_SUPPORT_ERRINFO_PDU = 0x0001
|
RNS_UD_CS_SUPPORT_ERRINFO_PDU = 0x0001
|
||||||
@@ -100,7 +100,7 @@ class CapabilityFlags(object):
|
|||||||
|
|
||||||
class ConnectionType(object):
|
class ConnectionType(object):
|
||||||
"""
|
"""
|
||||||
This information is correct if
|
@summary: This information is correct if
|
||||||
RNS_UD_CS_VALID_CONNECTION_TYPE flag is set on capabilityFlag
|
RNS_UD_CS_VALID_CONNECTION_TYPE flag is set on capabilityFlag
|
||||||
@see: http://msdn.microsoft.com/en-us/library/cc240510.aspx
|
@see: http://msdn.microsoft.com/en-us/library/cc240510.aspx
|
||||||
"""
|
"""
|
||||||
@@ -114,7 +114,7 @@ class ConnectionType(object):
|
|||||||
|
|
||||||
class Version(object):
|
class Version(object):
|
||||||
"""
|
"""
|
||||||
Supported version of RDP
|
@summary: Supported version of RDP
|
||||||
@see: http://msdn.microsoft.com/en-us/library/cc240510.aspx
|
@see: http://msdn.microsoft.com/en-us/library/cc240510.aspx
|
||||||
"""
|
"""
|
||||||
RDP_VERSION_4 = 0x00080001
|
RDP_VERSION_4 = 0x00080001
|
||||||
@@ -125,7 +125,7 @@ class Sequence(object):
|
|||||||
|
|
||||||
class Encryption(object):
|
class Encryption(object):
|
||||||
"""
|
"""
|
||||||
Encryption methods supported
|
@summary: Encryption methods supported
|
||||||
@see: http://msdn.microsoft.com/en-us/library/cc240511.aspx
|
@see: http://msdn.microsoft.com/en-us/library/cc240511.aspx
|
||||||
"""
|
"""
|
||||||
ENCRYPTION_FLAG_40BIT = 0x00000001
|
ENCRYPTION_FLAG_40BIT = 0x00000001
|
||||||
@@ -135,7 +135,7 @@ class Encryption(object):
|
|||||||
|
|
||||||
class ChannelOptions(object):
|
class ChannelOptions(object):
|
||||||
"""
|
"""
|
||||||
Channel options
|
@summary: Channel options
|
||||||
@see: http://msdn.microsoft.com/en-us/library/cc240513.aspx
|
@see: http://msdn.microsoft.com/en-us/library/cc240513.aspx
|
||||||
"""
|
"""
|
||||||
CHANNEL_OPTION_INITIALIZED = 0x80000000
|
CHANNEL_OPTION_INITIALIZED = 0x80000000
|
||||||
@@ -152,8 +152,8 @@ class ChannelOptions(object):
|
|||||||
|
|
||||||
class KeyboardType(object):
|
class KeyboardType(object):
|
||||||
"""
|
"""
|
||||||
Keyboard type
|
@summary: Keyboard type
|
||||||
IBM_101_102_KEYS is the most common keyboard type
|
@see: IBM_101_102_KEYS is the most common keyboard type
|
||||||
"""
|
"""
|
||||||
IBM_PC_XT_83_KEY = 0x00000001
|
IBM_PC_XT_83_KEY = 0x00000001
|
||||||
OLIVETTI = 0x00000002
|
OLIVETTI = 0x00000002
|
||||||
@@ -165,7 +165,7 @@ class KeyboardType(object):
|
|||||||
|
|
||||||
class KeyboardLayout(object):
|
class KeyboardLayout(object):
|
||||||
"""
|
"""
|
||||||
Keyboard layout definition
|
@summary: Keyboard layout definition
|
||||||
@see: http://technet.microsoft.com/en-us/library/cc766503%28WS.10%29.aspx
|
@see: http://technet.microsoft.com/en-us/library/cc766503%28WS.10%29.aspx
|
||||||
"""
|
"""
|
||||||
ARABIC = 0x00000401
|
ARABIC = 0x00000401
|
||||||
@@ -197,7 +197,7 @@ class CertificateType(object):
|
|||||||
|
|
||||||
class DataBlock(CompositeType):
|
class DataBlock(CompositeType):
|
||||||
"""
|
"""
|
||||||
Block settings
|
@summary: Block settings
|
||||||
"""
|
"""
|
||||||
def __init__(self, dataBlock = None):
|
def __init__(self, dataBlock = None):
|
||||||
CompositeType.__init__(self)
|
CompositeType.__init__(self)
|
||||||
|
|||||||
@@ -275,6 +275,7 @@ class LicenseManager(object):
|
|||||||
sessionKeyBlob = sec.generateMicrosoftKeyABBCCC(masterSecret, self._serverRandom, self._clientRandom)
|
sessionKeyBlob = sec.generateMicrosoftKeyABBCCC(masterSecret, self._serverRandom, self._clientRandom)
|
||||||
self._macSalt = sessionKeyBlob[:16]
|
self._macSalt = sessionKeyBlob[:16]
|
||||||
self._licenseKey = sec.finalHash(sessionKeyBlob[16:32], self._clientRandom, self._serverRandom)
|
self._licenseKey = sec.finalHash(sessionKeyBlob[16:32], self._clientRandom, self._serverRandom)
|
||||||
|
self._rc4LicenseKey = rc4.RC4Key(self._licenseKey)
|
||||||
|
|
||||||
def recv(self, s):
|
def recv(self, s):
|
||||||
"""
|
"""
|
||||||
@@ -324,7 +325,7 @@ class LicenseManager(object):
|
|||||||
"""
|
"""
|
||||||
#decrypt server challenge
|
#decrypt server challenge
|
||||||
#it should be TEST word in unicode format
|
#it should be TEST word in unicode format
|
||||||
serverChallenge = rc4.crypt(self._licenseKey, self._serverEncryptedChallenge)
|
serverChallenge = rc4.crypt(self._rc4LicenseKey, self._serverEncryptedChallenge)
|
||||||
|
|
||||||
#generate hwid
|
#generate hwid
|
||||||
s = Stream()
|
s = Stream()
|
||||||
@@ -333,7 +334,7 @@ class LicenseManager(object):
|
|||||||
|
|
||||||
message = ClientPLatformChallengeResponse()
|
message = ClientPLatformChallengeResponse()
|
||||||
message.encryptedPlatformChallengeResponse.blobData.value = self._serverEncryptedChallenge
|
message.encryptedPlatformChallengeResponse.blobData.value = self._serverEncryptedChallenge
|
||||||
message.encryptedHWID.blobData.value = rc4.crypt(self._licenseKey, hwid)
|
message.encryptedHWID.blobData.value = rc4.crypt(self._rc4LicenseKey, hwid)
|
||||||
message.MACData.value = sec.macData(self._macSalt, serverChallenge + hwid)
|
message.MACData.value = sec.macData(self._macSalt, serverChallenge + hwid)
|
||||||
|
|
||||||
self._transport.sendFlagged(sec.SecurityFlag.SEC_LICENSE_PKT, LicPacket(message))
|
self._transport.sendFlagged(sec.SecurityFlag.SEC_LICENSE_PKT, LicPacket(message))
|
||||||
@@ -362,8 +362,9 @@ class PointerCapability(CompositeType):
|
|||||||
def __init__(self, readLen = None):
|
def __init__(self, readLen = None):
|
||||||
CompositeType.__init__(self, readLen = readLen)
|
CompositeType.__init__(self, readLen = readLen)
|
||||||
self.colorPointerFlag = UInt16Le()
|
self.colorPointerFlag = UInt16Le()
|
||||||
self.colorPointerCacheSize = UInt16Le()
|
self.colorPointerCacheSize = UInt16Le(20)
|
||||||
self.pointerCacheSize = UInt16Le()
|
#old version of rdp doesn't support ...
|
||||||
|
#self.pointerCacheSize = UInt16Le()
|
||||||
|
|
||||||
class InputCapability(CompositeType):
|
class InputCapability(CompositeType):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -24,8 +24,7 @@ In this layer are managed all mains bitmap update orders end user inputs
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
from rdpy.core.layer import LayerAutomata
|
from rdpy.core.layer import LayerAutomata
|
||||||
from rdpy.core.error import InvalidExpectedDataException, CallPureVirtualFuntion
|
from rdpy.core.error import CallPureVirtualFuntion
|
||||||
from rdpy.core.type import UInt16Le
|
|
||||||
import rdpy.core.log as log
|
import rdpy.core.log as log
|
||||||
import rdpy.protocol.rdp.gcc as gcc
|
import rdpy.protocol.rdp.gcc as gcc
|
||||||
import rdpy.protocol.rdp.tpkt as tpkt
|
import rdpy.protocol.rdp.tpkt as tpkt
|
||||||
@@ -71,7 +70,7 @@ class PDUServerListener(object):
|
|||||||
"""
|
"""
|
||||||
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "onSlowPathInput", "PDUServerListener"))
|
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "onSlowPathInput", "PDUServerListener"))
|
||||||
|
|
||||||
class PDULayer(LayerAutomata):
|
class PDULayer(LayerAutomata, tpkt.IFastPathListener):
|
||||||
"""
|
"""
|
||||||
@summary: Global channel for MCS that handle session
|
@summary: Global channel for MCS that handle session
|
||||||
identification user, licensing management, and capabilities exchange
|
identification user, licensing management, and capabilities exchange
|
||||||
@@ -106,6 +105,15 @@ class PDULayer(LayerAutomata):
|
|||||||
}
|
}
|
||||||
#share id between client and server
|
#share id between client and server
|
||||||
self._shareId = 0x103EA
|
self._shareId = 0x103EA
|
||||||
|
#enable or not fast path
|
||||||
|
self._fastPathSender = None
|
||||||
|
|
||||||
|
def setFastPathSender(self, fastPathSender):
|
||||||
|
"""
|
||||||
|
@param fastPathSender: {tpkt.FastPathSender}
|
||||||
|
@note: implement tpkt.IFastPathListener
|
||||||
|
"""
|
||||||
|
self._fastPathSender = fastPathSender
|
||||||
|
|
||||||
def sendPDU(self, pduMessage):
|
def sendPDU(self, pduMessage):
|
||||||
"""
|
"""
|
||||||
@@ -121,7 +129,7 @@ class PDULayer(LayerAutomata):
|
|||||||
"""
|
"""
|
||||||
self.sendPDU(data.DataPDU(pduData, self._shareId))
|
self.sendPDU(data.DataPDU(pduData, self._shareId))
|
||||||
|
|
||||||
class Client(PDULayer, tpkt.IFastPathListener):
|
class Client(PDULayer):
|
||||||
"""
|
"""
|
||||||
@summary: Client automata of PDU layer
|
@summary: Client automata of PDU layer
|
||||||
"""
|
"""
|
||||||
@@ -131,8 +139,6 @@ class Client(PDULayer, tpkt.IFastPathListener):
|
|||||||
"""
|
"""
|
||||||
PDULayer.__init__(self)
|
PDULayer.__init__(self)
|
||||||
self._listener = listener
|
self._listener = listener
|
||||||
#enable or not fast path
|
|
||||||
self._fastPathSender = None
|
|
||||||
|
|
||||||
def connect(self):
|
def connect(self):
|
||||||
"""
|
"""
|
||||||
@@ -149,13 +155,6 @@ class Client(PDULayer, tpkt.IFastPathListener):
|
|||||||
"""
|
"""
|
||||||
self._transport.close()
|
self._transport.close()
|
||||||
#self.sendDataPDU(data.ShutdownRequestPDU())
|
#self.sendDataPDU(data.ShutdownRequestPDU())
|
||||||
|
|
||||||
def setFastPathSender(self, fastPathSender):
|
|
||||||
"""
|
|
||||||
@param fastPathSender: tpkt.FastPathSender
|
|
||||||
@note: implement tpkt.IFastPathListener
|
|
||||||
"""
|
|
||||||
self._fastPathSender = fastPathSender
|
|
||||||
|
|
||||||
def recvDemandActivePDU(self, s):
|
def recvDemandActivePDU(self, s):
|
||||||
"""
|
"""
|
||||||
@@ -267,11 +266,12 @@ class Client(PDULayer, tpkt.IFastPathListener):
|
|||||||
#http://msdn.microsoft.com/en-us/library/cc240454.aspx
|
#http://msdn.microsoft.com/en-us/library/cc240454.aspx
|
||||||
self.setNextState(self.recvDemandActivePDU)
|
self.setNextState(self.recvDemandActivePDU)
|
||||||
|
|
||||||
def recvFastPath(self, fastPathS):
|
def recvFastPath(self, secFlag, fastPathS):
|
||||||
"""
|
"""
|
||||||
@summary: Implement IFastPathListener interface
|
@summary: Implement IFastPathListener interface
|
||||||
Fast path is needed by RDP 8.0
|
Fast path is needed by RDP 8.0
|
||||||
@param fastPathS: Stream that contain fast path data
|
@param fastPathS: {Stream} that contain fast path data
|
||||||
|
@param secFlag: {SecFlags}
|
||||||
"""
|
"""
|
||||||
fastPathPDU = data.FastPathUpdatePDU()
|
fastPathPDU = data.FastPathUpdatePDU()
|
||||||
fastPathS.readType(fastPathPDU)
|
fastPathS.readType(fastPathPDU)
|
||||||
@@ -343,7 +343,7 @@ class Client(PDULayer, tpkt.IFastPathListener):
|
|||||||
|
|
||||||
def sendClientFinalizeSynchronizePDU(self):
|
def sendClientFinalizeSynchronizePDU(self):
|
||||||
"""
|
"""
|
||||||
send a synchronize PDU from client to server
|
@summary: send a synchronize PDU from client to server
|
||||||
"""
|
"""
|
||||||
synchronizePDU = data.SynchronizeDataPDU(self._transport._transport.getChannelId())
|
synchronizePDU = data.SynchronizeDataPDU(self._transport._transport.getChannelId())
|
||||||
self.sendDataPDU(synchronizePDU)
|
self.sendDataPDU(synchronizePDU)
|
||||||
@@ -371,7 +371,7 @@ class Client(PDULayer, tpkt.IFastPathListener):
|
|||||||
pdu.slowPathInputEvents._array = [data.SlowPathInputEvent(x) for x in pointerEvents]
|
pdu.slowPathInputEvents._array = [data.SlowPathInputEvent(x) for x in pointerEvents]
|
||||||
self.sendDataPDU(pdu)
|
self.sendDataPDU(pdu)
|
||||||
|
|
||||||
class Server(PDULayer, tpkt.IFastPathListener):
|
class Server(PDULayer):
|
||||||
"""
|
"""
|
||||||
Server Automata of PDU layer
|
Server Automata of PDU layer
|
||||||
"""
|
"""
|
||||||
@@ -389,14 +389,7 @@ class Server(PDULayer, tpkt.IFastPathListener):
|
|||||||
Connect message for server automata
|
Connect message for server automata
|
||||||
"""
|
"""
|
||||||
self.sendDemandActivePDU()
|
self.sendDemandActivePDU()
|
||||||
self.setNextState(self.recvConfirmActivePDU)
|
self.setNextState(self.recvConfirmActivePDU)
|
||||||
|
|
||||||
def setFastPathSender(self, fastPathSender):
|
|
||||||
"""
|
|
||||||
@param fastPathSender: tpkt.FastPathSender
|
|
||||||
@note: implement tpkt.IFastPathListener
|
|
||||||
"""
|
|
||||||
self._fastPathSender = fastPathSender
|
|
||||||
|
|
||||||
def recvConfirmActivePDU(self, s):
|
def recvConfirmActivePDU(self, s):
|
||||||
"""
|
"""
|
||||||
@@ -588,7 +581,8 @@ class Server(PDULayer, tpkt.IFastPathListener):
|
|||||||
#fast path case
|
#fast path case
|
||||||
fastPathUpdateDataPDU = data.FastPathBitmapUpdateDataPDU()
|
fastPathUpdateDataPDU = data.FastPathBitmapUpdateDataPDU()
|
||||||
fastPathUpdateDataPDU.rectangles._array = bitmapDatas
|
fastPathUpdateDataPDU.rectangles._array = bitmapDatas
|
||||||
self._fastPathSender.sendFastPath(data.FastPathUpdatePDU(fastPathUpdateDataPDU))
|
self._fastPathSender.sendFastPath(0, data.FastPathUpdatePDU(fastPathUpdateDataPDU))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
#slow path case
|
#slow path case
|
||||||
updateDataPDU = data.BitmapUpdateDataPDU()
|
updateDataPDU = data.BitmapUpdateDataPDU()
|
||||||
|
|||||||
@@ -50,7 +50,8 @@ def RC4(key):
|
|||||||
S = KSA(key)
|
S = KSA(key)
|
||||||
return PRGA(S)
|
return PRGA(S)
|
||||||
|
|
||||||
def crypt(key, plaintext):
|
def RC4Key(key):
|
||||||
keystream = RC4([ord(c) for c in key])
|
return RC4([ord(c) for c in key])
|
||||||
|
|
||||||
|
def crypt(keystream, plaintext):
|
||||||
return "".join([chr(ord(c) ^ keystream.next()) for c in plaintext])
|
return "".join([chr(ord(c) ^ keystream.next()) for c in plaintext])
|
||||||
@@ -45,7 +45,10 @@ class RDPClientController(pdu.layer.PDUClientListener):
|
|||||||
#transport pdu layer
|
#transport pdu layer
|
||||||
self._x224Layer = x224.Client(self._mcsLayer)
|
self._x224Layer = x224.Client(self._mcsLayer)
|
||||||
#transport packet (protocol layer)
|
#transport packet (protocol layer)
|
||||||
self._tpktLayer = tpkt.TPKT(self._x224Layer, self._pduLayer)
|
self._tpktLayer = tpkt.TPKT(self._x224Layer)
|
||||||
|
#fastpath stack
|
||||||
|
self._pduLayer.initFastPath(self._secLayer)
|
||||||
|
self._secLayer.initFastPath(self._tpktLayer)
|
||||||
#is pdu layer is ready to send
|
#is pdu layer is ready to send
|
||||||
self._isReady = False
|
self._isReady = False
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,8 @@
|
|||||||
Some use full methods for security in RDP
|
Some use full methods for security in RDP
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import sha, md5, rsa, gcc, rc4, lic
|
import sha, md5, rsa, rc4
|
||||||
|
import gcc, lic, tpkt
|
||||||
from rdpy.core.type import CompositeType, Stream, UInt32Le, UInt16Le, String, sizeof, UInt8
|
from rdpy.core.type import CompositeType, Stream, UInt32Le, UInt16Le, String, sizeof, UInt8
|
||||||
from rdpy.core.layer import LayerAutomata, IStreamSender
|
from rdpy.core.layer import LayerAutomata, IStreamSender
|
||||||
from rdpy.core.error import InvalidExpectedDataException
|
from rdpy.core.error import InvalidExpectedDataException
|
||||||
@@ -238,7 +239,7 @@ class RDPExtendedInfo(CompositeType):
|
|||||||
self.clientSessionId = UInt32Le()
|
self.clientSessionId = UInt32Le()
|
||||||
self.performanceFlags = UInt32Le()
|
self.performanceFlags = UInt32Le()
|
||||||
|
|
||||||
class SecLayer(LayerAutomata, IStreamSender):
|
class SecLayer(LayerAutomata, IStreamSender, tpkt.IFastPathListener, tpkt.IFastPathSender):
|
||||||
"""
|
"""
|
||||||
@summary: Basic RDP security manager
|
@summary: Basic RDP security manager
|
||||||
This layer is Transparent as possible for upper layer
|
This layer is Transparent as possible for upper layer
|
||||||
@@ -248,10 +249,25 @@ class SecLayer(LayerAutomata, IStreamSender):
|
|||||||
@param presentation: Layer (generally pdu layer)
|
@param presentation: Layer (generally pdu layer)
|
||||||
"""
|
"""
|
||||||
LayerAutomata.__init__(self, presentation)
|
LayerAutomata.__init__(self, presentation)
|
||||||
|
#thios layer is like a fastpath proxy
|
||||||
|
self._fastPathTransport = None
|
||||||
|
self._fastPathPresentation = None
|
||||||
|
|
||||||
|
#credentials
|
||||||
self._info = RDPInfo(extendedInfoConditional = lambda:(self._transport.getGCCServerSettings().getBlock(gcc.MessageType.SC_CORE).rdpVersion.value == gcc.Version.RDP_VERSION_5_PLUS))
|
self._info = RDPInfo(extendedInfoConditional = lambda:(self._transport.getGCCServerSettings().getBlock(gcc.MessageType.SC_CORE).rdpVersion.value == gcc.Version.RDP_VERSION_5_PLUS))
|
||||||
|
|
||||||
|
#True if classic encryption is enable
|
||||||
self._enableEncryption = False
|
self._enableEncryption = False
|
||||||
|
|
||||||
|
#crypto random
|
||||||
|
self._clientRandom = None
|
||||||
|
self._serverRandom = None
|
||||||
|
#initialise decrypt and encrypt keys
|
||||||
self._decryt = None
|
self._decryt = None
|
||||||
self._encrypt = None
|
self._encrypt = None
|
||||||
|
#current rc4 map key
|
||||||
|
self._decryptRc4 = None
|
||||||
|
self._encryptRc4 = None
|
||||||
|
|
||||||
def generateKeys(self):
|
def generateKeys(self):
|
||||||
"""
|
"""
|
||||||
@@ -273,7 +289,12 @@ class SecLayer(LayerAutomata, IStreamSender):
|
|||||||
signature = String(readLen = UInt8(8))
|
signature = String(readLen = UInt8(8))
|
||||||
encryptedPayload = String()
|
encryptedPayload = String()
|
||||||
s.readType((signature, encryptedPayload))
|
s.readType((signature, encryptedPayload))
|
||||||
return Stream(rc4.crypt(self._decrypt, encryptedPayload.value))
|
decrypted = rc4.crypt(self._decryptRc4, encryptedPayload.value)
|
||||||
|
#ckeck signature
|
||||||
|
if macData(self._macKey128, decrypted)[:8] != signature.value:
|
||||||
|
raise InvalidExpectedDataException("Bad packet signature")
|
||||||
|
|
||||||
|
return Stream(decrypted)
|
||||||
|
|
||||||
def writeEncryptedPayload(self, data):
|
def writeEncryptedPayload(self, data):
|
||||||
"""
|
"""
|
||||||
@@ -283,7 +304,7 @@ class SecLayer(LayerAutomata, IStreamSender):
|
|||||||
"""
|
"""
|
||||||
s = Stream()
|
s = Stream()
|
||||||
s.writeType(data)
|
s.writeType(data)
|
||||||
return (String(macData(self._macKey128, s.getvalue())[:8]), String(rc4.crypt(self._encrypt, s.getvalue())))
|
return (String(macData(self._macKey128, s.getvalue())[:8]), String(rc4.crypt(self._encryptRc4, s.getvalue())))
|
||||||
|
|
||||||
def recv(self, data):
|
def recv(self, data):
|
||||||
"""
|
"""
|
||||||
@@ -301,7 +322,7 @@ class SecLayer(LayerAutomata, IStreamSender):
|
|||||||
|
|
||||||
if securityFlag.value & SecurityFlag.SEC_ENCRYPT:
|
if securityFlag.value & SecurityFlag.SEC_ENCRYPT:
|
||||||
data = self.readEncryptedPayload(data)
|
data = self.readEncryptedPayload(data)
|
||||||
|
|
||||||
self._presentation.recv(data)
|
self._presentation.recv(data)
|
||||||
|
|
||||||
def send(self, data):
|
def send(self, data):
|
||||||
@@ -324,16 +345,44 @@ class SecLayer(LayerAutomata, IStreamSender):
|
|||||||
@param flag: {integer} security flag
|
@param flag: {integer} security flag
|
||||||
@param data: {Type | Tuple}
|
@param data: {Type | Tuple}
|
||||||
"""
|
"""
|
||||||
if self._enableEncryption:
|
if flag & SecurityFlag.SEC_ENCRYPT:
|
||||||
flag |= SecurityFlag.SEC_ENCRYPT
|
|
||||||
data = self.writeEncryptedPayload(data)
|
data = self.writeEncryptedPayload(data)
|
||||||
self.__sendFlagged__(flag, data)
|
|
||||||
|
|
||||||
def __sendFlagged__(self, flag, data):
|
|
||||||
"""
|
|
||||||
@summary: format basic message of security layer
|
|
||||||
"""
|
|
||||||
self._transport.send((UInt16Le(flag), UInt16Le(), data))
|
self._transport.send((UInt16Le(flag), UInt16Le(), data))
|
||||||
|
|
||||||
|
def recvFastPath(self, secFlag, fastPathS):
|
||||||
|
"""
|
||||||
|
@summary: Call when fast path packet is received
|
||||||
|
@param secFlag: {SecFlags}
|
||||||
|
@param fastPathS: {Stream}
|
||||||
|
"""
|
||||||
|
if self._enableEncryption and secFlag & tpkt.SecFlags.FASTPATH_OUTPUT_ENCRYPTED:
|
||||||
|
fastPathS = self.readEncryptedPayload(fastPathS)
|
||||||
|
|
||||||
|
self._fastPathPresentation.recvFastPath(secFlag, fastPathS)
|
||||||
|
|
||||||
|
def setFastPathListener(self, fastPathListener):
|
||||||
|
"""
|
||||||
|
@param fastPathListener : {IFastPathListener}
|
||||||
|
"""
|
||||||
|
self._fastPathPresentation = fastPathListener
|
||||||
|
|
||||||
|
def sendFastPath(self, secFlag, fastPathS):
|
||||||
|
"""
|
||||||
|
@summary: Send fastPathS Type as fast path packet
|
||||||
|
@param secFlag: {SecFlags}
|
||||||
|
@param fastPathS: {Stream} type transform to stream and send as fastpath
|
||||||
|
"""
|
||||||
|
if self._enableEncryption:
|
||||||
|
secFlag |= tpkt.SecFlags.FASTPATH_OUTPUT_ENCRYPTED
|
||||||
|
fastPathS = self.writeEncryptedPayload(fastPathS)
|
||||||
|
|
||||||
|
self._fastPathTransport.sendFastPath(secFlag, fastPathS)
|
||||||
|
|
||||||
|
def setFastPathSender(self, fastPathSender):
|
||||||
|
"""
|
||||||
|
@param fastPathSender: {tpkt.FastPathSender}
|
||||||
|
"""
|
||||||
|
self._fastPathTransport = fastPathSender
|
||||||
|
|
||||||
class Client(SecLayer):
|
class Client(SecLayer):
|
||||||
"""
|
"""
|
||||||
@@ -352,19 +401,27 @@ class Client(SecLayer):
|
|||||||
self._clientRandom = rsa.randnum.read_random_bits(256)
|
self._clientRandom = rsa.randnum.read_random_bits(256)
|
||||||
self._serverRandom = self._transport.getGCCServerSettings().getBlock(gcc.MessageType.SC_SECURITY).serverRandom.value
|
self._serverRandom = self._transport.getGCCServerSettings().getBlock(gcc.MessageType.SC_SECURITY).serverRandom.value
|
||||||
self._decrypt, self._encrypt = self.generateKeys()
|
self._decrypt, self._encrypt = self.generateKeys()
|
||||||
|
self._decryptRc4 = rc4.RC4Key(self._decrypt)
|
||||||
|
self._encryptRc4 = rc4.RC4Key(self._encrypt)
|
||||||
|
|
||||||
#send client random encrypted with
|
#send client random encrypted with
|
||||||
certificate = self._transport.getGCCServerSettings().getBlock(gcc.MessageType.SC_SECURITY).serverCertificate.certData
|
certificate = self._transport.getGCCServerSettings().getBlock(gcc.MessageType.SC_SECURITY).serverCertificate.certData
|
||||||
|
#reverse because bignum in little endian
|
||||||
serverPublicKey = rsa.PublicKey(bin2bn(certificate.PublicKeyBlob.modulus.value[::-1]), certificate.PublicKeyBlob.pubExp.value)
|
serverPublicKey = rsa.PublicKey(bin2bn(certificate.PublicKeyBlob.modulus.value[::-1]), certificate.PublicKeyBlob.pubExp.value)
|
||||||
|
|
||||||
message = ClientSecurityExchangePDU()
|
message = ClientSecurityExchangePDU()
|
||||||
|
#reverse because bignum in little endian
|
||||||
message.encryptedClientRandom.value = rsa.encrypt(self._clientRandom[::-1], serverPublicKey)[::-1]
|
message.encryptedClientRandom.value = rsa.encrypt(self._clientRandom[::-1], serverPublicKey)[::-1]
|
||||||
self.sendFlagged(SecurityFlag.SEC_EXCHANGE_PKT, message)
|
self.sendFlagged(SecurityFlag.SEC_EXCHANGE_PKT, message)
|
||||||
|
|
||||||
#now all messages must be encrypted
|
#now all messages must be encrypted
|
||||||
self._enableEncryption = True
|
self._enableEncryption = True
|
||||||
|
|
||||||
self.sendFlagged(SecurityFlag.SEC_INFO_PKT, self._info)
|
secFlag = SecurityFlag.SEC_INFO_PKT
|
||||||
|
if self._enableEncryption:
|
||||||
|
secFlag |= SecurityFlag.SEC_ENCRYPT
|
||||||
|
self.sendFlagged(secFlag, self._info)
|
||||||
|
|
||||||
self.setNextState(self.recvLicenceInfo)
|
self.setNextState(self.recvLicenceInfo)
|
||||||
|
|
||||||
def recvLicenceInfo(self, s):
|
def recvLicenceInfo(self, s):
|
||||||
|
|||||||
@@ -33,36 +33,67 @@ class Action(object):
|
|||||||
"""
|
"""
|
||||||
FASTPATH_ACTION_FASTPATH = 0x0
|
FASTPATH_ACTION_FASTPATH = 0x0
|
||||||
FASTPATH_ACTION_X224 = 0x3
|
FASTPATH_ACTION_X224 = 0x3
|
||||||
|
|
||||||
|
class SecFlags(object):
|
||||||
|
"""
|
||||||
|
@see: http://msdn.microsoft.com/en-us/library/cc240621.aspx
|
||||||
|
"""
|
||||||
|
#hihi 'secure' checksum but private key is public !!!
|
||||||
|
FASTPATH_OUTPUT_SECURE_CHECKSUM = 0x1
|
||||||
|
FASTPATH_OUTPUT_ENCRYPTED = 0x2
|
||||||
|
|
||||||
class IFastPathListener(object):
|
class IFastPathListener(object):
|
||||||
"""
|
"""
|
||||||
@summary: Fast path packet listener
|
@summary: Fast path packet listener
|
||||||
Usually X224 layer
|
Usually X224 layer
|
||||||
"""
|
"""
|
||||||
def recvFastPath(self, fastPathS):
|
def recvFastPath(self, secFlag, fastPathS):
|
||||||
"""
|
"""
|
||||||
@summary: Call when fast path packet is received
|
@summary: Call when fast path packet is received
|
||||||
@param fastPathS: Stream
|
@param secFlag: {SecFlags}
|
||||||
|
@param fastPathS: {Stream}
|
||||||
"""
|
"""
|
||||||
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "recvFastPath", "recvFastPath"))
|
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "recvFastPath", "IFastPathListener"))
|
||||||
|
|
||||||
|
def initFastPath(self, fastPathSender):
|
||||||
|
"""
|
||||||
|
@summary: initialize stack
|
||||||
|
@param fastPathSender: {IFastPathSender}
|
||||||
|
"""
|
||||||
|
self.setFastPathSender(fastPathSender)
|
||||||
|
fastPathSender.setFastPathListener(self)
|
||||||
|
|
||||||
def setFastPathSender(self, fastPathSender):
|
def setFastPathSender(self, fastPathSender):
|
||||||
"""
|
"""
|
||||||
@summary: Call to set a fast path sender to listener
|
@param fastPathSender : {IFastPathSender}
|
||||||
@param fastPathSender: IFastPathSender
|
|
||||||
"""
|
"""
|
||||||
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "setFastPathSender", "recvFastPath"))
|
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "setFastPathSender", "IFastPathListener"))
|
||||||
|
|
||||||
class IFastPathSender(object):
|
class IFastPathSender(object):
|
||||||
"""
|
"""
|
||||||
@summary: Fast path send capability
|
@summary: Fast path send capability
|
||||||
"""
|
"""
|
||||||
def sendFastPath(self, fastPathS):
|
def sendFastPath(self, secFlag, fastPathS):
|
||||||
"""
|
"""
|
||||||
@summary: Send fastPathS Type as fast path packet
|
@summary: Send fastPathS Type as fast path packet
|
||||||
|
@param secFlag: {SecFlags}
|
||||||
@param fastPathS: type transform to stream and send as fastpath
|
@param fastPathS: type transform to stream and send as fastpath
|
||||||
"""
|
"""
|
||||||
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "sendFastPath", "IFastPathSender"))
|
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "sendFastPath", "IFastPathSender"))
|
||||||
|
|
||||||
|
def initFastPath(self, fastPathListener):
|
||||||
|
"""
|
||||||
|
@summary: initialize stack
|
||||||
|
@param fastPathListener: {IFastPathListener}
|
||||||
|
"""
|
||||||
|
self.setFastPathListener(fastPathListener)
|
||||||
|
fastPathListener.setFastPathSender(self)
|
||||||
|
|
||||||
|
def setFastPathListener(self, fastPathListener):
|
||||||
|
"""
|
||||||
|
@param fastPathListener: {IFastPathListener}
|
||||||
|
"""
|
||||||
|
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "setFastPathListener", "IFastPathSender"))
|
||||||
|
|
||||||
class TPKT(RawLayer, IFastPathSender):
|
class TPKT(RawLayer, IFastPathSender):
|
||||||
"""
|
"""
|
||||||
@@ -70,21 +101,25 @@ class TPKT(RawLayer, IFastPathSender):
|
|||||||
represent the Raw Layer in stack (first layer)
|
represent the Raw Layer in stack (first layer)
|
||||||
This layer only handle size of packet and determine if is a fast path packet
|
This layer only handle size of packet and determine if is a fast path packet
|
||||||
"""
|
"""
|
||||||
def __init__(self, presentation, fastPathListener = None):
|
def __init__(self, presentation):
|
||||||
"""
|
"""
|
||||||
@param presentation: presentation layer, in RDP case is x224 layer
|
@param presentation: presentation layer, in RDP case is x224 layer
|
||||||
@param fastPathListener: IFastPathListener
|
|
||||||
"""
|
"""
|
||||||
RawLayer.__init__(self, presentation)
|
RawLayer.__init__(self, presentation)
|
||||||
#length may be coded on more than 1 bytes
|
#length may be coded on more than 1 bytes
|
||||||
self._lastShortLength = UInt8()
|
self._lastShortLength = UInt8()
|
||||||
#fast path listener
|
#fast path listener
|
||||||
|
self._fastPathListener = None
|
||||||
|
#last secure flag
|
||||||
|
self._secFlag = 0
|
||||||
|
|
||||||
|
def setFastPathListener(self, fastPathListener):
|
||||||
|
"""
|
||||||
|
@param fastPathListener : {IFastPathListener}
|
||||||
|
@note: implement IFastPathSender
|
||||||
|
"""
|
||||||
self._fastPathListener = fastPathListener
|
self._fastPathListener = fastPathListener
|
||||||
|
|
||||||
if not fastPathListener is None:
|
|
||||||
#set me as fast path sender
|
|
||||||
fastPathListener.setFastPathSender(self)
|
|
||||||
|
|
||||||
def connect(self):
|
def connect(self):
|
||||||
"""
|
"""
|
||||||
@summary: Call when transport layer connection
|
@summary: Call when transport layer connection
|
||||||
@@ -112,6 +147,7 @@ class TPKT(RawLayer, IFastPathSender):
|
|||||||
self.expect(2, self.readExtendedHeader)
|
self.expect(2, self.readExtendedHeader)
|
||||||
else:
|
else:
|
||||||
#is fast path packet
|
#is fast path packet
|
||||||
|
self._secFlag = version.value >> 6
|
||||||
data.readType(self._lastShortLength)
|
data.readType(self._lastShortLength)
|
||||||
if self._lastShortLength.value & 0x80:
|
if self._lastShortLength.value & 0x80:
|
||||||
#size is 1 byte more
|
#size is 1 byte more
|
||||||
@@ -147,7 +183,7 @@ class TPKT(RawLayer, IFastPathSender):
|
|||||||
Fast path data
|
Fast path data
|
||||||
@param data: Stream from twisted layer
|
@param data: Stream from twisted layer
|
||||||
"""
|
"""
|
||||||
self._fastPathListener.recvFastPath(data)
|
self._fastPathListener.recvFastPath(self._secFlag, data)
|
||||||
self.expect(2, self.readHeader)
|
self.expect(2, self.readHeader)
|
||||||
|
|
||||||
def readData(self, data):
|
def readData(self, data):
|
||||||
@@ -166,8 +202,9 @@ class TPKT(RawLayer, IFastPathSender):
|
|||||||
"""
|
"""
|
||||||
RawLayer.send(self, (UInt8(Action.FASTPATH_ACTION_X224), UInt8(0), UInt16Be(sizeof(message) + 4), message))
|
RawLayer.send(self, (UInt8(Action.FASTPATH_ACTION_X224), UInt8(0), UInt16Be(sizeof(message) + 4), message))
|
||||||
|
|
||||||
def sendFastPath(self, fastPathS):
|
def sendFastPath(self, secFlag, fastPathS):
|
||||||
"""
|
"""
|
||||||
@param fastPathS: type transform to stream and send as fastpath
|
@param fastPathS: type transform to stream and send as fastpath
|
||||||
|
@param secFlag: {SecFlags}
|
||||||
"""
|
"""
|
||||||
RawLayer.send(self, (UInt8(Action.FASTPATH_ACTION_FASTPATH), UInt16Be((sizeof(fastPathS) + 3) | 0x8000), fastPathS))
|
RawLayer.send(self, (UInt8(Action.FASTPATH_ACTION_FASTPATH | secFlag), UInt16Be((sizeof(fastPathS) + 3) | 0x8000), fastPathS))
|
||||||
@@ -132,7 +132,7 @@ class X224Layer(LayerAutomata, IStreamSender):
|
|||||||
LayerAutomata.__init__(self, presentation)
|
LayerAutomata.__init__(self, presentation)
|
||||||
#default selectedProtocol is SSl
|
#default selectedProtocol is SSl
|
||||||
#client requested selectedProtocol
|
#client requested selectedProtocol
|
||||||
self._requestedProtocol = Protocols.PROTOCOL_RDP
|
self._requestedProtocol = Protocols.PROTOCOL_RDP | Protocols.PROTOCOL_SSL
|
||||||
#server selected selectedProtocol
|
#server selected selectedProtocol
|
||||||
self._selectedProtocol = Protocols.PROTOCOL_SSL
|
self._selectedProtocol = Protocols.PROTOCOL_SSL
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user