diff --git a/rdpy/core/filetimes.py b/rdpy/core/filetimes.py new file mode 100644 index 0000000..5ada0ae --- /dev/null +++ b/rdpy/core/filetimes.py @@ -0,0 +1,98 @@ +# Copyright (c) 2009, David Buxton +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +"""Tools to convert between Python datetime instances and Microsoft times. +""" +from datetime import datetime, timedelta, tzinfo +from calendar import timegm + + +# http://support.microsoft.com/kb/167296 +# How To Convert a UNIX time_t to a Win32 FILETIME or SYSTEMTIME +EPOCH_AS_FILETIME = 116444736000000000 # January 1, 1970 as MS file time +HUNDREDS_OF_NANOSECONDS = 10000000 + + +ZERO = timedelta(0) +HOUR = timedelta(hours=1) + + +class UTC(tzinfo): + """UTC""" + def utcoffset(self, dt): + return ZERO + + def tzname(self, dt): + return "UTC" + + def dst(self, dt): + return ZERO + + +utc = UTC() + + +def dt_to_filetime(dt): + """Converts a datetime to Microsoft filetime format. If the object is + time zone-naive, it is forced to UTC before conversion. + + >>> "%.0f" % dt_to_filetime(datetime(2009, 7, 25, 23, 0)) + '128930364000000000' + + >>> "%.0f" % dt_to_filetime(datetime(1970, 1, 1, 0, 0, tzinfo=utc)) + '116444736000000000' + + >>> "%.0f" % dt_to_filetime(datetime(1970, 1, 1, 0, 0)) + '116444736000000000' + + >>> dt_to_filetime(datetime(2009, 7, 25, 23, 0, 0, 100)) + 128930364000001000 + """ + if (dt.tzinfo is None) or (dt.tzinfo.utcoffset(dt) is None): + dt = dt.replace(tzinfo=utc) + ft = EPOCH_AS_FILETIME + (timegm(dt.timetuple()) * HUNDREDS_OF_NANOSECONDS) + return ft + (dt.microsecond * 10) + + +def filetime_to_dt(ft): + """Converts a Microsoft filetime number to a Python datetime. The new + datetime object is time zone-naive but is equivalent to tzinfo=utc. + + >>> filetime_to_dt(116444736000000000) + datetime.datetime(1970, 1, 1, 0, 0) + + >>> filetime_to_dt(128930364000000000) + datetime.datetime(2009, 7, 25, 23, 0) + + >>> filetime_to_dt(128930364000001000) + datetime.datetime(2009, 7, 25, 23, 0, 0, 100) + """ + # Get seconds and remainder in terms of Unix epoch + (s, ns100) = divmod(ft - EPOCH_AS_FILETIME, HUNDREDS_OF_NANOSECONDS) + # Convert to datetime object + dt = datetime.utcfromtimestamp(s) + # Add remainder in as microseconds. Python 3.2 requires an integer + dt = dt.replace(microsecond=(ns100 // 10)) + return dt + \ No newline at end of file diff --git a/rdpy/protocol/rdp/nla/cssp.py b/rdpy/protocol/rdp/nla/cssp.py index b893071..229a664 100644 --- a/rdpy/protocol/rdp/nla/cssp.py +++ b/rdpy/protocol/rdp/nla/cssp.py @@ -97,7 +97,7 @@ class TSSmartCardCreds(univ.Sequence): namedtype.OptionalNamedType('domainHint', univ.OctetString().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 3))) ) -def encodeDERTRequest(negoTypes): +def encodeDERTRequest(negoTypes = [], pubKeyAuth = None): """ @summary: create TSRequest from list of Type @param negoTypes: {list(Type)} @@ -118,6 +118,9 @@ def encodeDERTRequest(negoTypes): request = TSRequest() request.setComponentByName("version", univ.Integer(2).subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0))) request.setComponentByName("negoTokens", negoData) + if not pubKeyAuth is None: + request.setComponentByName("pubKeyAuth", univ.OctetString(pubKeyAuth).subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 3))) + return String(encoder.encode(request)) def decodeDERTRequest(s): diff --git a/rdpy/protocol/rdp/nla/ntlm.py b/rdpy/protocol/rdp/nla/ntlm.py index cb91f83..04be11e 100644 --- a/rdpy/protocol/rdp/nla/ntlm.py +++ b/rdpy/protocol/rdp/nla/ntlm.py @@ -22,11 +22,13 @@ @see: https://msdn.microsoft.com/en-us/library/cc236621.aspx """ -import hashlib, hmac +import hashlib, hmac, struct, datetime +import sspi import rdpy.security.pyDes as pyDes import rdpy.security.rc4 as rc4 from rdpy.security.rsa_wrapper import random -from rdpy.core.type import CompositeType, CallableValue, String, UInt8, UInt16Le, UInt24Le, UInt32Le, sizeof +from rdpy.core.type import CompositeType, CallableValue, String, UInt8, UInt16Le, UInt24Le, UInt32Le, sizeof, Stream +from rdpy.core import filetimes class MajorVersion(object): """ @@ -98,6 +100,17 @@ class Version(CompositeType): self.ProductBuild = UInt16Le(6002) self.Reserved = UInt24Le() self.NTLMRevisionCurrent = UInt8(NTLMRevision.NTLMSSP_REVISION_W2K3) + +class MessageSignatureEx(CompositeType): + """ + @summary: Signature for message + @see: https://msdn.microsoft.com/en-us/library/cc422952.aspx + """ + def __init__(self): + CompositeType.__init__(self) + self.Version = UInt32Le(0x00000001, constant = True) + self.Checksum = String(readLen = CallableValue(16)) + self.SeqNum = UInt32Le() class NegotiateMessage(CompositeType): """ @@ -109,16 +122,7 @@ class NegotiateMessage(CompositeType): self.Signature = String("NTLMSSP\x00", readLen = CallableValue(8), constant = True) self.MessageType = UInt32Le(0x00000001, constant = True) - self.NegotiateFlags = UInt32Le(Negotiate.NTLMSSP_NEGOTIATE_KEY_EXCH | - Negotiate.NTLMSSP_NEGOTIATE_128 | - Negotiate.NTLMSSP_NEGOTIATE_56 | - Negotiate.NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY | - Negotiate.NTLMSSP_NEGOTIATE_ALWAYS_SIGN | - Negotiate.NTLMSSP_NEGOTIATE_NTLM | - Negotiate.NTLMSSP_REQUEST_TARGET | - Negotiate.NTLMSSP_NEGOTIATE_TARGET_INFO | - Negotiate.NTLMSSP_NEGOTIATE_VERSION | - Negotiate.NTLMSSP_NEGOTIATE_UNICODE) + self.NegotiateFlags = UInt32Le() self.DomainNameLen = UInt16Le() self.DomainNameMaxLen = UInt16Le(lambda:self.DomainNameLen.value) @@ -219,6 +223,46 @@ class AuthenticateMessage(CompositeType): def getEncryptedRandomSession(self): return getPayLoadField(self, self.EncryptedRandomSessionLen.value, self.EncryptedRandomSessionBufferOffset.value) +def createAuthenticationMessage(domain, user, NtChallengeResponse, LmChallengeResponse, EncryptedRandomSessionKey): + """ + @summary: Create an Authenticate Message + @param domain: {str} domain microsoft + @param user: {str} user microsoft + @param NtChallengeResponse: {str} Challenge response + @param LmChallengeResponse: {str} domain microsoft + @param EncryptedRandomSessionKey: {str} EncryptedRandomSessionKey + """ + message = AuthenticateMessage() + #fill message + offset = sizeof(message) + + message.DomainNameLen.value = len(domain) + message.DomainNameBufferOffset.value = offset + message.Payload.value += domain + offset += len(domain) + + message.UserNameLen.value = len(user) + message.UserNameBufferOffset.value = offset + message.Payload.value += user + offset += len(user) + + message.LmChallengeResponseLen.value = len(LmChallengeResponse) + message.LmChallengeResponseBufferOffset.value = offset + message.Payload.value += LmChallengeResponse + offset += len(LmChallengeResponse) + + message.NtChallengeResponseLen.value = len(NtChallengeResponse) + message.NtChallengeResponseBufferOffset.value = offset + message.Payload.value += NtChallengeResponse + offset += len(NtChallengeResponse) + + message.EncryptedRandomSessionLen.value = len(EncryptedRandomSessionKey) + message.EncryptedRandomSessionBufferOffset.value = offset + message.Payload.value += EncryptedRandomSessionKey + offset += len(EncryptedRandomSessionKey) + + return message + def expandDesKey(key): """ @summary: Expand the key from a 7-byte password key into a 8-byte DES key @@ -233,6 +277,13 @@ def expandDesKey(key): s = s + chr((ord(key[6]) & 0x7f) << 1) return s +def CurrentFileTimes(): + """ + @summary: Current File times in 64 bits + @return : {str[8]} + """ + return struct.pack("Q", filetimes.dt_to_filetime(datetime.datetime.now())) + def DES(key, data): """ @summary: DES use in microsoft specification @@ -289,137 +340,207 @@ def RC4K(key, plaintext): """ return rc4.crypt(rc4.RC4Key(key), plaintext) -def KXKEY(SessionBaseKey, LmChallengeResponse, ServerChallenge): +def KXKEYv2(SessionBaseKey, LmChallengeResponse, ServerChallenge): """ - @summary: Key eXchange Key + @summary: Key eXchange Key for NTLMv2 @param SessionBaseKey: {str} computed by NTLMv1Anthentication or NTLMv2Authenticate function @param LmChallengeResponse : {str} computed by NTLMv1Anthentication or NTLMv2Authenticate function @param ServerChallenge : {str} Server chanllenge come from ChallengeMessage @see: https://msdn.microsoft.com/en-us/library/cc236710.aspx """ - return HMAC_MD5(SessionBaseKey, ServerChallenge + LmChallengeResponse[:8]) + return SessionBaseKey -def SEALKEY(ExportedSessionKey): - return MD5(ExportedSessionKey + "session key to client-to-server sealing key magic constant") - -def SIGNKEY(ExportedSessionKey): - return MD5(ExportedSessionKey + "session key to client-to-server signing key magic constant") - - -def NTOWFv1(Passwd, User, UserDom): - """ - @see: https://msdn.microsoft.com/en-us/library/cc236699.aspx - """ - return MD4(UNICODE(Passwd)) - -def LMOWFv1(Passwd, User, UserDom): - """ - @see: https://msdn.microsoft.com/en-us/library/cc236699.aspx - """ - password = (Passwd.upper() + "\x00" * 14)[:14] - return DES(password[:7], "KGS!@#$%") + DES(password[7:], "KGS!@#$%") - -def NTLMv1Anthentication(negFlag, domain, user, password, serverChallenge, serverName): - """ - @summary: Not tested yet - @param negFlag: {int} use another non secure way - @param domain: {str} microsoft domain - @param user: {str} username - @param password: {str} password - @param serverChallenge: {str[8]} server challenge - """ - ResponseKeyNT = NTOWFv1(password, user, domain) - ResponseKeyLM = LMOWFv1(password, user, domain) - - if negFlag & Negotiate.NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY: - ClientChallenge = random(64) - NtChallengeResponse = DESL(ResponseKeyNT, MD5(serverChallenge + ClientChallenge)) - LmChallengeResponse = ClientChallenge + Z(16) +def SEALKEY(ExportedSessionKey, client): + if client: + return MD5(ExportedSessionKey + "session key to client-to-server sealing key magic constant\0") else: - NtChallengeResponse = DESL(ResponseKeyNT, serverChallenge) - LmChallengeResponse = DESL(ResponseKeyLM, serverChallenge) - - SessionBaseKey = MD4(ResponseKeyNT) - - return NtChallengeResponse, LmChallengeResponse, SessionBaseKey + return MD5(ExportedSessionKey + "session key to server-to-client sealing key magic constant\0") + +def SIGNKEY(ExportedSessionKey, client): + if client: + return MD5(ExportedSessionKey + "session key to client-to-server signing key magic constant\0") + else: + return MD5(ExportedSessionKey + "session key to server-to-client signing key magic constant\0") def HMAC_MD5(key, data): + """ + @summary: classic HMAC algorithm with MD5 sum + @param key: {str} key + @param data: {str} data + """ return hmac.new(key, data, hashlib.md5).digest() def NTOWFv2(Passwd, User, UserDom): + """ + @summary: Version 2 of NTLM hash function + @param Passwd: {str} Password + @param User: {str} Username + @param UserDom: {str} microsoft domain + @see: https://msdn.microsoft.com/en-us/library/cc236700.aspx + """ return HMAC_MD5(MD4(UNICODE(Passwd)), UNICODE(User.upper() + UserDom)) def LMOWFv2(Passwd, User, UserDom): - return NTOWFv2(Passwd, User, UserDom) - -def NTLMv2Authenticate(negFlag, domain, user, password, serverChallenge, serverName, Time = "\x00" * 8, ClientChallenge = None): """ - @summary: process NTLMv2 Authenticate hash + @summary: Same as NTOWFv2 + @param Passwd: {str} Password + @param User: {str} Username + @param UserDom: {str} microsoft domain + @see: https://msdn.microsoft.com/en-us/library/cc236700.aspx + """ + return NTOWFv2(Passwd, User, UserDom) + +def ComputeResponsev2(ResponseKeyNT, ResponseKeyLM, ServerChallenge, ClientChallenge, Time, ServerName): + """ + @summary: process NTLMv2 Authenticate hash + @param NegFlg: {int} Negotiation flags come from challenge message @see: https://msdn.microsoft.com/en-us/library/cc236700.aspx """ - ResponseKeyNT = NTOWFv2(password, user, domain) - ResponseKeyLM = LMOWFv2(password, user, domain) - Responserversion = "\x01" HiResponserversion = "\x01" - #Time = "\x00" * 8 - if ClientChallenge is None: - ClientChallenge = random(64) - temp = Responserversion + HiResponserversion + Z(6) + Time + ClientChallenge + Z(4) + serverName + Z(4) - NTProofStr = HMAC_MD5(ResponseKeyNT, serverChallenge + temp) + temp = Responserversion + HiResponserversion + Z(6) + Time + ClientChallenge + Z(4) + ServerName + Z(4) + NTProofStr = HMAC_MD5(ResponseKeyNT, ServerChallenge + temp) NtChallengeResponse = NTProofStr + temp - LmChallengeResponse = HMAC_MD5(ResponseKeyLM, serverChallenge + ClientChallenge) + ClientChallenge + LmChallengeResponse = HMAC_MD5(ResponseKeyLM, ServerChallenge + ClientChallenge) + ClientChallenge SessionBaseKey = HMAC_MD5(ResponseKeyNT, NTProofStr) return NtChallengeResponse, LmChallengeResponse, SessionBaseKey -def createAuthenticationMessage(method, challengeResponse, domain, user, password): - #extract target info - NtChallengeResponse, LmChallengeResponse, SessionBaseKey = method(challengeResponse.NegotiateFlags.value, - domain, user, password, - challengeResponse.ServerChallenge.value, - challengeResponse.getTargetInfo()) +def MAC(handle, SigningKey, SeqNum, Message): + """ + @summary: generate signature for application message + @param handle: {rc4.RC4Key} handle on crypt + @param SigningKey: {str} Signing key + @param SeqNum: {int} Sequence number + @param Message: Message to sign + @see: https://msdn.microsoft.com/en-us/library/cc422952.aspx + """ + signature = MessageSignatureEx() + signature.SeqNum.value = SeqNum - if challengeResponse.NegotiateFlags.value & Negotiate.NTLMSSP_NEGOTIATE_UNICODE: - domain, user = UNICODE(domain), UNICODE(user) + #write the SeqNum + s = Stream() + s.writeType(signature.SeqNum) - message = AuthenticateMessage() - #fill message - offset = sizeof(message) + signature.Checksum.value = rc4.crypt(handle, HMAC_MD5(SigningKey, s.getvalue() + Message)[:8]) - message.NegotiateFlags.value = challengeResponse.NegotiateFlags.value + return signature - message.LmChallengeResponseLen.value = len(LmChallengeResponse) - message.LmChallengeResponseBufferOffset.value = offset - message.Payload.value += LmChallengeResponse - offset += len(LmChallengeResponse) +class NTLMv2(sspi.IAuthenticationProtocol): + """ + @summary: Handle NTLMv2 Authentication + """ + def __init__(self, domain, user, password): + self._domain = domain + self._user = user + #https://msdn.microsoft.com/en-us/library/cc236700.aspx + self._ResponseKeyNT = NTOWFv2(password, user, domain) + self._ResponseKeyLM = LMOWFv2(password, user, domain) - message.NtChallengeResponseLen.value = len(NtChallengeResponse) - message.NtChallengeResponseBufferOffset.value = offset - message.Payload.value += NtChallengeResponse - offset += len(NtChallengeResponse) + def getNegotiateMessage(self): + """ + @summary: generate first handshake messgae + """ + message = NegotiateMessage() + message.NegotiateFlags.value = (Negotiate.NTLMSSP_NEGOTIATE_KEY_EXCH | + Negotiate.NTLMSSP_NEGOTIATE_128 | + Negotiate.NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY | + Negotiate.NTLMSSP_NEGOTIATE_ALWAYS_SIGN | + Negotiate.NTLMSSP_NEGOTIATE_NTLM | + Negotiate.NTLMSSP_NEGOTIATE_SEAL | + Negotiate.NTLMSSP_NEGOTIATE_SIGN | + Negotiate.NTLMSSP_REQUEST_TARGET | + Negotiate.NTLMSSP_NEGOTIATE_UNICODE) + return message - message.DomainNameLen.value = len(domain) - message.DomainNameBufferOffset.value = offset - message.Payload.value += domain - offset += len(domain) - - message.UserNameLen.value = len(user) - message.UserNameBufferOffset.value = offset - message.Payload.value += user - offset += len(user) - - message.EncryptedRandomSessionLen.value = len(SessionBaseKey) - message.EncryptedRandomSessionBufferOffset.value = offset - message.Payload.value += SessionBaseKey - offset += len(SessionBaseKey) - - return message + def getAuthenticateMessage(self, s): + """ + @summary: Client last handshake message + @param s: {Stream} challenge message stream + @return: {(AuthenticateMessage, NTLMv2SecurityInterface)} Last handshake message and security interface use to encrypt + @see: https://msdn.microsoft.com/en-us/library/cc236676.aspx + """ + challenge = ChallengeMessage() + s.readType(challenge) + + ServerChallenge = challenge.ServerChallenge.value + ClientChallenge = random(64) + Timestamp = CurrentFileTimes() + ServerName = challenge.getTargetInfo() + + NtChallengeResponse, LmChallengeResponse, SessionBaseKey = ComputeResponsev2(self._ResponseKeyNT, self._ResponseKeyLM, ServerChallenge, ClientChallenge, Timestamp, ServerName) + KeyExchangeKey = KXKEYv2(SessionBaseKey, LmChallengeResponse, ServerChallenge) + ExportedSessionKey = random(128) + EncryptedRandomSessionKey = RC4K(KeyExchangeKey, ExportedSessionKey) + + domain, user = self._domain, self._user + if challenge.NegotiateFlags.value & Negotiate.NTLMSSP_NEGOTIATE_UNICODE: + domain, user = UNICODE(domain), UNICODE(user) + message = createAuthenticationMessage(domain, user, NtChallengeResponse, LmChallengeResponse, EncryptedRandomSessionKey) + + ClientSigningKey = SIGNKEY(ExportedSessionKey, True) + ServerSigningKey = SIGNKEY(ExportedSessionKey, False) + ClientSealingKey = SEALKEY(ExportedSessionKey, True) + ServerSealingKey = SEALKEY(ExportedSessionKey, False) + + interface = NTLMv2SecurityInterface(rc4.RC4Key(ClientSealingKey), rc4.RC4Key(ServerSealingKey), ClientSigningKey, ServerSigningKey) + + return message, interface + +class NTLMv2SecurityInterface(sspi.IGenericSecurityService): + """ + @summary: Generic Security Service for NTLM session + """ + def __init__(self, encryptHandle, decryptHandle, signingKey, verifyKey): + """ + @param encryptHandle: {rc4.RC4Key} rc4 keystream for encrypt phase + @param decryptHandle: {rc4.RC4Key} rc4 keystream for decrypt phase + @param signingKey: {str} signingKey + @param verifyKey: {str} verifyKey + """ + self._encryptHandle = encryptHandle + self._decryptHandle = decryptHandle + self._signingKey = signingKey + self._verifyKey = verifyKey + self._seqNum = 0 + + def GSS_WrapEx(self, data): + """ + @summary: Encrypt function for NTLMv2 security service + @param data: data to encrypt + @return: {str} encrypted data + """ + encryptedData = rc4.crypt(self._encryptHandle, data) + signature = MAC(self._encryptHandle, self._signingKey, self._seqNum, data) + self._seqNum += 1 + s = Stream() + s.writeType(signature) + return s.getvalue() + encryptedData -cssp_1 = [ +pubKeyHex = [ +0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0x9E, +0x95, 0xB5, 0x41, 0x03, 0xC5, 0x33, 0xEA, 0x29, +0x65, 0x2B, 0x65, 0xEF, 0x30, 0x71, 0xDD, 0x73, +0xBB, 0x30, 0x3B, 0xEC, 0xCA, 0x72, 0xCF, 0xBD, +0xE0, 0xF8, 0x21, 0xFF, 0xA6, 0x97, 0x76, 0xA1, +0x08, 0xB5, 0xD2, 0xC6, 0x95, 0x81, 0xD2, 0xBA, +0x71, 0x10, 0x4A, 0xAC, 0x25, 0x34, 0x37, 0xA0, +0xC3, 0x57, 0xF0, 0xEA, 0x1F, 0x8C, 0x84, 0xEB, +0x7B, 0xE6, 0x6C, 0x50, 0x26, 0x1F, 0xB7, 0x41, +0x0A, 0x58, 0xD3, 0x80, 0x87, 0x3D, 0x0B, 0x41, +0xD9, 0xBC, 0x54, 0x3A, 0x0F, 0x77, 0x14, 0x79, +0xF5, 0xB9, 0xA4, 0x38, 0xEB, 0x13, 0x08, 0x35, +0xAE, 0xBF, 0xB3, 0x17, 0x5A, 0xE2, 0x58, 0x89, +0x39, 0xC4, 0x22, 0x7F, 0x16, 0x57, 0x90, 0x08, +0xAF, 0x91, 0x3B, 0x95, 0xC8, 0x53, 0xD0, 0xC0, +0x8E, 0x19, 0x8A, 0xF3, 0x10, 0xBC, 0xC8, 0xC7, +0x42, 0xFB, 0x12, 0xDE, 0x2D, 0x5E, 0x83, 0x02, +0x03, 0x01, 0x00, 0x01 ] + +peer0_0 = [ 0x30, 0x2f, 0xa0, 0x03, 0x02, 0x01, 0x02, 0xa1, 0x28, 0x30, 0x26, 0x30, 0x24, 0xa0, 0x22, 0x04, 0x20, 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, @@ -427,15 +548,15 @@ cssp_1 = [ 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ] -cssp_2 = [ +peer1_0 = [ 0x30, 0x82, 0x01, 0x09, 0xa0, 0x03, 0x02, 0x01, 0x02, 0xa1, 0x82, 0x01, 0x00, 0x30, 0x81, 0xfd, 0x30, 0x81, 0xfa, 0xa0, 0x81, 0xf7, 0x04, 0x81, 0xf4, 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x38, 0x00, 0x00, 0x00, 0x35, 0x82, 0x89, -0x62, 0x73, 0xc7, 0x43, 0xa9, 0xe7, 0xfc, 0xbb, -0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x62, 0x0a, 0xee, 0xd7, 0xc3, 0xeb, 0x8e, 0x34, +0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xae, 0x00, 0xae, 0x00, 0x46, 0x00, 0x00, 0x00, 0x06, 0x01, 0xb1, 0x1d, 0x00, 0x00, 0x00, 0x0f, 0x53, 0x00, 0x49, 0x00, 0x52, 0x00, 0x41, @@ -460,86 +581,84 @@ cssp_2 = [ 0x00, 0x61, 0x00, 0x64, 0x00, 0x65, 0x00, 0x6c, 0x00, 0x2e, 0x00, 0x6c, 0x00, 0x6f, 0x00, 0x63, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x07, 0x00, 0x08, -0x00, 0x56, 0x93, 0x34, 0x32, 0xc7, 0x55, 0xd0, +0x00, 0xe5, 0x40, 0x3c, 0xa6, 0x68, 0x57, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00 ] -cssp_3 = [ -0x30, 0x82, 0x02, 0x0f, 0xa0, 0x03, 0x02, 0x01, -0x02, 0xa1, 0x82, 0x01, 0x62, 0x30, 0x82, 0x01, -0x5e, 0x30, 0x82, 0x01, 0x5a, 0xa0, 0x82, 0x01, -0x56, 0x04, 0x82, 0x01, 0x52, 0x4e, 0x54, 0x4c, +peer0_1 = [ +0x30, 0x82, 0x02, 0x21, 0xa0, 0x03, 0x02, 0x01, +0x02, 0xa1, 0x82, 0x01, 0x76, 0x30, 0x82, 0x01, +0x72, 0x30, 0x82, 0x01, 0x6e, 0xa0, 0x82, 0x01, +0x6a, 0x04, 0x82, 0x01, 0x66, 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x03, 0x00, 0x00, -0x00, 0x18, 0x00, 0x18, 0x00, 0x50, 0x00, 0x00, -0x00, 0xda, 0x00, 0xda, 0x00, 0x68, 0x00, 0x00, -0x00, 0x08, 0x00, 0x08, 0x00, 0x40, 0x00, 0x00, -0x00, 0x08, 0x00, 0x08, 0x00, 0x48, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, -0x00, 0x10, 0x00, 0x10, 0x00, 0x42, 0x01, 0x00, -0x00, 0x35, 0x82, 0x08, 0x60, 0x63, 0x00, 0x6f, -0x00, 0x63, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, -0x00, 0x74, 0x00, 0x6f, 0x00, 0x1a, 0x8a, 0xc2, -0xbc, 0x64, 0xda, 0xc0, 0x28, 0x9b, 0xa8, 0x14, -0x08, 0x51, 0x6d, 0xd6, 0xb8, 0x29, 0x09, 0xd2, -0x99, 0x19, 0x33, 0x70, 0x9e, 0x51, 0xa0, 0x6e, -0xc5, 0x39, 0x47, 0xf3, 0x9e, 0x96, 0x6a, 0xc3, -0xfc, 0xb2, 0xeb, 0xc7, 0xe0, 0x01, 0x01, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x08, -0x32, 0xc7, 0x55, 0xd0, 0x01, 0x29, 0x09, 0xd2, -0x99, 0x19, 0x33, 0x70, 0x9e, 0x00, 0x00, 0x00, -0x00, 0x02, 0x00, 0x0e, 0x00, 0x53, 0x00, 0x49, -0x00, 0x52, 0x00, 0x41, 0x00, 0x44, 0x00, 0x45, -0x00, 0x4c, 0x00, 0x01, 0x00, 0x16, 0x00, 0x57, -0x00, 0x41, 0x00, 0x56, 0x00, 0x2d, 0x00, 0x47, -0x00, 0x4c, 0x00, 0x57, 0x00, 0x2d, 0x00, 0x30, -0x00, 0x30, 0x00, 0x39, 0x00, 0x04, 0x00, 0x1a, +0x00, 0x18, 0x00, 0x18, 0x00, 0x64, 0x00, 0x00, +0x00, 0xda, 0x00, 0xda, 0x00, 0x7c, 0x00, 0x00, +0x00, 0x0e, 0x00, 0x0e, 0x00, 0x40, 0x00, 0x00, +0x00, 0x16, 0x00, 0x16, 0x00, 0x4e, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x10, 0x00, 0x10, 0x00, 0x56, 0x01, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x00, 0x69, +0x00, 0x72, 0x00, 0x61, 0x00, 0x64, 0x00, 0x65, +0x00, 0x6c, 0x00, 0x73, 0x00, 0x70, 0x00, 0x65, +0x00, 0x79, 0x00, 0x72, 0x00, 0x65, 0x00, 0x66, +0x00, 0x69, 0x00, 0x74, 0x00, 0x74, 0x00, 0x65, +0x00, 0x8a, 0x01, 0x34, 0xd8, 0x57, 0x6e, 0x14, +0x2b, 0xda, 0xc6, 0x91, 0x02, 0x49, 0xbb, 0xc4, +0x00, 0x19, 0x6c, 0x60, 0x26, 0x16, 0xdb, 0x37, +0x8f, 0x98, 0xe1, 0x04, 0xf8, 0x36, 0x6a, 0x96, +0xa2, 0xa1, 0x9a, 0xf9, 0x5f, 0x1f, 0x04, 0x63, +0x69, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x38, 0x8d, 0x10, 0x08, 0x71, 0x57, 0xd0, +0x01, 0x19, 0x6c, 0x60, 0x26, 0x16, 0xdb, 0x37, +0x8f, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x0e, +0x00, 0x53, 0x00, 0x49, 0x00, 0x52, 0x00, 0x41, +0x00, 0x44, 0x00, 0x45, 0x00, 0x4c, 0x00, 0x01, +0x00, 0x16, 0x00, 0x57, 0x00, 0x41, 0x00, 0x56, +0x00, 0x2d, 0x00, 0x47, 0x00, 0x4c, 0x00, 0x57, +0x00, 0x2d, 0x00, 0x30, 0x00, 0x30, 0x00, 0x39, +0x00, 0x04, 0x00, 0x1a, 0x00, 0x53, 0x00, 0x69, +0x00, 0x72, 0x00, 0x61, 0x00, 0x64, 0x00, 0x65, +0x00, 0x6c, 0x00, 0x2e, 0x00, 0x6c, 0x00, 0x6f, +0x00, 0x63, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x03, +0x00, 0x32, 0x00, 0x77, 0x00, 0x61, 0x00, 0x76, +0x00, 0x2d, 0x00, 0x67, 0x00, 0x6c, 0x00, 0x77, +0x00, 0x2d, 0x00, 0x30, 0x00, 0x30, 0x00, 0x39, +0x00, 0x2e, 0x00, 0x53, 0x00, 0x69, 0x00, 0x72, +0x00, 0x61, 0x00, 0x64, 0x00, 0x65, 0x00, 0x6c, +0x00, 0x2e, 0x00, 0x6c, 0x00, 0x6f, 0x00, 0x63, +0x00, 0x61, 0x00, 0x6c, 0x00, 0x05, 0x00, 0x1a, 0x00, 0x53, 0x00, 0x69, 0x00, 0x72, 0x00, 0x61, 0x00, 0x64, 0x00, 0x65, 0x00, 0x6c, 0x00, 0x2e, 0x00, 0x6c, 0x00, 0x6f, 0x00, 0x63, 0x00, 0x61, -0x00, 0x6c, 0x00, 0x03, 0x00, 0x32, 0x00, 0x77, -0x00, 0x61, 0x00, 0x76, 0x00, 0x2d, 0x00, 0x67, -0x00, 0x6c, 0x00, 0x77, 0x00, 0x2d, 0x00, 0x30, -0x00, 0x30, 0x00, 0x39, 0x00, 0x2e, 0x00, 0x53, -0x00, 0x69, 0x00, 0x72, 0x00, 0x61, 0x00, 0x64, -0x00, 0x65, 0x00, 0x6c, 0x00, 0x2e, 0x00, 0x6c, -0x00, 0x6f, 0x00, 0x63, 0x00, 0x61, 0x00, 0x6c, -0x00, 0x05, 0x00, 0x1a, 0x00, 0x53, 0x00, 0x69, -0x00, 0x72, 0x00, 0x61, 0x00, 0x64, 0x00, 0x65, -0x00, 0x6c, 0x00, 0x2e, 0x00, 0x6c, 0x00, 0x6f, -0x00, 0x63, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x07, -0x00, 0x08, 0x00, 0x56, 0x93, 0x34, 0x32, 0xc7, -0x55, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xbf, -0xec, 0xf5, 0xf6, 0x69, 0x01, 0x3a, 0xef, 0x5b, -0xd0, 0xab, 0xfe, 0x3f, 0xdf, 0x75, 0x30, 0xa3, -0x82, 0x00, 0xa0, 0x04, 0x82, 0x00, 0x9c, 0x01, -0x00, 0x00, 0x00, 0xc4, 0x0e, 0xcd, 0x96, 0x8f, -0x67, 0xc0, 0xdd, 0x00, 0x00, 0x00, 0x00, 0xcf, -0x88, 0xbd, 0x30, 0xe2, 0x53, 0x4a, 0x4b, 0x8d, -0x49, 0xd4, 0xe9, 0xa3, 0x63, 0x1f, 0xe8, 0x19, -0x59, 0xe6, 0x88, 0x96, 0xaa, 0x50, 0x35, 0x81, -0x02, 0x9a, 0x91, 0x25, 0x8b, 0x1c, 0x0f, 0x8f, -0xc6, 0x91, 0x44, 0x55, 0x5f, 0x4e, 0xd9, 0x1b, -0xc3, 0xae, 0x94, 0xde, 0x09, 0xa8, 0xdd, 0x80, -0x64, 0x52, 0x85, 0x4a, 0xf2, 0xd7, 0xc7, 0x11, -0x29, 0x22, 0xbe, 0xe5, 0xad, 0x57, 0x6b, 0x4f, -0xdc, 0xa1, 0xae, 0x00, 0x5b, 0xff, 0xe8, 0x6c, -0xdb, 0x15, 0x84, 0x18, 0x94, 0x0e, 0xeb, 0xcd, -0x9d, 0x41, 0xc3, 0x4e, 0xf6, 0xa6, 0xcf, 0x2c, -0xf5, 0xc5, 0x9e, 0xa0, 0xd9, 0x80, 0x5f, 0xaa, -0x22, 0x66, 0x61, 0x56, 0xde, 0x3e, 0xcb, 0x5f, -0x7c, 0x64, 0xaf, 0xbf, 0xa7, 0x26, 0x83, 0xa8, -0x5c, 0x88, 0xf3, 0xbe, 0x8a, 0xe6, 0xe6, 0x4c, -0xf7, 0x95, 0xd0, 0xa8, 0xf0, 0x8c, 0x21, 0xf8, -0x86, 0x77, 0x49, 0x29, 0xe3, 0xd3, 0xf8, 0x78, -0x1f, 0x51, 0x91 ] - -pubKey = "\x30\x81\x89\x02\x81\x81\x00\x9e\x95\xb5\x41\x03\xc5\x33\xea\x29\x65\x2b\x65\xef\x30\x71\xdd\x73\xbb\x30\x3b\xec\xca\x72\xcf\xbd\xe0\xf8\x21\xff\xa6\x97\x76\xa1\x08\xb5\xd2\xc6\x95\x81\xd2\xba\x71\x10\x4a\xac\x25\x34\x37\xa0\xc3\x57\xf0\xea\x1f\x8c\x84\xeb\x7b\xe6\x6c\x50\x26\x1f\xb7\x41\x0a\x58\xd3\x80\x87\x3d\x0b\x41\xd9\xbc\x54\x3a\x0f\x77\x14\x79\xf5\xb9\xa4\x38\xeb\x13\x08\x35\xae\xbf\xb3\x17\x5a\xe2\x58\x89\x39\xc4\x22\x7f\x16\x57\x90\x08\xaf\x91\x3b\x95\xc8\x53\xd0\xc0\x8e\x19\x8a\xf3\x10\xbc\xc8\xc7\x42\xfb\x12\xde\x2d\x5e\x83\x02\x03\x01\x00\x01" +0x00, 0x6c, 0x00, 0x07, 0x00, 0x08, 0x00, 0xe5, +0x40, 0x3c, 0xa6, 0x68, 0x57, 0xd0, 0x01, 0x00, +0x00, 0x00, 0x00, 0x59, 0x49, 0x84, 0x63, 0xf2, +0x84, 0x53, 0x18, 0xea, 0xa4, 0xc3, 0xb6, 0x97, +0x0d, 0x3e, 0x38, 0xa3, 0x81, 0x9f, 0x04, 0x81, +0x9c, 0x01, 0x00, 0x00, 0x00, 0xc9, 0x56, 0x22, +0x84, 0x7d, 0xba, 0xa2, 0xe6, 0x00, 0x00, 0x00, +0x00, 0x1c, 0x6d, 0x39, 0xe1, 0x5a, 0x31, 0x5d, +0xf5, 0x01, 0xa6, 0xea, 0x4b, 0xaf, 0x83, 0x13, +0xdc, 0x8a, 0x45, 0xb3, 0x76, 0xc6, 0x3d, 0xbf, +0x73, 0x4c, 0x93, 0xe6, 0x75, 0x8b, 0x42, 0x21, +0xea, 0xe6, 0x0c, 0xfa, 0x3c, 0xd0, 0x7c, 0x8d, +0xd6, 0x2a, 0x97, 0x7a, 0x49, 0xb5, 0x7d, 0xeb, +0xc2, 0x94, 0xc0, 0x84, 0xb4, 0xef, 0x7f, 0x1e, +0xa3, 0xa3, 0x3f, 0x61, 0x7c, 0x1c, 0xd9, 0x82, +0xc6, 0x0b, 0x6c, 0x85, 0x15, 0xb0, 0x47, 0x25, +0xe9, 0x0a, 0x88, 0x58, 0x3c, 0x6d, 0x8e, 0x60, +0x2a, 0xbc, 0x04, 0x57, 0x7f, 0x5b, 0x03, 0x7c, +0x7a, 0x8f, 0x1b, 0x7b, 0xe3, 0x67, 0xb6, 0x02, +0xa4, 0xc0, 0xdd, 0x9e, 0x97, 0x4c, 0xd8, 0x86, +0x5c, 0x9a, 0x45, 0x0d, 0x85, 0x4b, 0x46, 0x87, +0xde, 0xcf, 0x31, 0x72, 0xe3, 0xd7, 0x5d, 0x0b, +0x67, 0x1b, 0xa1, 0xde, 0x24, 0x87, 0xdf, 0xd9, +0xb2, 0x18, 0xfd, 0x5a, 0x29, 0xbb, 0x35, 0xe0, +0x3d, 0x9f, 0x85, 0xf7, 0x36 ] if __name__ == "__main__": import cssp, hexdump - from rdpy.core.type import Stream - - negotiate_data_request = cssp.decodeDERTRequest(Stream("".join([chr(i) for i in cssp_1]))) - challenge_data_request = cssp.decodeDERTRequest(Stream("".join([chr(i) for i in cssp_2]))) - authenticate_data_request = cssp.decodeDERTRequest(Stream("".join([chr(i) for i in cssp_3]))) + negotiate_data_request = cssp.decodeDERTRequest(Stream("".join([chr(i) for i in peer0_0]))) + challenge_data_request = cssp.decodeDERTRequest(Stream("".join([chr(i) for i in peer1_0]))) + authenticate_data_request = cssp.decodeDERTRequest(Stream("".join([chr(i) for i in peer0_1]))) negotiate_data = cssp.getNegoTokens(negotiate_data_request)[0] challenge_data = cssp.getNegoTokens(challenge_data_request)[0] @@ -557,57 +676,39 @@ if __name__ == "__main__": authenticate = AuthenticateMessage() authenticate_data.readType(authenticate) - NtChallengeResponse = authenticate.getNtChallengeResponse() - NTProofStr = NtChallengeResponse[:16] - temp = NtChallengeResponse[16:] - Time = temp[8:16] + NtChallengeResponseTemp = authenticate.getNtChallengeResponse() + NTProofStr = NtChallengeResponseTemp[:16] + temp = NtChallengeResponseTemp[16:] + Timestamp = temp[8:16] ClientChallenge = temp[16:24] - ServerName2 = temp[28:-4] + EncryptedRandomSessionKey = authenticate.getEncryptedRandomSession() - LmChallengeResponse = authenticate.getLmChallengeResponse() - EncryptedRandom = authenticate.getEncryptedRandomSession() - encryptedPubKey = cssp.getPubKeyAuth(authenticate_data_request) + domain = "dodo" + user = "uouo" + password = "popo" + ResponseKeyNT = NTOWFv2(password, user, domain) + ResponseKeyLM = LMOWFv2(password, user, domain) + + NtChallengeResponse, LmChallengeResponse, SessionBaseKey = ComputeResponsev2(ResponseKeyNT, ResponseKeyLM, ServerChallenge, ClientChallenge, Timestamp, ServerName) + KeyExchangeKey = KXKEYv2(SessionBaseKey, LmChallengeResponse, ServerChallenge) + ExportedSessionKey = RC4K(KeyExchangeKey, EncryptedRandomSessionKey) - NtChallengeResponse2, LmChallengeResponse2, SessionBaseKey2 = NTLMv2Authenticate(None, "coco", "toto", "lolo", ServerChallenge, ServerName, Time, ClientChallenge) + domain, user = domain, user + if challenge.NegotiateFlags.value & Negotiate.NTLMSSP_NEGOTIATE_UNICODE: + domain, user = UNICODE(domain), UNICODE(user) + message = createAuthenticationMessage(domain, user, NtChallengeResponse, LmChallengeResponse, EncryptedRandomSessionKey) - KeyExchangeKey = KXKEY(SessionBaseKey2, LmChallengeResponse2, ServerChallenge) - #decrypt - ExportedSessionKey = RC4K(KeyExchangeKey, EncryptedRandom) + ClientSigningKey = SIGNKEY(ExportedSessionKey, True) + ServerSigningKey = SIGNKEY(ExportedSessionKey, False) + ClientSealingKey = SEALKEY(ExportedSessionKey, True) + ServerSealingKey = SEALKEY(ExportedSessionKey, False) - sealingKey = SEALKEY(ExportedSessionKey) - signingKey = SIGNKEY(ExportedSessionKey) + interface = NTLMv2SecurityInterface(rc4.RC4Key(ClientSealingKey), rc4.RC4Key(ServerSealingKey), ClientSigningKey, ServerSigningKey) - key = rc4.RC4Key(sealingKey) + EncryptedPubKeySrc = cssp.getPubKeyAuth(authenticate_data_request) + EncryptedPubKeyDst = interface.GSS_WrapEx("".join([chr(i) for i in pubKeyHex])) - encryptedPubKey2 = rc4.crypt(key, pubKey) - signature = rc4.crypt(key, HMAC_MD5(signingKey, "\x00\x00\x00\x00" + pubKey)[:8]) - - - hexdump.hexdump(encryptedPubKey) - print "\n" - hexdump.hexdump(signature) - print "\n" - hexdump.hexdump(encryptedPubKey2) -# print "-"*40 -# print "NtChallengeResponse" -# print "\n" -# hexdump.hexdump(NtChallengeResponse) -# print "\n" -# hexdump.hexdump(NtChallengeResponse2) -# print "-"*40 -# -# print "-"*40 -# print "LmChallengeResponse" -# print "\n" -# hexdump.hexdump(LmChallengeResponse) -# print "\n" -# hexdump.hexdump(LmChallengeResponse2) -# print "-"*40 -# -# print "-"*40 -# print "SessionBaseKey" -# print "\n" -# hexdump.hexdump(SessionBaseKey) -# print "\n" -# hexdump.hexdump(SessionBaseKey2) -# print "-"*40 \ No newline at end of file + print "EncryptedPubKeySrc" + hexdump.hexdump(EncryptedPubKeySrc) + print "EncryptedPubKeyDst" + hexdump.hexdump(EncryptedPubKeyDst) \ No newline at end of file diff --git a/rdpy/protocol/rdp/nla/sspi.py b/rdpy/protocol/rdp/nla/sspi.py new file mode 100644 index 0000000..0e7d072 --- /dev/null +++ b/rdpy/protocol/rdp/nla/sspi.py @@ -0,0 +1,55 @@ +# +# Copyright (c) 2014-2015 Sylvain Peyrefitte +# +# This file is part of rdpy. +# +# rdpy is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +""" +@summary: security service provider interface (Microsoft) +""" + +from rdpy.core.error import CallPureVirtualFuntion + +class IAuthenticationProtocol(object): + """ + @summary: generic class for authentication Protocol (ex: ntlmv2, SPNEGO or kerberos) + """ + def getNegotiateMessage(self): + """ + @summary: Client first handshake message for authentication protocol + @return: {object} first handshake message + """ + raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "getNegotiateMessage", "IAuthenticationProtocol")) + + def getAuthenticateMessage(self, s): + """ + @summary: Client last handshake message + @param s: {Stream} challenge message stream + @return: {(object, IGenericSecurityService)} Last handshake message and interface for application + """ + raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "getAuthenticateMessage", "IAuthenticationProtocol")) + +class IGenericSecurityService(object): + """ + @summary: use by application from authentification protocol + @see: http://www.rfc-editor.org/rfc/rfc2743.txt + """ + def GSS_WrapEx(self, data): + """ + @summary: encrypt data with key exchage in Authentication protocol + @param data: {str} + """ + raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "GSS_WrapEx", "IGenericSecurityService")) \ No newline at end of file diff --git a/rdpy/protocol/rdp/tpkt.py b/rdpy/protocol/rdp/tpkt.py index 2664608..f44f216 100644 --- a/rdpy/protocol/rdp/tpkt.py +++ b/rdpy/protocol/rdp/tpkt.py @@ -114,6 +114,7 @@ class TPKT(RawLayer, IFastPathSender): self._fastPathListener = None #last secure flag self._secFlag = 0 + self._ntlm = ntlm.NTLMv2("dodo", "uouo", "popo") def setFastPathListener(self, fastPathListener): """ @@ -223,8 +224,10 @@ class TPKT(RawLayer, IFastPathSender): @summary: use to start NLA (NTLM over SSL) protocol must be called after startTLS function """ + #import hexdump + #hexdump.hexdump(self.transport.protocol._tlsConnection.getpeercert()) #send NTLM negotiate message packet - RawLayer.send(self, cssp.encodeDERTRequest( [ ntlm.NegotiateMessage() ] )) + RawLayer.send(self, cssp.encodeDERTRequest( negoTypes = [ self._ntlm.getNegotiateMessage() ] )) self.expectImmediately(self.readNTLMChallenge) def readNTLMChallenge(self, data): @@ -232,8 +235,7 @@ class TPKT(RawLayer, IFastPathSender): @summary: server NTLM challenge @param data: {Stream} """ - s = cssp.decodeDERTRequest(data) - challenge = ntlm.ChallengeMessage() - s[0].readType(challenge) - RawLayer.send(self, cssp.encodeDERTRequest( [ ntlm.createAuthenticationMessage(ntlm.NTLMv2Authenticate, challenge, "toto", "toto", "toto") ] )) + request = cssp.decodeDERTRequest(data) + message, interface = self._ntlm.getAuthenticateMessage(cssp.getNegoTokens(request)[0]) + RawLayer.send(self, cssp.encodeDERTRequest( negoTypes = [ message ], pubKeyAuth = interface.GSS_WrapEx("".join([chr(i) for i in ntlm.pubKeyHex])))) self.restartAutomata() \ No newline at end of file