/// <summary> /// Decode Fast-path Update PDU /// </summary> /// <param name="serverSessionContext">server session context</param> /// <param name="data">data to be parsed</param> /// <returns>decoded Fast-path Update PDU</returns> public StackPacket DecodeTsFpInputPDU(RdpbcgrServerSessionContext serverSessionContext, byte[] data) { int currentIndex = 0; TS_FP_INPUT_PDU pdu = new TS_FP_INPUT_PDU(); pdu.fpInputHeader.actionCode = ParseByte(data, ref currentIndex); nested_TS_FP_UPDATE_PDU_fpOutputHeader_actionCode_Values actionCode; byte numberEvents; encryptionFlagsChgd_Values encryptionFlags; GetFpInputHeaderInfo(pdu.fpInputHeader.actionCode, out actionCode, out numberEvents, out encryptionFlags); pdu.length1 = ParseByte(data, ref currentIndex); if ((ConstValue.MOST_SIGNIFICANT_BIT_FILTER & pdu.length1) != pdu.length1) { // length2 is present (since the most significant bit of length1 is set) pdu.length2 = ParseByte(data, ref currentIndex); } // TS_FP_UPDATE_PDU: fipsInformation if (EncryptionLevel.ENCRYPTION_LEVEL_FIPS == serverSessionContext.RdpEncryptionLevel) { pdu.fipsInformation = ParseTsFpFipsInfo(data, ref currentIndex); } // TS_FP_UPDATE_PDU: dataSignature if (IsFlagExist((byte)encryptionFlags, (byte)encryptionFlagsChgd_Values.FASTPATH_OUTPUT_ENCRYPTED)) { // pdu were encrypted, data signature exists pdu.dataSignature = GetBytes(data, ref currentIndex, ConstValue.TS_FP_UPDATE_PDU_DATA_SIGNATURE_LENGTH); } else { pdu.dataSignature = null; } // Decryption bool isSalted = IsFlagExist((byte)encryptionFlags, (byte)encryptionFlagsChgd_Values.FASTPATH_OUTPUT_SECURE_CHECKSUM); byte[] remainData = GetBytes(data, ref currentIndex, (data.Length - currentIndex)); byte[] decryptedData = DecryptFastPathInputData(serverSessionContext, remainData, pdu.dataSignature, isSalted); // Decrypted data index int decryptedDataIndex = 0; //[yunzed] if( numberEvents == 0 ) { Console.WriteLine("numberEvents is 0, so parse the additional numberEvents"); pdu.numberEvents = ParseByte(decryptedData, ref decryptedDataIndex); } // TS_FP_UPDATE_PDU: fpOutputUpdates pdu.fpInputEvents= ParseTsFpInputEvents(decryptedData, ref decryptedDataIndex); // ETW Provider Dump Message if (pdu.dataSignature != null) { // Fast-Path encrypted string messageName = "RDPBCGR:" + pdu.GetType().Name; ExtendedLogger.DumpMessage(messageName, RdpbcgrUtility.DumpLevel_Layer3, pdu.GetType().Name, decryptedData); } // Check if data length exceeded expectation VerifyDataLength(decryptedData.Length, decryptedDataIndex, ConstValue.ERROR_MESSAGE_DATA_LENGTH_EXCEEDED); return pdu; }
/// <summary> /// 2.2.8.1.2 Client Fast-Path Input Event PDU (TS_FP_INPUT_PDU) /// </summary> /// <param name="fpInputPdu"></param> public void VerifyPdu(TS_FP_INPUT_PDU fpInputPdu) { int actionCode; int numberEvents; int encryptionFlags; TS_FP_INPUT_EVENT e; actionCode = fpInputPdu.fpInputHeader.actionCode&0x3; numberEvents = (fpInputPdu.fpInputHeader.actionCode & 0x3c) >> 2; encryptionFlags = (fpInputPdu.fpInputHeader.actionCode & 0xc0) >> 6; CaptureRequirement(actionCode == 0 || actionCode == 3, 1700); if( fpInputPdu.numberEvents != 0 ) { CaptureRequirement(numberEvents == 0, 1704); } if (this.serverConfig.encryptionLevel == EncryptionLevel.ENCRYPTION_LEVEL_FIPS) { site.CaptureRequirementIfAreEqual<TS_FP_FIPS_INFO_length_Values>(TS_FP_FIPS_INFO_length_Values.V1, fpInputPdu.fipsInformation.length, 1713, @"In TS_FP_INPUT_PDU structure, the fipsInformation is present when the Encryption Level " + @"selected by the server is ENCRYPTION_LEVEL_FIPS (4).In TS_FP_INPUT_PDU structure, the" + @" fipsInformation is present when the Encryption Level selected by the server is " + @"ENCRYPTION_LEVEL_FIPS (4)."); } Console.WriteLine("encryptionFlags= " + encryptionFlags); if (fpInputPdu.dataSignature == null) Console.WriteLine("fpInputPdu.dataSignature is null"); if (encryptionFlags == (int)encryptionFlags_Values.FASTPATH_INPUT_ENCRYPTED) { site.CaptureRequirementIfIsNotNull(fpInputPdu.dataSignature, 1715, @"In TS_FP_INPUT_PDU structure, the dataSignature MUST be present if the FASTPATH_INPUT_ENCRYPTED" + @" flag is set in the fpInputHeader field."); } if (numberEvents == 0) { //or fpInputPdu.numberEvents!=0 site.CaptureRequirementIfIsNotNull(fpInputPdu.numberEvents, 1717, @"In TS_FP_INPUT_PDU structure, the numberEvents field is present if the numberEvents bit field in" + @" the fast-path header byte is zero."); } if (fpInputPdu.numberEvents == 0) { site.CaptureRequirementIfAreEqual<int>(numberEvents, fpInputPdu.fpInputEvents.Count, 1718, @"In TS_FP_INPUT_PDU structure, the number of events present in fpInputEvents array is " + @"given by the numberEvents bit field in the fast-path header byte, or by the numberEvents" + @" field in the Fast-Path Input Event PDU (if it is present)."); } else { site.CaptureRequirementIfAreEqual<int>(fpInputPdu.numberEvents, fpInputPdu.fpInputEvents.Count, 1718, @"In TS_FP_INPUT_PDU structure, the number of events present in fpInputEvents array is given" + @" by the numberEvents bit field in the fast-path header byte, or by the numberEvents field " + @"in the Fast-Path Input Event PDU (if it is present)."); } if (this.serverConfig.encryptionLevel == EncryptionLevel.ENCRYPTION_LEVEL_FIPS) { site.CaptureRequirementIfAreEqual<TS_FP_FIPS_INFO_length_Values>(TS_FP_FIPS_INFO_length_Values.V1, fpInputPdu.fipsInformation.length, 1721, @"In TS_FP_FIPS_INFO structure, the length field MUST be set to 0x0010 (16 bytes)."); //ConstValue.TSFIPS_VERSION1 site.CaptureRequirementIfAreEqual<byte>(1, fpInputPdu.fipsInformation.version, 1723, @"In TS_FP_FIPS_INFO structure, the version field SHOULD be set to TSFIPS_VERSION1 (0x01)."); } if( numberEvents == 0 ) numberEvents = fpInputPdu.numberEvents; for (int i = 0; i < fpInputPdu.fpInputEvents.Count; i++) { e = fpInputPdu.fpInputEvents[i]; VerifyStructure(e); } }
/// <summary> /// Create an instance of the class that is identical to the current PDU. /// </summary> /// <returns>The new instance.</returns> public override StackPacket Clone() { TS_FP_INPUT_PDU cloneFpInputPdu = new TS_FP_INPUT_PDU(context); cloneFpInputPdu.dataSignature = RdpbcgrUtility.CloneByteArray(dataSignature); cloneFpInputPdu.fpInputHeader = fpInputHeader; cloneFpInputPdu.length1 = length1; cloneFpInputPdu.length2 = length2; cloneFpInputPdu.numberEvents = numberEvents; cloneFpInputPdu.fipsInformation = fipsInformation; if (fpInputEvents != null) { cloneFpInputPdu.fpInputEvents = new Collection<TS_FP_INPUT_EVENT>(); for (int count = 0; count < fpInputEvents.Count; count++) { cloneFpInputPdu.fpInputEvents.Add(fpInputEvents[count]); } } return cloneFpInputPdu; }