add hostname support + finish license automata

This commit is contained in:
speyrefitte
2014-12-01 18:06:08 +01:00
parent 99198321a4
commit fa25a40721
6 changed files with 50 additions and 32 deletions

View File

@@ -21,7 +21,7 @@
example of use rdpy as rdp client
"""
import sys, os, getopt
import sys, os, getopt, socket
from PyQt4 import QtGui, QtCore
from rdpy.ui.qt4 import RDPClientQt
@@ -77,6 +77,7 @@ class RDPClientQtFactory(rdp.ClientFactory):
controller.setPassword(self._passwod)
controller.setDomain(self._domain)
controller.setKeyboardLayout(self._keyboardLayout)
controller.setHostname(socket.gethostname())
if self._optimized:
controller.setPerformanceSession()

View File

@@ -37,7 +37,7 @@ from rdpy.ui import view
from twisted.internet import reactor
from PyQt4 import QtCore, QtGui
log._LOG_LEVEL = log.Level.INFO
#log._LOG_LEVEL = log.Level.INFO
class ProxyServer(rdp.RDPServerObserver):
"""

View File

@@ -136,8 +136,7 @@ class Client(PDULayer, tpkt.IFastPathListener):
self._listener = listener
#enable or not fast path
self._fastPathSender = None
#todo generate hostname
self._licenceManager = lic.LicenseManager(self, self._info.userName.value, "wav-glw-009")
self._licenceManager = lic.LicenseManager(self)
def connect(self):
"""
@@ -592,8 +591,7 @@ class Server(PDULayer, tpkt.IFastPathListener):
def sendDemandActivePDU(self):
"""
Send server capabilities
server automata PDU
@summary: Send server capabilities server automata PDU
"""
#init general capability
generalCapability = self._serverCapabilities[caps.CapsType.CAPSTYPE_GENERAL].capability

View File

@@ -90,6 +90,7 @@ class Preambule(object):
"""
PREAMBLE_VERSION_2_0 = 0x2
PREAMBLE_VERSION_3_0 = 0x3
EXTENDED_ERROR_MSG_SUPPORTED = 0x80
class LicenseBinaryBlob(CompositeType):
"""
@@ -208,13 +209,13 @@ class ClientPLatformChallengeResponse(CompositeType):
def __init__(self):
CompositeType.__init__(self)
self.encryptedPlatformChallengeResponse = LicenseBinaryBlob(BinaryBlobType.BB_ENCRYPTED_DATA_BLOB)
self.encryptedHWID = LicenseBinaryBlob(BinaryBlobType.BB_ENCRYPTED_DATA_BLOB)
self.encryptedPlatformChallengeResponse = LicenseBinaryBlob(BinaryBlobType.BB_DATA_BLOB)
self.encryptedHWID = LicenseBinaryBlob(BinaryBlobType.BB_DATA_BLOB)
self.MACData = String(readLen = UInt8(16))
class LicPacket(CompositeType):
"""
A license packet
@summary: A license packet
"""
def __init__(self, message = None):
CompositeType.__init__(self)
@@ -225,7 +226,7 @@ class LicPacket(CompositeType):
def LicensingMessageFactory():
"""
factory for message nego
@summary: factory for message nego
Use in read mode
"""
for c in [LicensingErrorMessage, ServerLicenseRequest, ClientNewLicenseRequest, ServerPlatformChallenge, ClientPLatformChallengeResponse]:
@@ -249,32 +250,33 @@ def createValidClientLicensingErrorMessage():
message = LicensingErrorMessage()
message.dwErrorCode.value = ErrorCode.STATUS_VALID_CLIENT
message.dwStateTransition.value = StateTransition.ST_NO_TRANSITION
return LicPacket(message = message)
return LicPacket(message)
class LicenseManager(object):
"""
@summary: handle license automata
@see: http://msdn.microsoft.com/en-us/library/cc241890.aspx
"""
def __init__(self, transport, username, hostname):
def __init__(self, transport):
"""
@param transport: layer use to send packet
"""
self._preMasterSecret = "\x00" * 64
self._clientRandom = "\x00" * 32
self._serverRandom = None
self._serverEncryptedChallenge = None
self._transport = transport
self._username = username
self._hostname = hostname
self._username = ""
self._hostname = ""
def generateKeys(self):
"""
@summary: generate key for license session
"""
self._masterSecret = sec.generateMicrosoftKey("\x00" * 64, self._clientRandom, self._serverRandom)
self._sessionKeyBlob = sec.generateMicrosoftKey(self._masterSecret, self._serverRandom, self._clientRandom)
self._macSalt = self._sessionKeyBlob[:16]
self._licenseKey = sec.md5_16_32_32(self._sessionKeyBlob[16:], self._clientRandom, self._serverRandom)
masterSecret = sec.generateMicrosoftKey(self._preMasterSecret, self._clientRandom, self._serverRandom)
sessionKeyBlob = sec.generateMicrosoftKey(masterSecret, self._serverRandom, self._clientRandom)
self._macSalt = sessionKeyBlob[:16]
self._licenseKey = sec.finalHash(sessionKeyBlob[16:32], self._clientRandom, self._serverRandom)
def recv(self, s):
"""
@@ -296,7 +298,11 @@ class LicenseManager(object):
elif licPacket.bMsgtype.value == MessageType.PLATFORM_CHALLENGE:
self._serverEncryptedChallenge = licPacket.licensingMessage.encryptedPlatformChallenge.blobData.value
self.sendClientChallengeResponse()
#yes get a new license
elif licPacket.bMsgtype.value == MessageType.NEW_LICENSE:
return True
else:
raise InvalidExpectedDataException("Not a valid license packet")
@@ -309,25 +315,27 @@ class LicenseManager(object):
"""
message = ClientNewLicenseRequest()
message.clientRandom.value = self._clientRandom
message.encryptedPreMasterSecret.blobData = String("\x00" * (64 + 8))
message.encryptedPreMasterSecret.blobData = String(self._preMasterSecret + "\x00" * 8)
message.ClientMachineName.blobData = String(self._hostname + "\x00")
message.ClientUserName.blobData = String(self._username + "\x00")
self._transport.sendLicensePacket(LicPacket(message))
def sendClientChallengeResponse(self):
#it should be TEST in unicode format
"""
@summary: generate valid challenge response
"""
#decrypt server challenge
#it should be TEST word in unicode format
serverChallenge = rc4.crypt(self._licenseKey, self._serverEncryptedChallenge)
#generate hwid
s = Stream()
s.writeType((UInt32Le(2), String(self._username + self._hostname + "\x00" * 20)))
s.writeType((UInt32Le(2), String(self._hostname + "\x00" * 16)))
hwid = s.getvalue()[:20]
signature = sec.macData(self._macSalt, serverChallenge + hwid)
message = ClientPLatformChallengeResponse()
message.encryptedPlatformChallengeResponse.blobData.value = self._serverEncryptedChallenge
message.encryptedHWID.blobData.value = rc4.crypt(self._licenseKey, hwid)
message.MACData.value = signature
message.MACData.value = sec.macData(self._macSalt, serverChallenge + hwid)
self._transport.sendLicensePacket(LicPacket(message))

View File

@@ -89,6 +89,7 @@ class RDPClientController(pdu.layer.PDUClientListener):
"""
#username in PDU info packet
self._pduLayer._info.userName.value = username
self._pduLayer._licenceManager._username = username
def setPassword(self, password):
"""
@@ -120,6 +121,13 @@ class RDPClientController(pdu.layer.PDUClientListener):
self._mcsLayer._clientSettings.getBlock(gcc.MessageType.CS_CORE).kbdLayout.value = gcc.KeyboardLayout.FRENCH
elif layout == "us":
self._mcsLayer._clientSettings.getBlock(gcc.MessageType.CS_CORE).kbdLayout.value = gcc.KeyboardLayout.US
def setHostname(self, hostname):
"""
@summary: set hostname of machine
"""
self._mcsLayer._clientSettings.getBlock(gcc.MessageType.CS_CORE).clientName.value = hostname[:15] + "\x00" * (15 - len(hostname))
self._pduLayer._licenceManager._hostname = hostname
def addClientObserver(self, observer):
"""

View File

@@ -48,18 +48,18 @@ def saltedHash(inputData, salt, salt1, salt2):
return md5Digest.digest()
def md5_16_32_32(in0, in1, in2):
def finalHash(key, random1, random2):
"""
@summary: MD5(in0[:16] + in1[:32] + in2[:32])
@param in0: in 16
@param in1: in 32
@param in2: in 32
@param key: in 16
@param random1: in 32
@param random2: in 32
@return MD5(in0[:16] + in1[:32] + in2[:32])
"""
md5Digest = md5.new()
md5Digest.update(in0[:16])
md5Digest.update(in1[:32])
md5Digest.update(in2[:32])
md5Digest.update(key)
md5Digest.update(random1)
md5Digest.update(random2)
return md5Digest.digest()
def generateMicrosoftKey(secret, random1, random2):
@@ -72,6 +72,9 @@ def generateMicrosoftKey(secret, random1, random2):
return saltedHash("A", secret, random1, random2) + saltedHash("BB", secret, random1, random2) + saltedHash("CCC", secret, random1, random2)
def macData(macSaltKey, data):
"""
@see: http://msdn.microsoft.com/en-us/library/cc241995.aspx
"""
sha1Digest = sha.new()
md5Digest = md5.new()