From 5b0a9d9da3280f2d90da60efd9436d03f02c4eaa Mon Sep 17 00:00:00 2001 From: Pourliver Date: Wed, 12 Jun 2019 15:03:37 -0400 Subject: [PATCH 1/2] Fixed Licensing issue and added boilerplate --- pyrdp/layer/rdp/security.py | 4 +++- pyrdp/mitm/SecurityMITM.py | 18 +++++++++++++++--- pyrdp/parser/rdp/licensing.py | 36 +++++++++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 4 deletions(-) diff --git a/pyrdp/layer/rdp/security.py b/pyrdp/layer/rdp/security.py index 74d63330f..897577883 100644 --- a/pyrdp/layer/rdp/security.py +++ b/pyrdp/layer/rdp/security.py @@ -135,7 +135,9 @@ def __init__(self, parser = BasicSecurityParser()): self.securityHeaderExpected = False def recv(self, data: bytes): - if not self.securityHeaderExpected: + # Licensing happens in the security layer + licensingBytes = b"\x80\x00" + if not self.securityHeaderExpected and data[0:2] != b"\x80\x00": if self.next is not None: self.next.recv(data) else: diff --git a/pyrdp/mitm/SecurityMITM.py b/pyrdp/mitm/SecurityMITM.py index 1c8e3abea..bceb80717 100644 --- a/pyrdp/mitm/SecurityMITM.py +++ b/pyrdp/mitm/SecurityMITM.py @@ -38,12 +38,13 @@ def __init__(self, client: SecurityLayer, server: SecurityLayer, log: LoggerAdap self.recorder = recorder self.client.createObserver( + onLicensingDataReceived = self.onClientLicensingData, onSecurityExchangeReceived = self.onSecurityExchange, onClientInfoReceived=self.onClientInfo, ) self.server.createObserver( - onLicensingDataReceived = self.onLicensingData + onLicensingDataReceived = self.onServerLicensingData, ) def onSecurityExchange(self, pdu: SecurityExchangePDU): @@ -94,7 +95,7 @@ def onClientInfo(self, data: bytes): self.log.debug("Sending %(pdu)s", {"pdu": pdu}) self.server.sendClientInfo(pdu) - def onLicensingData(self, data: bytes): + def onServerLicensingData(self, data: bytes): """ Forward licensing data to the client and disable security headers if TLS is in use. :param data: the licensing data @@ -103,4 +104,15 @@ def onLicensingData(self, data: bytes): self.client.securityHeaderExpected = False self.server.securityHeaderExpected = False - self.client.sendLicensing(data) \ No newline at end of file + self.client.sendLicensing(data) + + def onClientLicensingData(self, data: bytes): + """ + Forward licensing data to the server and disable security headers if TLS is in use. + :param data: the licensing data + """ + if self.state.useTLS: + self.client.securityHeaderExpected = False + self.server.securityHeaderExpected = False + + self.server.sendLicensing(data) \ No newline at end of file diff --git a/pyrdp/parser/rdp/licensing.py b/pyrdp/parser/rdp/licensing.py index 6cd2c89e2..b51ab749f 100644 --- a/pyrdp/parser/rdp/licensing.py +++ b/pyrdp/parser/rdp/licensing.py @@ -20,7 +20,15 @@ class LicensingParser(Parser): def __init__(self): super().__init__() + self.parsers = { + LicensingPDUType.LICENSE_REQUEST: self.parseLicenseRequest, + LicensingPDUType.PLATFORM_CHALLENGE: self.parsePlatformChallenge, + LicensingPDUType.NEW_LICENSE: self.parseNewLicense, + LicensingPDUType.UPGRADE_LICENSE: self.parseUpgradeLicense, + LicensingPDUType.LICENSE_INFO: self.parseLicenseInfo, + LicensingPDUType.NEW_LICENSE_REQUEST: self.parseNewLicenseRequest, + LicensingPDUType.PLATFORM_CHALLENGE_RESPONSE: self.parsePlatformChallengeResponse, LicensingPDUType.ERROR_ALERT: self.parseErrorAlert, } @@ -52,6 +60,34 @@ def parseLicenseBlob(self, stream): data = stream.read(length) return LicenseBinaryBlob(type, data) + def parseLicenseRequest(self, stream, flags): + # https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpele/a870d76a-639b-4757-9370-a9bdfbfd6961 + raise ("parseLicenseRequest isn't implemented yet") + + def parsePlatformChallenge(self, stream, flags): + # https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpele/3e78e067-83a8-42b5-b5b3-054679ade7c7 + raise ("parsePlatformChallenge isn't implemented yet") + + def parseNewLicense(self, stream, flags): + # https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpele/73c596f1-9550-4649-b880-2947c36c1bb6 + raise ("parseNewLicense isn't implemented yet") + + def parseUpgradeLicense(self, stream, flags): + # https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpele/94f9f260-fe9d-4429-b3b5-228bef28bc5d + raise ("parseUpgradeLicense isn't implemented yet") + + def parseLicenseInfo(self, stream, flags): + # https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpele/9fea482b-f9e5-4175-9350-ac540a804eba + raise ("parseLicenseInfo isn't implemented yet") + + def parseNewLicenseRequest(self, stream, flags): + # https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpele/9b4e7ee7-9e85-46f0-9583-77cfd397864e + raise ("parseNewLicenseRequest isn't implemented yet") + + def parsePlatformChallengeResponse(self, stream, flags): + # https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpele/58e79794-58f8-4607-a510-c0b5fef49c40 + raise ("parsePlatformChallengeResponse isn't implemented yet") + def parseErrorAlert(self, stream, flags): """ Parse the provided byte stream and return the corresponding RDPLicenseErrorAlertPDU From 954d61f2f30ab58b0f6197f96e769977596e871b Mon Sep 17 00:00:00 2001 From: Pourliver Date: Wed, 12 Jun 2019 15:08:07 -0400 Subject: [PATCH 2/2] Fixed unused variable --- pyrdp/layer/rdp/security.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyrdp/layer/rdp/security.py b/pyrdp/layer/rdp/security.py index 897577883..605c77d40 100644 --- a/pyrdp/layer/rdp/security.py +++ b/pyrdp/layer/rdp/security.py @@ -137,7 +137,7 @@ def __init__(self, parser = BasicSecurityParser()): def recv(self, data: bytes): # Licensing happens in the security layer licensingBytes = b"\x80\x00" - if not self.securityHeaderExpected and data[0:2] != b"\x80\x00": + if not self.securityHeaderExpected and data[0:2] != licensingBytes: if self.next is not None: self.next.recv(data) else: