def macSaltedData(macSaltKey, data, encryptionCount): """ @see: https://msdn.microsoft.com/en-us/library/cc240789.aspx @param macSaltKey: {str} mac key @param data: {str} data to sign @param encryptionCount: nb encrypted packet @return: {str} signature """ sha1Digest = sha.new() md5Digest = md5.new() #encode length dataLengthS = Stream() dataLengthS.writeType(UInt32Le(len(data))) encryptionCountS = Stream() encryptionCountS.writeType(UInt32Le(encryptionCount)) sha1Digest.update(macSaltKey) sha1Digest.update("\x36" * 40) sha1Digest.update(dataLengthS.getvalue()) sha1Digest.update(data) sha1Digest.update(encryptionCountS.getvalue()) sha1Sig = sha1Digest.digest() md5Digest.update(macSaltKey) md5Digest.update("\x5c" * 48) md5Digest.update(sha1Sig) return md5Digest.digest()
def sendClientChallengeResponse(self, platformChallenge): """ @summary: generate valid challenge response @param platformChallenge: {ServerPlatformChallenge} """ serverEncryptedChallenge = platformChallenge.encryptedPlatformChallenge.blobData.value #decrypt server challenge #it should be TEST word in unicode format serverChallenge = rc4.crypt(rc4.RC4Key(self._licenseKey), serverEncryptedChallenge) if serverChallenge != "T\x00E\x00S\x00T\x00\x00\x00": raise InvalidExpectedDataException("bad license server challenge") #generate hwid s = Stream() s.writeType((UInt32Le(2), String(self._hostname + self._username + "\x00" * 16))) hwid = s.getvalue()[:20] message = ClientPLatformChallengeResponse() message.encryptedPlatformChallengeResponse.blobData.value = serverEncryptedChallenge message.encryptedHWID.blobData.value = rc4.crypt( rc4.RC4Key(self._licenseKey), hwid) message.MACData.value = sec.macData(self._macSalt, serverChallenge + hwid) self._transport.sendFlagged(sec.SecurityFlag.SEC_LICENSE_PKT, LicPacket(message))
def writeEncryptedPayload(self, data, saltedMacGeneration): """ @summary: sign and crypt data @param data: {Type} raw stream @param saltedMacGeneration: {bool} use salted mac generation @return: {Tuple} (signature, encryptedData) """ if self._nbEncryptedPacket == 4096: log.debug("update encrypt key") self._currentEncryptKey = updateKey( self._initialEncryptKey, self._currentEncryptKey, self.getGCCServerSettings().SC_SECURITY.encryptionMethod.value) self._encryptRc4 = rc4.RC4Key(self._currentEncryptKey) self._nbEncryptedPacket = 0 self._nbEncryptedPacket += 1 s = Stream() s.writeType(data) if saltedMacGeneration: return (String( macSaltedData(self._macKey, s.getvalue(), self._nbEncryptedPacket - 1)[:8]), String(rc4.crypt(self._encryptRc4, s.getvalue()))) else: return (String(macData(self._macKey, s.getvalue())[:8]), String(rc4.crypt(self._encryptRc4, s.getvalue())))
def macData(macSaltKey, data): """ @see: http://msdn.microsoft.com/en-us/library/cc241995.aspx @param macSaltKey: {str} mac key @param data: {str} data to sign @return: {str} signature """ sha1Digest = sha.new() md5Digest = md5.new() #encode length dataLength = Stream() dataLength.writeType(UInt32Le(len(data))) sha1Digest.update(macSaltKey) sha1Digest.update("\x36" * 40) sha1Digest.update(dataLength.getvalue()) sha1Digest.update(data) sha1Sig = sha1Digest.digest() md5Digest.update(macSaltKey) md5Digest.update("\x5c" * 48) md5Digest.update(sha1Sig) return md5Digest.digest()
def macData(macSaltKey, data): """ @see: http://msdn.microsoft.com/en-us/library/cc241995.aspx @param macSaltKey: {str} mac key @param data: {str} data to sign @return: {str} signature """ sha1Digest = hashlib.sha1() md5Digest = hashlib.md5() #encode length dataLength = Stream() dataLength.writeType(UInt32Le(len(data))) sha1Digest.update(macSaltKey) sha1Digest.update("\x36" * 40) sha1Digest.update(dataLength.getvalue()) sha1Digest.update(data) sha1Sig = sha1Digest.digest() md5Digest.update(macSaltKey) md5Digest.update("\x5c" * 48) md5Digest.update(sha1Sig) return md5Digest.digest()
def encodeDERTRequestOriginal(negoTypes = [], authInfo = None, pubKeyAuth = None): """ @summary: create TSRequest from list of Type @param negoTypes: {list(Type)} @param authInfo: {str} authentication info TSCredentials encrypted with authentication protocol @param pubKeyAuth: {str} public key encrypted with authentication protocol @return: {str} TRequest der encoded """ negoData = NegoData().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1)) #fill nego data tokens i = 0 for negoType in negoTypes: s = Stream() s.writeType(negoType) negoToken = NegoToken() negoToken.setComponentByPosition(0, s.getvalue()) negoData.setComponentByPosition(i, negoToken) i += 1 request = TSRequest() request.setComponentByName("version", univ.Integer(2).subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0))) if i > 0: request.setComponentByName("negoTokens", negoData) if not authInfo is None: request.setComponentByName("authInfo", univ.OctetString(authInfo).subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 2))) if not pubKeyAuth is None: request.setComponentByName("pubKeyAuth", univ.OctetString(pubKeyAuth).subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 3))) return der_encoder.encode(request)
def encodeDERTRequest(negoTypes = [], authInfo = None, pubKeyAuth = None): """ @summary: create TSRequest from list of Type @param negoTypes: {list(Type)} @param authInfo: {str} authentication info TSCredentials encrypted with authentication protocol @param pubKeyAuth: {str} public key encrypted with authentication protocol @return: {str} TRequest der encoded """ negoData = NegoData().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1)) #fill nego data tokens i = 0 for negoType in negoTypes: s = Stream() s.writeType(negoType) negoToken = NegoToken() negoToken.setComponentByPosition(0, s.getvalue()) negoData.setComponentByPosition(i, negoToken) i += 1 request = TSRequest() request.setComponentByName("version", univ.Integer(2).subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0))) if i > 0: request.setComponentByName("negoTokens", negoData) if not authInfo is None: request.setComponentByName("authInfo", univ.OctetString(authInfo).subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 2))) if not pubKeyAuth is None: request.setComponentByName("pubKeyAuth", univ.OctetString(pubKeyAuth).subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 3))) return der_encoder.encode(request)
def macSaltedData(macSaltKey, data, encryptionCount): """ @see: https://msdn.microsoft.com/en-us/library/cc240789.aspx @param macSaltKey: {str} mac key @param data: {str} data to sign @param encryptionCount: nb encrypted packet @return: {str} signature """ sha1Digest = hashlib.sha1() md5Digest = hashlib.md5() #encode length dataLengthS = Stream() dataLengthS.writeType(UInt32Le(len(data))) encryptionCountS = Stream() encryptionCountS.writeType(UInt32Le(encryptionCount)) sha1Digest.update(macSaltKey) sha1Digest.update("\x36" * 40) sha1Digest.update(dataLengthS.getvalue()) sha1Digest.update(data) sha1Digest.update(encryptionCountS.getvalue()) sha1Sig = sha1Digest.digest() md5Digest.update(macSaltKey) md5Digest.update("\x5c" * 48) md5Digest.update(sha1Sig) return md5Digest.digest()
def send(self, message): """ @summary: Send Stream on TCP layer write rdpy Stream message to str And send it to transport layer @param message: (tuple | Type) """ s = Stream() s.writeType(message) self.transport.write(s.getvalue())
def sendConnectResponse(self): """ @summary: Send connect response """ ccReq = gcc.writeConferenceCreateResponse(self._serverSettings) ccReqStream = Stream() ccReqStream.writeType(ccReq) tmp = (ber.writeEnumerated(0), ber.writeInteger(0), self.writeDomainParams(22, 3, 0, 0xfff8), ber.writeOctetstring(ccReqStream.getvalue())) self._transport.send((ber.writeApplicationTag(Message.MCS_TYPE_CONNECT_RESPONSE, sizeof(tmp)), tmp))
def MIC(ExportedSessionKey, negotiateMessage, challengeMessage, authenticateMessage): """ @summary: Compute MIC signature @param negotiateMessage: {NegotiateMessage} @param challengeMessage: {ChallengeMessage} @param authenticateMessage: {AuthenticateMessage} @return: {str} signature @see: https://msdn.microsoft.com/en-us/library/cc236676.aspx """ s = Stream() s.writeType((negotiateMessage, challengeMessage, authenticateMessage)) return HMAC_MD5(ExportedSessionKey, s.getvalue())
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
def writeConferenceCreateRequest(userData): """ @summary: Write conference create request structure @param userData: Settings for client @return: GCC packet """ userDataStream = Stream() userDataStream.writeType(userData) return (per.writeChoice(0), per.writeObjectIdentifier(t124_02_98_oid), per.writeLength(len(userDataStream.getvalue()) + 14), per.writeChoice(0), per.writeSelection(0x08), per.writeNumericString("1", 1), per.writePadding(1), per.writeNumberOfSet(1), per.writeChoice(0xc0), per.writeOctetStream(h221_cs_key, 4), per.writeOctetStream(userDataStream.getvalue()))
def writeConferenceCreateResponse(serverData): """ @summary: Write a conference create response packet @param serverData: Settings for server @return: gcc packet """ serverDataStream = Stream() serverDataStream.writeType(serverData) return (per.writeChoice(0), per.writeObjectIdentifier(t124_02_98_oid), per.writeLength(len(serverDataStream.getvalue()) + 14), per.writeChoice(0x14), per.writeInteger16(0x79F3, 1001), per.writeInteger(1), per.writeEnumerates(0), per.writeNumberOfSet(1), per.writeChoice(0xc0), per.writeOctetStream(h221_sc_key, 4), per.writeOctetStream(serverDataStream.getvalue()))
def sendConnectInitial(self): """ @summary: Send connect initial packet client automata function """ ccReq = gcc.writeConferenceCreateRequest(self._clientSettings) ccReqStream = Stream() ccReqStream.writeType(ccReq) tmp = (ber.writeOctetstring("\x01"), ber.writeOctetstring("\x01"), ber.writeBoolean(True), self.writeDomainParams(34, 2, 0, 0xffff), self.writeDomainParams(1, 1, 1, 0x420), self.writeDomainParams(0xffff, 0xfc17, 0xffff, 0xffff), ber.writeOctetstring(ccReqStream.getvalue())) self._transport.send((ber.writeApplicationTag(Message.MCS_TYPE_CONNECT_INITIAL, sizeof(tmp)), tmp))
def computeSignatureHash(self): """ @summary: compute hash """ s = Stream() s.writeType(UInt32Le(self.__class__._TYPE_)) s.writeType(self.dwSigAlgId) s.writeType(self.dwKeyAlgId) s.writeType(self.wPublicKeyBlobType) s.writeType(self.wPublicKeyBlobLen) s.writeType(self.PublicKeyBlob) md5Digest = md5.new() md5Digest.update(s.getvalue()) return md5Digest.digest() + "\x00" + "\xff" * 45 + "\x01"
def rec(self, event): """ @summary: save event in file @param event: {UpdateEvent} """ now = timeMs() #wrap around event message e = Event(event) #timestamp is time since last event e.timestamp.value = now - self._lastEventTimer self._lastEventTimer = now s = Stream() s.writeType(e) self._file.write(s.getvalue())
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 #write the SeqNum s = Stream() s.writeType(signature.SeqNum) signature.Checksum.value = rc4.crypt(handle, HMAC_MD5(SigningKey, s.getvalue() + Message)[:8]) return signature
def GSS_UnWrapEx(self, data): """ @summary: decrypt data with key exchange in Authentication protocol @param data: {str} """ signature = MessageSignatureEx() message = String() s = Stream(data) s.readType((signature, message)) #decrypt message plaintextMessage = rc4.crypt(self._decryptHandle, message.value) checksum = rc4.crypt(self._decryptHandle, signature.Checksum.value) #recompute checksum t = Stream() t.writeType(signature.SeqNum) verify = HMAC_MD5(self._verifyKey, t.getvalue() + plaintextMessage)[:8] if verify != checksum: raise error.InvalidExpectedDataException("NTLMv2SecurityInterface : Invalid checksum") return plaintextMessage
def writeEncryptedPayload(self, data, saltedMacGeneration): """ @summary: sign and crypt data @param data: {Type} raw stream @param saltedMacGeneration: {bool} use salted mac generation @return: {Tuple} (signature, encryptedData) """ if self._nbEncryptedPacket == 4096: log.debug("update encrypt key") self._currentEncryptKey = updateKey( self._initialEncryptKey, self._currentEncryptKey, self.getGCCServerSettings().SC_SECURITY.encryptionMethod.value) self._encryptRc4 = rc4.RC4Key(self._currentEncryptKey) self._nbEncryptedPacket = 0 self._nbEncryptedPacket += 1 s = Stream() s.writeType(data) if saltedMacGeneration: return (String(macSaltedData(self._macKey, s.getvalue(), self._nbEncryptedPacket - 1)[:8]), String(rc4.crypt(self._encryptRc4, s.getvalue()))) else: return (String(macData(self._macKey, s.getvalue())[:8]), String(rc4.crypt(self._encryptRc4, s.getvalue())))
def sendClientChallengeResponse(self, platformChallenge): """ @summary: generate valid challenge response @param platformChallenge: {ServerPlatformChallenge} """ serverEncryptedChallenge = platformChallenge.encryptedPlatformChallenge.blobData.value #decrypt server challenge #it should be TEST word in unicode format serverChallenge = rc4.crypt(rc4.RC4Key(self._licenseKey), serverEncryptedChallenge) if serverChallenge != "T\x00E\x00S\x00T\x00\x00\x00": raise InvalidExpectedDataException("bad license server challenge") #generate hwid s = Stream() s.writeType((UInt32Le(2), String(self._hostname + self._username + "\x00" * 16))) hwid = s.getvalue()[:20] message = ClientPLatformChallengeResponse() message.encryptedPlatformChallengeResponse.blobData.value = serverEncryptedChallenge message.encryptedHWID.blobData.value = rc4.crypt(rc4.RC4Key(self._licenseKey), hwid) message.MACData.value = sec.macData(self._macSalt, serverChallenge + hwid) self._transport.sendFlagged(sec.SecurityFlag.SEC_LICENSE_PKT, LicPacket(message))